SourceMapManager.js 5.4 KB

12345678910111213141516171819202122232425262728293031
  1. export default class SourceMapManager extends Common.Object{constructor(target){super();this._target=target;this._isEnabled=true;this._relativeSourceURL=new Map();this._relativeSourceMapURL=new Map();this._resolvedSourceMapId=new Map();this._sourceMapById=new Map();this._sourceMapIdToLoadingClients=new Platform.Multimap();this._sourceMapIdToClients=new Platform.Multimap();SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged,this._inspectedURLChanged,this);}
  2. setEnabled(isEnabled){if(isEnabled===this._isEnabled){return;}
  3. this._isEnabled=isEnabled;const clients=[...this._resolvedSourceMapId.keys()];for(const client of clients){const relativeSourceURL=this._relativeSourceURL.get(client);const relativeSourceMapURL=this._relativeSourceMapURL.get(client);this.detachSourceMap(client);this.attachSourceMap(client,relativeSourceURL,relativeSourceMapURL);}}
  4. _inspectedURLChanged(event){if(event.data!==this._target){return;}
  5. const prevSourceMapIds=new Map(this._resolvedSourceMapId);for(const[client,prevSourceMapId]of prevSourceMapIds){const relativeSourceURL=this._relativeSourceURL.get(client);const relativeSourceMapURL=this._relativeSourceMapURL.get(client);const{sourceMapId}=this._resolveRelativeURLs(relativeSourceURL,relativeSourceMapURL);if(prevSourceMapId!==sourceMapId){this.detachSourceMap(client);this.attachSourceMap(client,relativeSourceURL,relativeSourceMapURL);}}}
  6. sourceMapForClient(client){const sourceMapId=this._resolvedSourceMapId.get(client);if(!sourceMapId){return null;}
  7. return this._sourceMapById.get(sourceMapId)||null;}
  8. clientsForSourceMap(sourceMap){const sourceMapId=this._getSourceMapId(sourceMap.compiledURL(),sourceMap.url());if(this._sourceMapIdToClients.has(sourceMapId)){return this._sourceMapIdToClients.get(sourceMapId).valuesArray();}
  9. return this._sourceMapIdToLoadingClients.get(sourceMapId).valuesArray();}
  10. _getSourceMapId(sourceURL,sourceMapURL){return`${sourceURL}:${sourceMapURL}`;}
  11. _resolveRelativeURLs(sourceURL,sourceMapURL){const resolvedSourceURL=Common.ParsedURL.completeURL(this._target.inspectedURL(),sourceURL);if(!resolvedSourceURL){return null;}
  12. const resolvedSourceMapURL=Common.ParsedURL.completeURL(resolvedSourceURL,sourceMapURL);if(!resolvedSourceMapURL){return null;}
  13. return{sourceURL:resolvedSourceURL,sourceMapURL:resolvedSourceMapURL,sourceMapId:this._getSourceMapId(resolvedSourceURL,resolvedSourceMapURL)};}
  14. attachSourceMap(client,relativeSourceURL,relativeSourceMapURL){if(!relativeSourceMapURL){return;}
  15. console.assert(!this._resolvedSourceMapId.has(client),'SourceMap is already attached to client');const resolvedURLs=this._resolveRelativeURLs(relativeSourceURL,relativeSourceMapURL);if(!resolvedURLs){return;}
  16. this._relativeSourceURL.set(client,relativeSourceURL);this._relativeSourceMapURL.set(client,relativeSourceMapURL);const{sourceURL,sourceMapURL,sourceMapId}=resolvedURLs;this._resolvedSourceMapId.set(client,sourceMapId);if(!this._isEnabled){return;}
  17. this.dispatchEventToListeners(Events.SourceMapWillAttach,client);if(this._sourceMapById.has(sourceMapId)){attach.call(this,sourceMapId,client);return;}
  18. if(!this._sourceMapIdToLoadingClients.has(sourceMapId)){const sourceMapPromise=sourceMapURL===SDK.WasmSourceMap.FAKE_URL?SDK.WasmSourceMap.load(client,sourceURL):SDK.TextSourceMap.load(sourceMapURL,sourceURL);sourceMapPromise.catch(e=>{Common.console.warn('DevTools failed to parse SourceMap: '+sourceMapURL);}).then(onSourceMap.bind(this,sourceMapId));}
  19. this._sourceMapIdToLoadingClients.set(sourceMapId,client);function onSourceMap(sourceMapId,sourceMap){this._sourceMapLoadedForTest();const clients=this._sourceMapIdToLoadingClients.get(sourceMapId);this._sourceMapIdToLoadingClients.deleteAll(sourceMapId);if(!clients.size){return;}
  20. if(!sourceMap){for(const client of clients){this.dispatchEventToListeners(Events.SourceMapFailedToAttach,client);}
  21. return;}
  22. this._sourceMapById.set(sourceMapId,sourceMap);for(const client of clients){attach.call(this,sourceMapId,client);}}
  23. function attach(sourceMapId,client){this._sourceMapIdToClients.set(sourceMapId,client);const sourceMap=this._sourceMapById.get(sourceMapId);this.dispatchEventToListeners(Events.SourceMapAttached,{client:client,sourceMap:sourceMap});}}
  24. detachSourceMap(client){const sourceMapId=this._resolvedSourceMapId.get(client);this._relativeSourceURL.delete(client);this._relativeSourceMapURL.delete(client);this._resolvedSourceMapId.delete(client);if(!sourceMapId){return;}
  25. if(!this._sourceMapIdToClients.hasValue(sourceMapId,client)){if(this._sourceMapIdToLoadingClients.delete(sourceMapId,client)){this.dispatchEventToListeners(Events.SourceMapFailedToAttach,client);}
  26. return;}
  27. this._sourceMapIdToClients.delete(sourceMapId,client);const sourceMap=this._sourceMapById.get(sourceMapId);this.dispatchEventToListeners(Events.SourceMapDetached,{client:client,sourceMap:sourceMap});if(!this._sourceMapIdToClients.has(sourceMapId)){sourceMap.dispose();this._sourceMapById.delete(sourceMapId);}}
  28. _sourceMapLoadedForTest(){}
  29. dispose(){for(const sourceMap of this._sourceMapById.values()){sourceMap.dispose();}
  30. SDK.targetManager.removeEventListener(SDK.TargetManager.Events.InspectedURLChanged,this._inspectedURLChanged,this);}}
  31. export const Events={SourceMapWillAttach:Symbol('SourceMapWillAttach'),SourceMapFailedToAttach:Symbol('SourceMapFailedToAttach'),SourceMapAttached:Symbol('SourceMapAttached'),SourceMapDetached:Symbol('SourceMapDetached'),SourceMapChanged:Symbol('SourceMapChanged')};self.SDK=self.SDK||{};SDK=SDK||{};SDK.SourceMapManager=SourceMapManager;SDK.SourceMapManager.Events=Events;