| Index: third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
|
| index 48e86cc5bd6ce29222c7556cb670e19228ae705c..5f1bc8693a2ef6dea6d97f0364737d06b8966dc3 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
|
| @@ -40,6 +40,11 @@ Bindings.ResourceScriptMapping = class {
|
| constructor(debuggerModel, workspace, debuggerWorkspaceBinding) {
|
| this._debuggerModel = debuggerModel;
|
| this._workspace = workspace;
|
| + /** @type {!Map<string, !Bindings.ContentProviderBasedProject>} */
|
| + this._workspaceProjects = new Map();
|
| + /** @type {!Set<!SDK.Script>} */
|
| + this._acceptedScripts = new Set();
|
| +
|
| this._debuggerWorkspaceBinding = debuggerWorkspaceBinding;
|
| /** @type {!Set<!Workspace.UISourceCode>} */
|
| this._boundUISourceCodes = new Set();
|
| @@ -47,35 +52,47 @@ Bindings.ResourceScriptMapping = class {
|
| /** @type {!Map.<!Workspace.UISourceCode, !Bindings.ResourceScriptFile>} */
|
| this._uiSourceCodeToScriptFile = new Map();
|
|
|
| + var runtimeModel = this._debuggerModel.runtimeModel();
|
| this._eventListeners = [
|
| + runtimeModel.addEventListener(
|
| + SDK.RuntimeModel.Events.ExecutionContextDestroyed, this._executionContextDestroyed, this),
|
| debuggerModel.addEventListener(SDK.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this),
|
| debuggerModel.addEventListener(SDK.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this),
|
| debuggerModel.addEventListener(
|
| SDK.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this),
|
| - workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this),
|
| - workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this)
|
| ];
|
| }
|
|
|
| + /**
|
| + * @param {!SDK.Target} target
|
| + * @param {string} frameId
|
| + * @param {boolean} isContentScripts
|
| + * @return {string}
|
| + */
|
| + static projectId(target, frameId, isContentScripts) {
|
| + return target.id() + ':' + frameId + ':' + (isContentScripts ? 'contentscripts' : '');
|
| + }
|
| +
|
| /**
|
| * @override
|
| * @param {!SDK.DebuggerModel.Location} rawLocation
|
| * @return {?Workspace.UILocation}
|
| */
|
| rawLocationToUILocation(rawLocation) {
|
| - var debuggerModelLocation = /** @type {!SDK.DebuggerModel.Location} */ (rawLocation);
|
| - var script = debuggerModelLocation.script();
|
| - if (!script)
|
| + var script = rawLocation.script();
|
| + if (!script || !this._acceptsScript(script))
|
| return null;
|
| - var uiSourceCode = this._workspaceUISourceCodeForScript(script);
|
| + var frameId = script[Bindings.ResourceScriptMapping._frameIdSymbol];
|
| + var project = this._workspaceProject(frameId, script.isContentScript());
|
| + var uiSourceCode = project.uiSourceCodeForURL(script.contentURL());
|
| if (!uiSourceCode)
|
| return null;
|
| var scriptFile = this.scriptFile(uiSourceCode);
|
| if (scriptFile &&
|
| ((scriptFile.hasDivergedFromVM() && !scriptFile.isMergingToVM()) || scriptFile.isDivergingFromVM()))
|
| return null;
|
| - var lineNumber = debuggerModelLocation.lineNumber - (script.isInlineScriptWithSourceURL() ? script.lineOffset : 0);
|
| - var columnNumber = debuggerModelLocation.columnNumber || 0;
|
| + var lineNumber = rawLocation.lineNumber - (script.isInlineScriptWithSourceURL() ? script.lineOffset : 0);
|
| + var columnNumber = rawLocation.columnNumber || 0;
|
| if (script.isInlineScriptWithSourceURL() && !lineNumber && columnNumber)
|
| columnNumber -= script.columnOffset;
|
| return uiSourceCode.uiLocation(lineNumber, columnNumber);
|
| @@ -89,10 +106,10 @@ Bindings.ResourceScriptMapping = class {
|
| * @return {?SDK.DebuggerModel.Location}
|
| */
|
| uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber) {
|
| - var scripts = this._scriptsForUISourceCode(uiSourceCode);
|
| - if (!scripts.length)
|
| + var scriptFile = this.scriptFile(uiSourceCode);
|
| + if (!scriptFile)
|
| return null;
|
| - var script = scripts[scripts.length - 1];
|
| + var script = scriptFile._script;
|
| if (script.isInlineScriptWithSourceURL()) {
|
| return this._debuggerModel.createRawLocationByURL(
|
| script.sourceURL, lineNumber + script.lineOffset,
|
| @@ -102,113 +119,83 @@ Bindings.ResourceScriptMapping = class {
|
| }
|
|
|
| /**
|
| - * @param {!Common.Event} event
|
| - */
|
| - _parsedScriptSource(event) {
|
| - var script = /** @type {!SDK.Script} */ (event.data);
|
| - if (script.isAnonymousScript())
|
| - return;
|
| -
|
| - var uiSourceCode = this._workspaceUISourceCodeForScript(script);
|
| - if (!uiSourceCode)
|
| - return;
|
| -
|
| - this._bindUISourceCodeToScripts(uiSourceCode, [script]);
|
| - }
|
| -
|
| - /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| - * @return {?Bindings.ResourceScriptFile}
|
| - */
|
| - scriptFile(uiSourceCode) {
|
| - return this._uiSourceCodeToScriptFile.get(uiSourceCode) || null;
|
| - }
|
| -
|
| - /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| - * @param {?Bindings.ResourceScriptFile} scriptFile
|
| - */
|
| - _setScriptFile(uiSourceCode, scriptFile) {
|
| - if (scriptFile)
|
| - this._uiSourceCodeToScriptFile.set(uiSourceCode, scriptFile);
|
| - else
|
| - this._uiSourceCodeToScriptFile.remove(uiSourceCode);
|
| - }
|
| -
|
| - /**
|
| - * @param {!Common.Event} event
|
| + * @param {!SDK.Script} script
|
| + * @return {boolean}
|
| */
|
| - _uiSourceCodeAdded(event) {
|
| - var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
|
| - if (uiSourceCode.project().isServiceProject())
|
| - return;
|
| - var scripts = this._scriptsForUISourceCode(uiSourceCode);
|
| - if (!scripts.length)
|
| - return;
|
| -
|
| - this._bindUISourceCodeToScripts(uiSourceCode, scripts);
|
| + _acceptsScript(script) {
|
| + if (!script.sourceURL || script.isLiveEdit() || (script.isInlineScript() && !script.hasSourceURL))
|
| + return false;
|
| + // Filter out embedder injected content scripts.
|
| + if (script.isContentScript() && !script.hasSourceURL) {
|
| + var parsedURL = new Common.ParsedURL(script.sourceURL);
|
| + if (!parsedURL.isValid)
|
| + return false;
|
| + }
|
| + return true;
|
| }
|
|
|
| /**
|
| * @param {!Common.Event} event
|
| */
|
| - _uiSourceCodeRemoved(event) {
|
| - var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
|
| - if (uiSourceCode.project().isServiceProject() || !this._boundUISourceCodes.has(uiSourceCode))
|
| + _parsedScriptSource(event) {
|
| + var script = /** @type {!SDK.Script} */ (event.data);
|
| + if (!this._acceptsScript(script))
|
| return;
|
| + this._acceptedScripts.add(script);
|
| + var originalContentProvider = script.originalContentProvider();
|
| + var frameId = Bindings.frameIdForScript(script);
|
| + script[Bindings.ResourceScriptMapping._frameIdSymbol] = frameId;
|
| +
|
| + var project = this._workspaceProject(frameId, script.isContentScript());
|
| + var uiSourceCode = project.uiSourceCodeForURL(script.contentURL());
|
| + if (uiSourceCode)
|
| + this._unbindUISourceCode(uiSourceCode);
|
| + uiSourceCode = project.createUISourceCode(script.contentURL(), originalContentProvider.contentType());
|
| + if (frameId)
|
| + Bindings.NetworkProject.setInitialFrameAttribution(uiSourceCode, frameId);
|
|
|
| - this._unbindUISourceCode(uiSourceCode);
|
| - }
|
| + var scriptFile = new Bindings.ResourceScriptFile(this, uiSourceCode, script);
|
| + this._uiSourceCodeToScriptFile.set(uiSourceCode, scriptFile);
|
| + this._debuggerWorkspaceBinding.updateLocations(script);
|
| + this._boundUISourceCodes.add(uiSourceCode);
|
|
|
| - /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| - */
|
| - _updateLocations(uiSourceCode) {
|
| - var scripts = this._scriptsForUISourceCode(uiSourceCode);
|
| - if (!scripts.length)
|
| - return;
|
| - for (var i = 0; i < scripts.length; ++i)
|
| - this._debuggerWorkspaceBinding.updateLocations(scripts[i]);
|
| + var metadata = Bindings.metadataForURL(this._debuggerModel.target(), frameId, uiSourceCode.url());
|
| + project.addUISourceCodeWithProvider(uiSourceCode, originalContentProvider, metadata, 'text/javascript');
|
| }
|
|
|
| /**
|
| - * @param {!SDK.Script} script
|
| - * @return {?Workspace.UISourceCode}
|
| + * @param {string} frameId
|
| + * @param {boolean} isContentScripts
|
| + * @return {!Bindings.ContentProviderBasedProject}
|
| */
|
| - _workspaceUISourceCodeForScript(script) {
|
| - if (script.isAnonymousScript())
|
| - return null;
|
| - return Bindings.NetworkProject.uiSourceCodeForScriptURL(this._workspace, script.sourceURL, script);
|
| + _workspaceProject(frameId, isContentScripts) {
|
| + var projectId = Bindings.ResourceScriptMapping.projectId(this._debuggerModel.target(), frameId, isContentScripts);
|
| + var projectType = isContentScripts ? Workspace.projectTypes.ContentScripts : Workspace.projectTypes.Network;
|
| +
|
| + var project = this._workspaceProjects.get(projectId);
|
| + if (project)
|
| + return project;
|
| +
|
| + project = new Bindings.ContentProviderBasedProject(
|
| + this._workspace, projectId, projectType, '', false /* isServiceProject */);
|
| + Bindings.NetworkProject.setTargetForProject(project, this._debuggerModel.target());
|
| + this._workspaceProjects.set(projectId, project);
|
| + return project;
|
| }
|
|
|
| /**
|
| * @param {!Workspace.UISourceCode} uiSourceCode
|
| - * @return {!Array.<!SDK.Script>}
|
| + * @return {?Bindings.ResourceScriptFile}
|
| */
|
| - _scriptsForUISourceCode(uiSourceCode) {
|
| - var target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode);
|
| - if (target !== this._debuggerModel.target())
|
| - return [];
|
| - return this._debuggerModel.scriptsForSourceURL(uiSourceCode.url());
|
| + scriptFile(uiSourceCode) {
|
| + return this._uiSourceCodeToScriptFile.get(uiSourceCode) || null;
|
| }
|
|
|
| /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| - * @param {!Array.<!SDK.Script>} scripts
|
| + * @param {!SDK.Script} script
|
| */
|
| - _bindUISourceCodeToScripts(uiSourceCode, scripts) {
|
| - console.assert(scripts.length);
|
| - // Due to different listeners order, a script file could be created just before uiSourceCode
|
| - // for the corresponding script was created. Check that we don't create scriptFile twice.
|
| - var boundScriptFile = this.scriptFile(uiSourceCode);
|
| - if (boundScriptFile && boundScriptFile._hasScripts(scripts))
|
| - return;
|
| -
|
| - var scriptFile = new Bindings.ResourceScriptFile(this, uiSourceCode, scripts);
|
| - this._setScriptFile(uiSourceCode, scriptFile);
|
| - for (var i = 0; i < scripts.length; ++i)
|
| - this._debuggerWorkspaceBinding.updateLocations(scripts[i]);
|
| - this._boundUISourceCodes.add(uiSourceCode);
|
| + _updateLocations(script) {
|
| + this._debuggerWorkspaceBinding.updateLocations(script);
|
| }
|
|
|
| /**
|
| @@ -218,7 +205,7 @@ Bindings.ResourceScriptMapping = class {
|
| var scriptFile = this.scriptFile(uiSourceCode);
|
| if (scriptFile) {
|
| scriptFile.dispose();
|
| - this._setScriptFile(uiSourceCode, null);
|
| + this._uiSourceCodeToScriptFile.delete(uiSourceCode);
|
| }
|
| this._boundUISourceCodes.delete(uiSourceCode);
|
| if (scriptFile._script)
|
| @@ -226,15 +213,52 @@ Bindings.ResourceScriptMapping = class {
|
| }
|
|
|
| _debuggerReset() {
|
| + this._removeScripts(Array.from(this._acceptedScripts));
|
| + console.assert(!this._boundUISourceCodes.size);
|
| for (var uiSourceCode of this._boundUISourceCodes.valuesArray())
|
| - this._unbindUISourceCode(uiSourceCode);
|
| + this._unbindUISourceCode(/** @type {!Workspace.UISourceCode} */ (uiSourceCode));
|
| this._boundUISourceCodes.clear();
|
| console.assert(!this._uiSourceCodeToScriptFile.size);
|
| }
|
|
|
| + /**
|
| + * @param {!Common.Event} event
|
| + */
|
| + _executionContextDestroyed(event) {
|
| + var executionContext = /** @type {!SDK.ExecutionContext} */ (event.data);
|
| + var scripts = this._debuggerModel.scriptsForExecutionContext(executionContext);
|
| + this._removeScripts(scripts);
|
| + }
|
| +
|
| + /**
|
| + * @param {!Array<!SDK.Script>} scripts
|
| + */
|
| + _removeScripts(scripts) {
|
| + for (var script of scripts) {
|
| + if (!this._acceptedScripts.has(script))
|
| + continue;
|
| + this._acceptedScripts.delete(script);
|
| + var frameId = script[Bindings.ResourceScriptMapping._frameIdSymbol];
|
| + var project = this._workspaceProjects.get(
|
| + Bindings.ResourceScriptMapping.projectId(this._debuggerModel.target(), frameId, script.isContentScript()));
|
| + var uiSourceCode = project.uiSourceCodeForURL(script.contentURL());
|
| + this._unbindUISourceCode(/** @type {!Workspace.UISourceCode} */ (uiSourceCode));
|
| + project.removeFile(script.contentURL());
|
| + }
|
| + }
|
| +
|
| + _resetForTest() {
|
| + for (var project of this._workspaceProjects.values())
|
| + project.removeProject();
|
| + this._workspaceProjects.clear();
|
| + }
|
| +
|
| dispose() {
|
| Common.EventTarget.removeEventListeners(this._eventListeners);
|
| this._debuggerReset();
|
| + for (var project of this._workspaceProjects.values())
|
| + project.removeProject();
|
| + this._workspaceProjects.clear();
|
| }
|
| };
|
|
|
| @@ -245,17 +269,13 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
| /**
|
| * @param {!Bindings.ResourceScriptMapping} resourceScriptMapping
|
| * @param {!Workspace.UISourceCode} uiSourceCode
|
| - * @param {!Array.<!SDK.Script>} scripts
|
| + * @param {!SDK.Script} script
|
| */
|
| - constructor(resourceScriptMapping, uiSourceCode, scripts) {
|
| + constructor(resourceScriptMapping, uiSourceCode, script) {
|
| super();
|
| - console.assert(scripts.length);
|
| -
|
| this._resourceScriptMapping = resourceScriptMapping;
|
| this._uiSourceCode = uiSourceCode;
|
| -
|
| - if (this._uiSourceCode.contentType().isScript())
|
| - this._script = scripts[scripts.length - 1];
|
| + this._script = script;
|
|
|
| this._uiSourceCode.addEventListener(
|
| Workspace.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
|
| @@ -264,11 +284,11 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
| }
|
|
|
| /**
|
| - * @param {!Array.<!SDK.Script>} scripts
|
| + * @param {!SDK.Script} script
|
| * @return {boolean}
|
| */
|
| - _hasScripts(scripts) {
|
| - return this._script && this._script === scripts[0];
|
| + _hasScript(script) {
|
| + return this._script === script;
|
| }
|
|
|
| /**
|
| @@ -277,8 +297,6 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
| _isDiverged() {
|
| if (this._uiSourceCode.isDirty())
|
| return true;
|
| - if (!this._script)
|
| - return false;
|
| if (typeof this._scriptSource === 'undefined')
|
| return false;
|
| var workingCopy = this._uiSourceCode.workingCopy();
|
| @@ -305,8 +323,6 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
| _workingCopyCommitted(event) {
|
| if (this._uiSourceCode.project().canSetFileContent())
|
| return;
|
| - if (!this._script)
|
| - return;
|
| var debuggerModel = this._resourceScriptMapping._debuggerModel;
|
| var source = this._uiSourceCode.workingCopy();
|
| debuggerModel.setScriptSource(this._script.scriptId, source, scriptSourceWasSet.bind(this));
|
| @@ -343,7 +359,7 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
|
|
| _divergeFromVM() {
|
| this._isDivergingFromVM = true;
|
| - this._resourceScriptMapping._updateLocations(this._uiSourceCode);
|
| + this._resourceScriptMapping._updateLocations(this._script);
|
| delete this._isDivergingFromVM;
|
| this._hasDivergedFromVM = true;
|
| this.dispatchEventToListeners(Bindings.ResourceScriptFile.Events.DidDivergeFromVM, this._uiSourceCode);
|
| @@ -352,7 +368,7 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
| _mergeToVM() {
|
| delete this._hasDivergedFromVM;
|
| this._isMergingToVM = true;
|
| - this._resourceScriptMapping._updateLocations(this._uiSourceCode);
|
| + this._resourceScriptMapping._updateLocations(this._script);
|
| delete this._isMergingToVM;
|
| this.dispatchEventToListeners(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._uiSourceCode);
|
| }
|
| @@ -379,7 +395,7 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
| }
|
|
|
| checkMapping() {
|
| - if (!this._script || typeof this._scriptSource !== 'undefined') {
|
| + if (typeof this._scriptSource !== 'undefined') {
|
| this._mappingCheckedForTest();
|
| return;
|
| }
|
| @@ -410,8 +426,6 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
| * @param {string} sourceMapURL
|
| */
|
| addSourceMapURL(sourceMapURL) {
|
| - if (!this._script)
|
| - return;
|
| this._script.debuggerModel.setSourceMapURL(this._script, sourceMapURL);
|
| }
|
|
|
| @@ -419,7 +433,7 @@ Bindings.ResourceScriptFile = class extends Common.Object {
|
| * @return {boolean}
|
| */
|
| hasSourceMapURL() {
|
| - return this._script && !!this._script.sourceMapURL;
|
| + return !!this._script.sourceMapURL;
|
| }
|
| };
|
|
|
| @@ -428,3 +442,5 @@ Bindings.ResourceScriptFile.Events = {
|
| DidMergeToVM: Symbol('DidMergeToVM'),
|
| DidDivergeFromVM: Symbol('DidDivergeFromVM'),
|
| };
|
| +
|
| +Bindings.ResourceScriptMapping._frameIdSymbol = Symbol('frameid');
|
|
|