let id=0;function nextId(prefix){return(prefix||'')+ ++id;}
SDKTestRunner.connectToPage=function(targetName,pageMock,makeMainTarget){const mockTarget=SDK.targetManager.createTarget(nextId('mock-target-'),targetName,pageMock.capabilities(),params=>pageMock.createConnection(params));if(makeMainTarget){SDK.targetManager._targets=SDK.targetManager._targets.filter(target=>target!==mockTarget);SDK.targetManager._targets.unshift(mockTarget);}
return mockTarget;};SDKTestRunner.PageMock=class{constructor(url){this._url=url;this._capabilities=SDK.Target.Capability.DOM|SDK.Target.Capability.JS|SDK.Target.Capability.Browser;this._enabledDomains=new Set();this._mainFrame={id:nextId(),loaderId:nextId(),mimeType:'text/html',securityOrigin:this._url,url:this._url};this._executionContexts=[];this._executionContexts.push(this._createExecutionContext(this._mainFrame,false));this._scripts=[];this._scriptContents=new Map();this._dispatchMap={'Debugger.enable':this._debuggerEnable,'Debugger.getScriptSource':this._debuggerGetScriptSource,'Debugger.setBlackboxPatterns':(id,params)=>this._sendResponse(id,{}),'Runtime.enable':this._runtimeEnable,'Page.enable':this._pageEnable,'Page.getResourceTree':this._pageGetResourceTree};}
capabilities(){return this._capabilities;}
disableDOMCapability(){this._capabilities=this._capabilities&~SDK.Target.Capability.DOM;}
createConnection(params){this._enabledDomains.clear();this._connection=new MockPageConnection(this,params);return this._connection;}
evalScript(url,content,isContentScript){const id=nextId();content+='\n//# sourceURL='+url;this._scriptContents.set(id,content);let context=this._executionContexts.find(context=>context.auxData.isDefault!==isContentScript);if(!context){context=this._createExecutionContext(this._mainFrame,isContentScript);this._fireEvent('Runtime.executionContextCreated',{context:context});}
const text=new TextUtils.Text(content);const script={scriptId:id,url:url,startLine:0,startColumn:0,endLine:text.lineCount(),endColumn:text.lineAt(text.lineCount()).length-1,executionContextId:context.id,hash:String.hashCode(content),executionContextAuxData:context.auxData,sourceMapURL:'',hasSourceURL:true,isLiveEdit:false,isModule:false,length:content.length};this._scripts.push(script);this._fireEvent('Debugger.scriptParsed',script);}
reload(){this._fireEvent('Page.frameStartedLoading',{frameId:this._mainFrame.id});for(const context of this._executionContexts)
this._fireEvent('Runtime.executionContextDestroyed',{executionContextId:context.id});this._scripts=[];this._scriptContents.clear();this._executionContexts=[];this._fireEvent('Runtime.executionContextsCleared',{});this._executionContexts.push(this._createExecutionContext(this._mainFrame,false));for(const context of this._executionContexts)
this._fireEvent('Runtime.executionContextCreated',{context:context});this._fireEvent('Page.frameNavigated',{frame:this._mainFrame});this._fireEvent('Page.loadEventFired',{timestamp:Date.now()/1000});this._fireEvent('Page.frameStoppedLoading',{frameId:this._mainFrame.id});this._fireEvent('Page.domContentEventFired',{timestamp:Date.now()/1000});}
close(){if(this._connection){this._connection.disconnect();this._connection=null;}}
_createExecutionContext(frame,isContentScript){return{id:nextId(),auxData:{isDefault:!isContentScript,frameId:frame.id},origin:frame.securityOrigin,name:''};}
_debuggerEnable(id,params){this._enabledDomains.add('Debugger');this._sendResponse(id,{});for(const script of this._scripts)
this._fireEvent('Debugger.scriptParsed',script);}
_debuggerGetScriptSource(id,params){if(!this._scriptContents.has(params.scriptId)){this._sendResponse(id,undefined,{message:'Can\'t get script content for id '+params.scriptId,code:1});return;}
const result={scriptSource:this._scriptContents.get(params.scriptId)};this._sendResponse(id,result);}
_runtimeEnable(id,params){this._enabledDomains.add('Runtime');this._sendResponse(id,{});for(const context of this._executionContexts)
this._fireEvent('Runtime.executionContextCreated',{context:context});}
_pageEnable(id,params){this._enabledDomains.add('Page');this._sendResponse(id,{});}
_pageGetResourceTree(id,params){const result={frameTree:{frame:this._mainFrame,resources:[]}};this._sendResponse(id,result);}
_isSupportedDomain(methodName){const domain=methodName.split('.')[0];if(domain==='Page')
return!!(this._capabilities&SDK.Target.Capability.DOM);return true;}
_dispatch(id,methodName,params,message){const handler=(this._isSupportedDomain(methodName)?this._dispatchMap[methodName]:null);if(handler)
return handler.call(this,id,params);this._sendResponse(id,undefined,{message:'Can\'t handle command '+methodName,code:Protocol.InspectorBackend.DevToolsStubErrorCode});}
_sendResponse(id,result,error){const message={id:id,result:result,error:error};this._connection.sendMessageToDevTools(message);}
_fireEvent(methodName,params){const domain=methodName.split('.')[0];if(!this._enabledDomains.has(domain))
return;const message={method:methodName,params:params};this._connection.sendMessageToDevTools(message);}};MockPageConnection=class{constructor(page,params){this._page=page;this._onMessage=params.onMessage;this._onDisconnect=params.onDisconnect;}
sendMessageToDevTools(message){setTimeout(()=>this._onMessage.call(null,JSON.stringify(message)),0);}
sendMessage(message){const json=JSON.parse(message);this._page._dispatch(json.id,json.method,json.params,message);}
disconnect(){this._onDisconnect.call(null,'force disconnect');this._onDisconnect=null;this._onMessage=null;return Promise.resolve();}};;