import*as Common from'../common/common.js';import*as SDK from'../sdk/sdk.js';import*as Workspace from'../workspace/workspace.js';import{ContentProviderBasedProject}from'./ContentProviderBasedProject.js';import{DebuggerSourceMapping,DebuggerWorkspaceBinding}from'./DebuggerWorkspaceBinding.js';import{NetworkProject}from'./NetworkProject.js';export class CompilerScriptMapping{constructor(debuggerModel,workspace,debuggerWorkspaceBinding){this._debuggerModel=debuggerModel;this._sourceMapManager=this._debuggerModel.sourceMapManager();this._workspace=workspace;this._debuggerWorkspaceBinding=debuggerWorkspaceBinding;const target=debuggerModel.target();this._regularProject=new ContentProviderBasedProject(workspace,'jsSourceMaps::'+target.id(),Workspace.Workspace.projectTypes.Network,'',false);this._contentScriptsProject=new ContentProviderBasedProject(workspace,'jsSourceMaps:extensions:'+target.id(),Workspace.Workspace.projectTypes.ContentScripts,'',false);NetworkProject.setTargetForProject(this._regularProject,target);NetworkProject.setTargetForProject(this._contentScriptsProject,target);this._regularBindings=new Map();this._contentScriptsBindings=new Map();this._stubUISourceCodes=new Map();this._stubProject=new ContentProviderBasedProject(workspace,'jsSourceMaps:stub:'+target.id(),Workspace.Workspace.projectTypes.Service,'',true);this._eventListeners=[this._sourceMapManager.addEventListener(SDK.SourceMapManager.Events.SourceMapWillAttach,this._sourceMapWillAttach,this),this._sourceMapManager.addEventListener(SDK.SourceMapManager.Events.SourceMapFailedToAttach,this._sourceMapFailedToAttach,this),this._sourceMapManager.addEventListener(SDK.SourceMapManager.Events.SourceMapAttached,this._sourceMapAttached,this),this._sourceMapManager.addEventListener(SDK.SourceMapManager.Events.SourceMapDetached,this._sourceMapDetached,this),];}
_addStubUISourceCode(script){const stubUISourceCode=this._stubProject.addContentProvider(script.sourceURL+':sourcemap',Common.StaticContentProvider.StaticContentProvider.fromString(script.sourceURL,Common.ResourceType.resourceTypes.Script,'\n\n\n\n\n// Please wait a bit.\n// Compiled script is not shown while source map is being loaded!'),'text/javascript');this._stubUISourceCodes.set(script,stubUISourceCode);}
_removeStubUISourceCode(script){const uiSourceCode=this._stubUISourceCodes.get(script);this._stubUISourceCodes.delete(script);this._stubProject.removeFile(uiSourceCode.url());this._debuggerWorkspaceBinding.updateLocations(script);}
static uiSourceCodeOrigin(uiSourceCode){const sourceMap=uiSourceCode[_sourceMapSymbol];if(!sourceMap){return null;}
return sourceMap.compiledURL();}
mapsToSourceCode(rawLocation){const script=rawLocation.script();const sourceMap=script?this._sourceMapManager.sourceMapForClient(script):null;if(!sourceMap){return true;}
const entry=sourceMap.findEntry(rawLocation.lineNumber,rawLocation.columnNumber);return!!entry&&entry.lineNumber===rawLocation.lineNumber&&entry.columnNumber===rawLocation.columnNumber;}
uiSourceCodeForURL(url,isContentScript){return isContentScript?this._contentScriptsProject.uiSourceCodeForURL(url):this._regularProject.uiSourceCodeForURL(url);}
rawLocationToUILocation(rawLocation){const script=rawLocation.script();if(!script){return null;}
const lineNumber=rawLocation.lineNumber-script.lineOffset;let columnNumber=rawLocation.columnNumber;if(!lineNumber){columnNumber-=script.columnOffset;}
const stubUISourceCode=this._stubUISourceCodes.get(script);if(stubUISourceCode){return new Workspace.UISourceCode.UILocation(stubUISourceCode,lineNumber,columnNumber);}
const sourceMap=this._sourceMapManager.sourceMapForClient(script);if(!sourceMap){return null;}
const entry=sourceMap.findEntry(lineNumber,columnNumber);if(!entry||!entry.sourceURL){return null;}
const uiSourceCode=script.isContentScript()?this._contentScriptsProject.uiSourceCodeForURL(entry.sourceURL):this._regularProject.uiSourceCodeForURL(entry.sourceURL);if(!uiSourceCode){return null;}
return uiSourceCode.uiLocation((entry.sourceLineNumber),(entry.sourceColumnNumber));}
uiLocationToRawLocations(uiSourceCode,lineNumber,columnNumber){const sourceMap=uiSourceCode[_sourceMapSymbol];if(!sourceMap){return[];}
const scripts=this._sourceMapManager.clientsForSourceMap(sourceMap);if(!scripts.length){return[];}
const entry=sourceMap.sourceLineMapping(uiSourceCode.url(),lineNumber,columnNumber);if(!entry){return[];}
return scripts.map(script=>this._debuggerModel.createRawLocation(script,entry.lineNumber+script.lineOffset,!entry.lineNumber?entry.columnNumber+script.columnOffset:entry.columnNumber));}
_sourceMapWillAttach(event){const script=(event.data);this._addStubUISourceCode(script);this._debuggerWorkspaceBinding.updateLocations(script);}
_sourceMapFailedToAttach(event){const script=(event.data);this._removeStubUISourceCode(script);}
_sourceMapAttached(event){const script=(event.data.client);const sourceMap=(event.data.sourceMap);this._removeStubUISourceCode(script);if(self.Bindings.blackboxManager.isBlackboxedURL(script.sourceURL,script.isContentScript())){this._sourceMapAttachedForTest(sourceMap);return;}
this._populateSourceMapSources(script,sourceMap);this._sourceMapAttachedForTest(sourceMap);}
_sourceMapDetached(event){const script=(event.data.client);const sourceMap=(event.data.sourceMap);const bindings=script.isContentScript()?this._contentScriptsBindings:this._regularBindings;for(const sourceURL of sourceMap.sourceURLs()){const binding=bindings.get(sourceURL);if(binding){binding.removeSourceMap(sourceMap,script.frameId);if(!binding._uiSourceCode){bindings.delete(sourceURL);}}}
this._debuggerWorkspaceBinding.updateLocations(script);}
sourceMapForScript(script){return this._sourceMapManager.sourceMapForClient(script);}
_sourceMapAttachedForTest(sourceMap){}
_populateSourceMapSources(script,sourceMap){const project=script.isContentScript()?this._contentScriptsProject:this._regularProject;const bindings=script.isContentScript()?this._contentScriptsBindings:this._regularBindings;for(const sourceURL of sourceMap.sourceURLs()){let binding=bindings.get(sourceURL);if(!binding){binding=new Binding(project,sourceURL);bindings.set(sourceURL,binding);}
binding.addSourceMap(sourceMap,script.frameId);}
this._debuggerWorkspaceBinding.updateLocations(script);}
static uiLineHasMapping(uiSourceCode,lineNumber){const sourceMap=uiSourceCode[_sourceMapSymbol];if(!sourceMap){return true;}
return!!sourceMap.sourceLineMapping(uiSourceCode.url(),lineNumber,0);}
dispose(){Common.EventTarget.EventTarget.removeEventListeners(this._eventListeners);this._regularProject.dispose();this._contentScriptsProject.dispose();this._stubProject.dispose();}}
const _sourceMapSymbol=Symbol('_sourceMapSymbol');class Binding{constructor(project,url){this._project=project;this._url=url;this._referringSourceMaps=[];this._activeSourceMap=null;this._uiSourceCode=null;}
_recreateUISourceCodeIfNeeded(frameId){const sourceMap=this._referringSourceMaps.peekLast();if(this._activeSourceMap===sourceMap){return;}
this._activeSourceMap=sourceMap;const newUISourceCode=this._project.createUISourceCode(this._url,Common.ResourceType.resourceTypes.SourceMapScript);newUISourceCode[_sourceMapSymbol]=sourceMap;const contentProvider=sourceMap.sourceContentProvider(this._url,Common.ResourceType.resourceTypes.SourceMapScript);const mimeType=Common.ResourceType.ResourceType.mimeFromURL(this._url)||'text/javascript';const embeddedContent=sourceMap.embeddedContentByURL(this._url);const metadata=typeof embeddedContent==='string'?new Workspace.UISourceCode.UISourceCodeMetadata(null,embeddedContent.length):null;if(this._uiSourceCode){NetworkProject.cloneInitialFrameAttribution(this._uiSourceCode,newUISourceCode);this._project.removeFile(this._uiSourceCode.url());}else{NetworkProject.setInitialFrameAttribution(newUISourceCode,frameId);}
this._uiSourceCode=newUISourceCode;this._project.addUISourceCodeWithProvider(this._uiSourceCode,contentProvider,metadata,mimeType);}
addSourceMap(sourceMap,frameId){if(this._uiSourceCode){NetworkProject.addFrameAttribution(this._uiSourceCode,frameId);}
this._referringSourceMaps.push(sourceMap);this._recreateUISourceCodeIfNeeded(frameId);}
removeSourceMap(sourceMap,frameId){NetworkProject.removeFrameAttribution((this._uiSourceCode),frameId);const lastIndex=this._referringSourceMaps.lastIndexOf(sourceMap);if(lastIndex!==-1){this._referringSourceMaps.splice(lastIndex,1);}
if(!this._referringSourceMaps.length){this._project.removeFile(this._uiSourceCode.url());this._uiSourceCode=null;}else{this._recreateUISourceCodeIfNeeded(frameId);}}}