BlackboxManager.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. export default class BlackboxManager{constructor(debuggerWorkspaceBinding){this._debuggerWorkspaceBinding=debuggerWorkspaceBinding;SDK.targetManager.addModelListener(SDK.DebuggerModel,SDK.DebuggerModel.Events.GlobalObjectCleared,this._clearCacheIfNeeded.bind(this),this);Common.moduleSetting('skipStackFramesPattern').addChangeListener(this._patternChanged.bind(this));Common.moduleSetting('skipContentScripts').addChangeListener(this._patternChanged.bind(this));this._listeners=new Set();this._isBlackboxedURLCache=new Map();SDK.targetManager.observeModels(SDK.DebuggerModel,this);}
  2. addChangeListener(listener){this._listeners.add(listener);}
  3. removeChangeListener(listener){this._listeners.delete(listener);}
  4. modelAdded(debuggerModel){this._setBlackboxPatterns(debuggerModel);const sourceMapManager=debuggerModel.sourceMapManager();sourceMapManager.addEventListener(SDK.SourceMapManager.Events.SourceMapAttached,this._sourceMapAttached,this);sourceMapManager.addEventListener(SDK.SourceMapManager.Events.SourceMapDetached,this._sourceMapDetached,this);}
  5. modelRemoved(debuggerModel){this._clearCacheIfNeeded();const sourceMapManager=debuggerModel.sourceMapManager();sourceMapManager.removeEventListener(SDK.SourceMapManager.Events.SourceMapAttached,this._sourceMapAttached,this);sourceMapManager.removeEventListener(SDK.SourceMapManager.Events.SourceMapDetached,this._sourceMapDetached,this);}
  6. _clearCacheIfNeeded(){if(this._isBlackboxedURLCache.size>1024){this._isBlackboxedURLCache.clear();}}
  7. _setBlackboxPatterns(debuggerModel){const regexPatterns=Common.moduleSetting('skipStackFramesPattern').getAsArray();const patterns=([]);for(const item of regexPatterns){if(!item.disabled&&item.pattern){patterns.push(item.pattern);}}
  8. return debuggerModel.setBlackboxPatterns(patterns);}
  9. isBlackboxedUISourceCode(uiSourceCode){const projectType=uiSourceCode.project().type();const isContentScript=projectType===Workspace.projectTypes.ContentScripts;if(isContentScript&&Common.moduleSetting('skipContentScripts').get()){return true;}
  10. const url=this._uiSourceCodeURL(uiSourceCode);return url?this.isBlackboxedURL(url):false;}
  11. isBlackboxedURL(url,isContentScript){if(this._isBlackboxedURLCache.has(url)){return!!this._isBlackboxedURLCache.get(url);}
  12. if(isContentScript&&Common.moduleSetting('skipContentScripts').get()){return true;}
  13. const regex=Common.moduleSetting('skipStackFramesPattern').asRegExp();const isBlackboxed=(regex&&regex.test(url))||false;this._isBlackboxedURLCache.set(url,isBlackboxed);return isBlackboxed;}
  14. _sourceMapAttached(event){const script=(event.data.client);const sourceMap=(event.data.sourceMap);this._updateScriptRanges(script,sourceMap);}
  15. _sourceMapDetached(event){const script=(event.data.client);this._updateScriptRanges(script,null);}
  16. async _updateScriptRanges(script,sourceMap){let hasBlackboxedMappings=false;if(!Bindings.blackboxManager.isBlackboxedURL(script.sourceURL,script.isContentScript())){hasBlackboxedMappings=sourceMap?sourceMap.sourceURLs().some(url=>this.isBlackboxedURL(url)):false;}
  17. if(!hasBlackboxedMappings){if(script[_blackboxedRanges]&&await script.setBlackboxedRanges([])){delete script[_blackboxedRanges];}
  18. this._debuggerWorkspaceBinding.updateLocations(script);return;}
  19. const mappings=sourceMap.mappings();const newRanges=[];let currentBlackboxed=false;if(mappings[0].lineNumber!==0||mappings[0].columnNumber!==0){newRanges.push({lineNumber:0,columnNumber:0});currentBlackboxed=true;}
  20. for(const mapping of mappings){if(mapping.sourceURL&&currentBlackboxed!==this.isBlackboxedURL(mapping.sourceURL)){newRanges.push({lineNumber:mapping.lineNumber,columnNumber:mapping.columnNumber});currentBlackboxed=!currentBlackboxed;}}
  21. const oldRanges=script[_blackboxedRanges]||[];if(!isEqual(oldRanges,newRanges)&&await script.setBlackboxedRanges(newRanges)){script[_blackboxedRanges]=newRanges;}
  22. this._debuggerWorkspaceBinding.updateLocations(script);function isEqual(rangesA,rangesB){if(rangesA.length!==rangesB.length){return false;}
  23. for(let i=0;i<rangesA.length;++i){if(rangesA[i].lineNumber!==rangesB[i].lineNumber||rangesA[i].columnNumber!==rangesB[i].columnNumber){return false;}}
  24. return true;}}
  25. _uiSourceCodeURL(uiSourceCode){return uiSourceCode.project().type()===Workspace.projectTypes.Debugger?null:uiSourceCode.url();}
  26. canBlackboxUISourceCode(uiSourceCode){const url=this._uiSourceCodeURL(uiSourceCode);return url?!!this._urlToRegExpString(url):false;}
  27. blackboxUISourceCode(uiSourceCode){const url=this._uiSourceCodeURL(uiSourceCode);if(url){this._blackboxURL(url);}}
  28. unblackboxUISourceCode(uiSourceCode){const url=this._uiSourceCodeURL(uiSourceCode);if(url){this._unblackboxURL(url);}}
  29. blackboxContentScripts(){Common.moduleSetting('skipContentScripts').set(true);}
  30. unblackboxContentScripts(){Common.moduleSetting('skipContentScripts').set(false);}
  31. _blackboxURL(url){const regexPatterns=Common.moduleSetting('skipStackFramesPattern').getAsArray();const regexValue=this._urlToRegExpString(url);if(!regexValue){return;}
  32. let found=false;for(let i=0;i<regexPatterns.length;++i){const item=regexPatterns[i];if(item.pattern===regexValue){item.disabled=false;found=true;break;}}
  33. if(!found){regexPatterns.push({pattern:regexValue});}
  34. Common.moduleSetting('skipStackFramesPattern').setAsArray(regexPatterns);}
  35. _unblackboxURL(url){let regexPatterns=Common.moduleSetting('skipStackFramesPattern').getAsArray();const regexValue=Bindings.blackboxManager._urlToRegExpString(url);if(!regexValue){return;}
  36. regexPatterns=regexPatterns.filter(function(item){return item.pattern!==regexValue;});for(let i=0;i<regexPatterns.length;++i){const item=regexPatterns[i];if(item.disabled){continue;}
  37. try{const regex=new RegExp(item.pattern);if(regex.test(url)){item.disabled=true;}}catch(e){}}
  38. Common.moduleSetting('skipStackFramesPattern').setAsArray(regexPatterns);}
  39. async _patternChanged(){this._isBlackboxedURLCache.clear();const promises=[];for(const debuggerModel of SDK.targetManager.models(SDK.DebuggerModel)){promises.push(this._setBlackboxPatterns(debuggerModel));const sourceMapManager=debuggerModel.sourceMapManager();for(const script of debuggerModel.scripts()){promises.push(this._updateScriptRanges(script,sourceMapManager.sourceMapForClient(script)));}}
  40. await Promise.all(promises);const listeners=Array.from(this._listeners);for(const listener of listeners){listener();}
  41. this._patternChangeFinishedForTests();}
  42. _patternChangeFinishedForTests(){}
  43. _urlToRegExpString(url){const parsedURL=new Common.ParsedURL(url);if(parsedURL.isAboutBlank()||parsedURL.isDataURL()){return'';}
  44. if(!parsedURL.isValid){return'^'+url.escapeForRegExp()+'$';}
  45. let name=parsedURL.lastPathComponent;if(name){name='/'+name;}else if(parsedURL.folderPathComponents){name=parsedURL.folderPathComponents+'/';}
  46. if(!name){name=parsedURL.host;}
  47. if(!name){return'';}
  48. const scheme=parsedURL.scheme;let prefix='';if(scheme&&scheme!=='http'&&scheme!=='https'){prefix='^'+scheme+'://';if(scheme==='chrome-extension'){prefix+=parsedURL.host+'\\b';}
  49. prefix+='.*';}
  50. return prefix+name.escapeForRegExp()+(url.endsWith(name)?'$':'\\b');}}
  51. const _blackboxedRanges=Symbol('blackboxedRanged');self.Bindings=self.Bindings||{};Bindings=Bindings||{};Bindings.BlackboxManager=BlackboxManager;Bindings.blackboxManager;