summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:20:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:28:57 +0000
commitd17ea114e5ef69ad5d5d7413280a13e6428098aa (patch)
tree2c01a75df69f30d27b1432467cfe7c1467a498da /chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
parent8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (diff)
downloadqtwebengine-chromium-d17ea114e5ef69ad5d5d7413280a13e6428098aa.tar.gz
BASELINE: Update Chromium to 67.0.3396.47
Change-Id: Idcb1341782e417561a2473eeecc82642dafda5b7 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js')
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js1493
1 files changed, 1493 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
new file mode 100644
index 00000000000..c71ecb3289d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
@@ -0,0 +1,1493 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @unrestricted
+ */
+SDK.DebuggerModel = class extends SDK.SDKModel {
+ /**
+ * @param {!SDK.Target} target
+ */
+ constructor(target) {
+ super(target);
+
+ target.registerDebuggerDispatcher(new SDK.DebuggerDispatcher(this));
+ this._agent = target.debuggerAgent();
+ this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel));
+
+ /** @type {!SDK.SourceMapManager<!SDK.Script>} */
+ this._sourceMapManager = new SDK.SourceMapManager(target);
+ /** @type {!Map<string, !SDK.Script>} */
+ this._sourceMapIdToScript = new Map();
+
+ /** @type {?SDK.DebuggerPausedDetails} */
+ this._debuggerPausedDetails = null;
+ /** @type {!Map<string, !SDK.Script>} */
+ this._scripts = new Map();
+ /** @type {!Map.<string, !Array.<!SDK.Script>>} */
+ this._scriptsBySourceURL = new Map();
+ /** @type {!Array.<!SDK.Script>} */
+ this._discardableScripts = [];
+
+ /** @type {!Common.Object} */
+ this._breakpointResolvedEventTarget = new Common.Object();
+
+ this._isPausing = false;
+ Common.moduleSetting('pauseOnExceptionEnabled').addChangeListener(this._pauseOnExceptionStateChanged, this);
+ Common.moduleSetting('pauseOnCaughtException').addChangeListener(this._pauseOnExceptionStateChanged, this);
+ Common.moduleSetting('disableAsyncStackTraces').addChangeListener(this._asyncStackTracesStateChanged, this);
+ Common.moduleSetting('breakpointsActive').addChangeListener(this._breakpointsActiveChanged, this);
+
+ if (!target.suspended())
+ this._enableDebugger();
+
+ /** @type {!Map<string, string>} */
+ this._stringMap = new Map();
+ this._sourceMapManager.setEnabled(Common.moduleSetting('jsSourceMapsEnabled').get());
+ Common.moduleSetting('jsSourceMapsEnabled')
+ .addChangeListener(event => this._sourceMapManager.setEnabled(/** @type {boolean} */ (event.data)));
+ }
+
+ /**
+ * @param {string} executionContextId
+ * @param {string} sourceURL
+ * @param {?string} sourceMapURL
+ * @return {?string}
+ */
+ static _sourceMapId(executionContextId, sourceURL, sourceMapURL) {
+ if (!sourceMapURL)
+ return null;
+ return executionContextId + ':' + sourceURL + ':' + sourceMapURL;
+ }
+
+ /**
+ * @return {!SDK.SourceMapManager<!SDK.Script>}
+ */
+ sourceMapManager() {
+ return this._sourceMapManager;
+ }
+
+ /**
+ * @return {!SDK.RuntimeModel}
+ */
+ runtimeModel() {
+ return this._runtimeModel;
+ }
+
+ /**
+ * @return {boolean}
+ */
+ debuggerEnabled() {
+ return !!this._debuggerEnabled;
+ }
+
+ /**
+ * @return {!Promise}
+ */
+ _enableDebugger() {
+ if (this._debuggerEnabled)
+ return Promise.resolve();
+ this._debuggerEnabled = true;
+
+ const enablePromise = this._agent.enable();
+ enablePromise.then(this._registerDebugger.bind(this));
+ this._pauseOnExceptionStateChanged();
+ this._asyncStackTracesStateChanged();
+ if (!Common.moduleSetting('breakpointsActive').get())
+ this._breakpointsActiveChanged();
+ if (SDK.DebuggerModel._scheduledPauseOnAsyncCall)
+ this._pauseOnAsyncCall(SDK.DebuggerModel._scheduledPauseOnAsyncCall);
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerWasEnabled, this);
+ return enablePromise;
+ }
+
+ /**
+ * @param {string|null} debuggerId
+ */
+ _registerDebugger(debuggerId) {
+ if (!debuggerId)
+ return;
+ SDK.DebuggerModel._debuggerIdToModel.set(debuggerId, this);
+ this._debuggerId = debuggerId;
+ }
+
+ /**
+ * @param {string} debuggerId
+ * @return {?SDK.DebuggerModel}
+ */
+ static modelForDebuggerId(debuggerId) {
+ return SDK.DebuggerModel._debuggerIdToModel.get(debuggerId) || null;
+ }
+
+ /**
+ * @return {!Promise}
+ */
+ _disableDebugger() {
+ if (!this._debuggerEnabled)
+ return Promise.resolve();
+ this._debuggerEnabled = false;
+
+ const disablePromise = this._agent.disable();
+ this._isPausing = false;
+ this._asyncStackTracesStateChanged();
+ this.globalObjectCleared();
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerWasDisabled);
+ SDK.DebuggerModel._debuggerIdToModel.delete(this._debuggerId);
+ return disablePromise;
+ }
+
+ /**
+ * @param {boolean} skip
+ */
+ _skipAllPauses(skip) {
+ if (this._skipAllPausesTimeout) {
+ clearTimeout(this._skipAllPausesTimeout);
+ delete this._skipAllPausesTimeout;
+ }
+ this._agent.setSkipAllPauses(skip);
+ }
+
+ /**
+ * @param {number} timeout
+ */
+ skipAllPausesUntilReloadOrTimeout(timeout) {
+ if (this._skipAllPausesTimeout)
+ clearTimeout(this._skipAllPausesTimeout);
+ this._agent.setSkipAllPauses(true);
+ // If reload happens before the timeout, the flag will be already unset and the timeout callback won't change anything.
+ this._skipAllPausesTimeout = setTimeout(this._skipAllPauses.bind(this, false), timeout);
+ }
+
+ _pauseOnExceptionStateChanged() {
+ let state;
+ if (!Common.moduleSetting('pauseOnExceptionEnabled').get())
+ state = SDK.DebuggerModel.PauseOnExceptionsState.DontPauseOnExceptions;
+ else if (Common.moduleSetting('pauseOnCaughtException').get())
+ state = SDK.DebuggerModel.PauseOnExceptionsState.PauseOnAllExceptions;
+ else
+ state = SDK.DebuggerModel.PauseOnExceptionsState.PauseOnUncaughtExceptions;
+
+ this._agent.setPauseOnExceptions(state);
+ }
+
+ _asyncStackTracesStateChanged() {
+ const maxAsyncStackChainDepth = 32;
+ const enabled = !Common.moduleSetting('disableAsyncStackTraces').get() && this._debuggerEnabled;
+ this._agent.setAsyncCallStackDepth(enabled ? maxAsyncStackChainDepth : 0);
+ }
+
+ _breakpointsActiveChanged() {
+ this._agent.setBreakpointsActive(Common.moduleSetting('breakpointsActive').get());
+ }
+
+ stepInto() {
+ this._agent.stepInto();
+ }
+
+ stepOver() {
+ this._agent.stepOver();
+ }
+
+ stepOut() {
+ this._agent.stepOut();
+ }
+
+ scheduleStepIntoAsync() {
+ this._agent.invoke_stepInto({breakOnAsyncCall: true});
+ }
+
+ resume() {
+ this._agent.resume();
+ this._isPausing = false;
+ }
+
+ pause() {
+ this._isPausing = true;
+ this._skipAllPauses(false);
+ this._agent.pause();
+ }
+
+ /**
+ * @param {!Protocol.Runtime.StackTraceId} parentStackTraceId
+ * @return {!Promise}
+ */
+ _pauseOnAsyncCall(parentStackTraceId) {
+ return this._agent.invoke_pauseOnAsyncCall({parentStackTraceId: parentStackTraceId});
+ }
+
+ /**
+ * @param {string} url
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @param {string=} condition
+ * @return {!Promise<!SDK.DebuggerModel.SetBreakpointResult>}
+ */
+ async setBreakpointByURL(url, lineNumber, columnNumber, condition) {
+ // Convert file url to node-js path.
+ if (this.target().isNodeJS())
+ url = Common.ParsedURL.urlToPlatformPath(url, Host.isWin());
+ // Adjust column if needed.
+ let minColumnNumber = 0;
+ const scripts = this._scriptsBySourceURL.get(url) || [];
+ for (let i = 0, l = scripts.length; i < l; ++i) {
+ const script = scripts[i];
+ if (lineNumber === script.lineOffset)
+ minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, script.columnOffset) : script.columnOffset;
+ }
+ columnNumber = Math.max(columnNumber, minColumnNumber);
+ const response = await this._agent.invoke_setBreakpointByUrl(
+ {lineNumber: lineNumber, url: url, columnNumber: columnNumber, condition: condition});
+ if (response[Protocol.Error])
+ return {locations: [], breakpointId: null};
+ let locations;
+ if (response.locations)
+ locations = response.locations.map(payload => SDK.DebuggerModel.Location.fromPayload(this, payload));
+ return {locations: locations, breakpointId: response.breakpointId};
+ }
+
+ /**
+ * @param {string} scriptId
+ * @param {string} scriptHash
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @param {string=} condition
+ * @return {!Promise<!SDK.DebuggerModel.SetBreakpointResult>}
+ */
+ async setBreakpointInAnonymousScript(scriptId, scriptHash, lineNumber, columnNumber, condition) {
+ const response = await this._agent.invoke_setBreakpointByUrl(
+ {lineNumber: lineNumber, scriptHash: scriptHash, columnNumber: columnNumber, condition: condition});
+ const error = response[Protocol.Error];
+ if (error) {
+ // Old V8 backend doesn't support scriptHash argument.
+ if (error !== 'Either url or urlRegex must be specified.')
+ return {locations: [], breakpointId: null};
+ return this._setBreakpointBySourceId(scriptId, lineNumber, columnNumber, condition);
+ }
+ let locations;
+ if (response.locations)
+ locations = response.locations.map(payload => SDK.DebuggerModel.Location.fromPayload(this, payload));
+ return {locations: locations, breakpointId: response.breakpointId};
+ }
+
+ /**
+ * @param {string} scriptId
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @param {string=} condition
+ * @return {!Promise<!SDK.DebuggerModel.SetBreakpointResult>}
+ */
+ async _setBreakpointBySourceId(scriptId, lineNumber, columnNumber, condition) {
+ // This method is required for backward compatibility with V8 before 6.3.275.
+ const response = await this._agent.invoke_setBreakpoint(
+ {location: {scriptId: scriptId, lineNumber: lineNumber, columnNumber: columnNumber}, condition: condition});
+ if (response[Protocol.Error])
+ return {breakpointId: null, locations: []};
+ let actualLocation = [];
+ if (response.actualLocation)
+ actualLocation = [SDK.DebuggerModel.Location.fromPayload(this, response.actualLocation)];
+ return {locations: actualLocation, breakpointId: response.breakpointId};
+ }
+
+ /**
+ * @param {!Protocol.Debugger.BreakpointId} breakpointId
+ * @return {!Promise}
+ */
+ async removeBreakpoint(breakpointId) {
+ const response = await this._agent.invoke_removeBreakpoint({breakpointId});
+ if (response[Protocol.Error])
+ console.error('Failed to remove breakpoint: ' + response[Protocol.Error]);
+ }
+
+ /**
+ * @param {!SDK.DebuggerModel.Location} startLocation
+ * @param {?SDK.DebuggerModel.Location} endLocation
+ * @param {boolean} restrictToFunction
+ * @return {!Promise<!Array<!SDK.DebuggerModel.BreakLocation>>}
+ */
+ async getPossibleBreakpoints(startLocation, endLocation, restrictToFunction) {
+ const response = await this._agent.invoke_getPossibleBreakpoints({
+ start: startLocation.payload(),
+ end: endLocation ? endLocation.payload() : undefined,
+ restrictToFunction: restrictToFunction
+ });
+ if (response[Protocol.Error] || !response.locations)
+ return [];
+ return response.locations.map(location => SDK.DebuggerModel.BreakLocation.fromPayload(this, location));
+ }
+
+ /**
+ * @param {!Protocol.Runtime.StackTraceId} stackId
+ * @return {!Promise<?Protocol.Runtime.StackTrace>}
+ */
+ async fetchAsyncStackTrace(stackId) {
+ const response = await this._agent.invoke_getStackTrace({stackTraceId: stackId});
+ return response[Protocol.Error] ? null : response.stackTrace;
+ }
+
+ /**
+ * @param {!Protocol.Debugger.BreakpointId} breakpointId
+ * @param {!Protocol.Debugger.Location} location
+ */
+ _breakpointResolved(breakpointId, location) {
+ this._breakpointResolvedEventTarget.dispatchEventToListeners(
+ breakpointId, SDK.DebuggerModel.Location.fromPayload(this, location));
+ }
+
+ globalObjectCleared() {
+ this._setDebuggerPausedDetails(null);
+ this._reset();
+ // TODO(dgozman): move clients to ExecutionContextDestroyed/ScriptCollected events.
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.GlobalObjectCleared, this);
+ }
+
+ _reset() {
+ for (const scriptWithSourceMap of this._sourceMapIdToScript.values())
+ this._sourceMapManager.detachSourceMap(scriptWithSourceMap);
+ this._sourceMapIdToScript.clear();
+
+ this._scripts.clear();
+ this._scriptsBySourceURL.clear();
+ this._stringMap.clear();
+ this._discardableScripts = [];
+ }
+
+ /**
+ * @return {!Array<!SDK.Script>}
+ */
+ scripts() {
+ return Array.from(this._scripts.values());
+ }
+
+ /**
+ * @param {!Protocol.Runtime.ScriptId} scriptId
+ * @return {?SDK.Script}
+ */
+ scriptForId(scriptId) {
+ return this._scripts.get(scriptId) || null;
+ }
+
+ /**
+ * @return {!Array.<!SDK.Script>}
+ */
+ scriptsForSourceURL(sourceURL) {
+ if (!sourceURL)
+ return [];
+ return this._scriptsBySourceURL.get(sourceURL) || [];
+ }
+
+ /**
+ * @param {!SDK.ExecutionContext} executionContext
+ * @return {!Array<!SDK.Script>}
+ */
+ scriptsForExecutionContext(executionContext) {
+ const result = [];
+ for (const script of this._scripts.values()) {
+ if (script.executionContextId === executionContext.id)
+ result.push(script);
+ }
+ return result;
+ }
+
+ /**
+ * @param {!Protocol.Runtime.ScriptId} scriptId
+ * @param {string} newSource
+ * @param {function(?Protocol.Error, !Protocol.Runtime.ExceptionDetails=)} callback
+ */
+ setScriptSource(scriptId, newSource, callback) {
+ this._scripts.get(scriptId).editSource(
+ newSource, this._didEditScriptSource.bind(this, scriptId, newSource, callback));
+ }
+
+ /**
+ * @param {!Protocol.Runtime.ScriptId} scriptId
+ * @param {string} newSource
+ * @param {function(?Protocol.Error, !Protocol.Runtime.ExceptionDetails=)} callback
+ * @param {?Protocol.Error} error
+ * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
+ * @param {!Array.<!Protocol.Debugger.CallFrame>=} callFrames
+ * @param {!Protocol.Runtime.StackTrace=} asyncStackTrace
+ * @param {!Protocol.Runtime.StackTraceId=} asyncStackTraceId
+ * @param {boolean=} needsStepIn
+ */
+ _didEditScriptSource(
+ scriptId, newSource, callback, error, exceptionDetails, callFrames, asyncStackTrace, asyncStackTraceId,
+ needsStepIn) {
+ callback(error, exceptionDetails);
+ if (needsStepIn) {
+ this.stepInto();
+ return;
+ }
+
+ if (!error && callFrames && callFrames.length) {
+ this._pausedScript(
+ callFrames, this._debuggerPausedDetails.reason, this._debuggerPausedDetails.auxData,
+ this._debuggerPausedDetails.breakpointIds, asyncStackTrace, asyncStackTraceId);
+ }
+ }
+
+ /**
+ * @return {?Array.<!SDK.DebuggerModel.CallFrame>}
+ */
+ get callFrames() {
+ return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFrames : null;
+ }
+
+ /**
+ * @return {?SDK.DebuggerPausedDetails}
+ */
+ debuggerPausedDetails() {
+ return this._debuggerPausedDetails;
+ }
+
+ /**
+ * @param {?SDK.DebuggerPausedDetails} debuggerPausedDetails
+ * @return {boolean}
+ */
+ _setDebuggerPausedDetails(debuggerPausedDetails) {
+ this._isPausing = false;
+ this._debuggerPausedDetails = debuggerPausedDetails;
+ if (this._debuggerPausedDetails) {
+ if (Runtime.experiments.isEnabled('emptySourceMapAutoStepping') && this._beforePausedCallback) {
+ if (!this._beforePausedCallback.call(null, this._debuggerPausedDetails))
+ return false;
+ }
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerPaused, this);
+ }
+ if (debuggerPausedDetails)
+ this.setSelectedCallFrame(debuggerPausedDetails.callFrames[0]);
+ else
+ this.setSelectedCallFrame(null);
+ return true;
+ }
+
+ /**
+ * @param {?function(!SDK.DebuggerPausedDetails):boolean} callback
+ */
+ setBeforePausedCallback(callback) {
+ this._beforePausedCallback = callback;
+ }
+
+ /**
+ * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
+ * @param {string} reason
+ * @param {!Object|undefined} auxData
+ * @param {!Array.<string>} breakpointIds
+ * @param {!Protocol.Runtime.StackTrace=} asyncStackTrace
+ * @param {!Protocol.Runtime.StackTraceId=} asyncStackTraceId
+ * @param {!Protocol.Runtime.StackTraceId=} asyncCallStackTraceId
+ */
+ async _pausedScript(
+ callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId, asyncCallStackTraceId) {
+ if (asyncCallStackTraceId) {
+ SDK.DebuggerModel._scheduledPauseOnAsyncCall = asyncCallStackTraceId;
+ const promises = [];
+ for (const model of SDK.DebuggerModel._debuggerIdToModel.values())
+ promises.push(model._pauseOnAsyncCall(asyncCallStackTraceId));
+ await Promise.all(promises);
+ this.resume();
+ return;
+ }
+
+ const pausedDetails = new SDK.DebuggerPausedDetails(
+ this, callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId);
+
+ if (pausedDetails && this._continueToLocationCallback) {
+ const callback = this._continueToLocationCallback;
+ delete this._continueToLocationCallback;
+ if (callback(pausedDetails))
+ return;
+ }
+
+ if (!this._setDebuggerPausedDetails(pausedDetails))
+ this._agent.stepInto();
+
+ SDK.DebuggerModel._scheduledPauseOnAsyncCall = null;
+ }
+
+ _resumedScript() {
+ this._setDebuggerPausedDetails(null);
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerResumed, this);
+ }
+
+ /**
+ * @param {!Protocol.Runtime.ScriptId} scriptId
+ * @param {string} sourceURL
+ * @param {number} startLine
+ * @param {number} startColumn
+ * @param {number} endLine
+ * @param {number} endColumn
+ * @param {!Protocol.Runtime.ExecutionContextId} executionContextId
+ * @param {string} hash
+ * @param {*|undefined} executionContextAuxData
+ * @param {boolean} isLiveEdit
+ * @param {string|undefined} sourceMapURL
+ * @param {boolean} hasSourceURLComment
+ * @param {boolean} hasSyntaxError
+ * @param {number} length
+ * @return {!SDK.Script}
+ */
+ _parsedScriptSource(
+ scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
+ executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURLComment, hasSyntaxError, length) {
+ let isContentScript = false;
+ if (executionContextAuxData && ('isDefault' in executionContextAuxData))
+ isContentScript = !executionContextAuxData['isDefault'];
+ // Support file URL for node.js.
+ if (this.target().isNodeJS() && sourceURL && !hasSourceURLComment) {
+ const nodeJSPath = sourceURL;
+ sourceURL = Common.ParsedURL.platformPathToURL(nodeJSPath);
+ sourceURL = this._internString(sourceURL);
+ } else {
+ sourceURL = this._internString(sourceURL);
+ }
+ const script = new SDK.Script(
+ this, scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId,
+ this._internString(hash), isContentScript, isLiveEdit, sourceMapURL, hasSourceURLComment, length);
+ this._registerScript(script);
+ if (!hasSyntaxError)
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.ParsedScriptSource, script);
+ else
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.FailedToParseScriptSource, script);
+
+ const sourceMapId =
+ SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
+ if (sourceMapId && !hasSyntaxError) {
+ // Consecutive script evaluations in the same execution context with the same sourceURL
+ // and sourceMappingURL should result in source map reloading.
+ const previousScript = this._sourceMapIdToScript.get(sourceMapId);
+ if (previousScript)
+ this._sourceMapManager.detachSourceMap(previousScript);
+ this._sourceMapIdToScript.set(sourceMapId, script);
+ this._sourceMapManager.attachSourceMap(script, script.sourceURL, script.sourceMapURL);
+ }
+
+ const isDiscardable = hasSyntaxError && script.isAnonymousScript();
+ if (isDiscardable) {
+ this._discardableScripts.push(script);
+ this._collectDiscardedScripts();
+ }
+ return script;
+ }
+
+ /**
+ * @param {!SDK.Script} script
+ * @param {string} newSourceMapURL
+ */
+ setSourceMapURL(script, newSourceMapURL) {
+ let sourceMapId = SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
+ if (sourceMapId && this._sourceMapIdToScript.get(sourceMapId) === script)
+ this._sourceMapIdToScript.delete(sourceMapId);
+ this._sourceMapManager.detachSourceMap(script);
+
+ script.sourceMapURL = newSourceMapURL;
+ sourceMapId = SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
+ if (!sourceMapId)
+ return;
+ this._sourceMapIdToScript.set(sourceMapId, script);
+ this._sourceMapManager.attachSourceMap(script, script.sourceURL, script.sourceMapURL);
+ }
+
+ /**
+ * @param {!SDK.ExecutionContext} executionContext
+ */
+ executionContextDestroyed(executionContext) {
+ const sourceMapIds = Array.from(this._sourceMapIdToScript.keys());
+ for (const sourceMapId of sourceMapIds) {
+ const script = this._sourceMapIdToScript.get(sourceMapId);
+ if (script.executionContextId === executionContext.id) {
+ this._sourceMapIdToScript.delete(sourceMapId);
+ this._sourceMapManager.detachSourceMap(script);
+ }
+ }
+ }
+
+ /**
+ * @param {!SDK.Script} script
+ */
+ _registerScript(script) {
+ this._scripts.set(script.scriptId, script);
+ if (script.isAnonymousScript())
+ return;
+
+ let scripts = this._scriptsBySourceURL.get(script.sourceURL);
+ if (!scripts) {
+ scripts = [];
+ this._scriptsBySourceURL.set(script.sourceURL, scripts);
+ }
+ scripts.push(script);
+ }
+
+ /**
+ * @param {!SDK.Script} script
+ */
+ _unregisterScript(script) {
+ console.assert(script.isAnonymousScript());
+ this._scripts.delete(script.scriptId);
+ }
+
+ _collectDiscardedScripts() {
+ if (this._discardableScripts.length < 1000)
+ return;
+ const scriptsToDiscard = this._discardableScripts.splice(0, 100);
+ for (const script of scriptsToDiscard) {
+ this._unregisterScript(script);
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.DiscardedAnonymousScriptSource, script);
+ }
+ }
+
+ /**
+ * @param {!SDK.Script} script
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {?SDK.DebuggerModel.Location}
+ */
+ createRawLocation(script, lineNumber, columnNumber) {
+ return new SDK.DebuggerModel.Location(this, script.scriptId, lineNumber, columnNumber);
+ }
+
+ /**
+ * @param {string} sourceURL
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {?SDK.DebuggerModel.Location}
+ */
+ createRawLocationByURL(sourceURL, lineNumber, columnNumber) {
+ let closestScript = null;
+ const scripts = this._scriptsBySourceURL.get(sourceURL) || [];
+ for (let i = 0, l = scripts.length; i < l; ++i) {
+ const script = scripts[i];
+ if (!closestScript)
+ closestScript = script;
+ if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber))
+ continue;
+ if (script.endLine < lineNumber || (script.endLine === lineNumber && script.endColumn <= columnNumber))
+ continue;
+ closestScript = script;
+ break;
+ }
+ return closestScript ? new SDK.DebuggerModel.Location(this, closestScript.scriptId, lineNumber, columnNumber) :
+ null;
+ }
+
+ /**
+ * @param {!Protocol.Runtime.ScriptId} scriptId
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {?SDK.DebuggerModel.Location}
+ */
+ createRawLocationByScriptId(scriptId, lineNumber, columnNumber) {
+ const script = this.scriptForId(scriptId);
+ return script ? this.createRawLocation(script, lineNumber, columnNumber) : null;
+ }
+
+ /**
+ * @param {!Protocol.Runtime.StackTrace} stackTrace
+ * @return {!Array<!SDK.DebuggerModel.Location>}
+ */
+ createRawLocationsByStackTrace(stackTrace) {
+ const frames = [];
+ while (stackTrace) {
+ for (const frame of stackTrace.callFrames)
+ frames.push(frame);
+ stackTrace = stackTrace.parent;
+ }
+
+ const rawLocations = [];
+ for (const frame of frames) {
+ const rawLocation = this.createRawLocationByScriptId(frame.scriptId, frame.lineNumber, frame.columnNumber);
+ if (rawLocation)
+ rawLocations.push(rawLocation);
+ }
+ return rawLocations;
+ }
+
+ /**
+ * @return {boolean}
+ */
+ isPaused() {
+ return !!this.debuggerPausedDetails();
+ }
+
+ /**
+ * @return {boolean}
+ */
+ isPausing() {
+ return this._isPausing;
+ }
+
+ /**
+ * @param {?SDK.DebuggerModel.CallFrame} callFrame
+ */
+ setSelectedCallFrame(callFrame) {
+ if (this._selectedCallFrame === callFrame)
+ return;
+ this._selectedCallFrame = callFrame;
+ this.dispatchEventToListeners(SDK.DebuggerModel.Events.CallFrameSelected, this);
+ }
+
+ /**
+ * @return {?SDK.DebuggerModel.CallFrame}
+ */
+ selectedCallFrame() {
+ return this._selectedCallFrame;
+ }
+
+ /**
+ * @param {!SDK.RuntimeModel.EvaluationOptions} options
+ * @return {!Promise<!SDK.RuntimeModel.EvaluationResult>}
+ */
+ evaluateOnSelectedCallFrame(options) {
+ return this.selectedCallFrame().evaluate(options);
+ }
+
+ /**
+ * @param {!SDK.RemoteObject} remoteObject
+ * @return {!Promise<?SDK.DebuggerModel.FunctionDetails>}
+ */
+ functionDetailsPromise(remoteObject) {
+ return remoteObject.getAllPropertiesPromise(false /* accessorPropertiesOnly */, false /* generatePreview */)
+ .then(buildDetails.bind(this));
+
+ /**
+ * @param {!{properties: ?Array.<!SDK.RemoteObjectProperty>, internalProperties: ?Array.<!SDK.RemoteObjectProperty>}} response
+ * @return {?SDK.DebuggerModel.FunctionDetails}
+ * @this {!SDK.DebuggerModel}
+ */
+ function buildDetails(response) {
+ if (!response)
+ return null;
+ let location = null;
+ if (response.internalProperties) {
+ for (const prop of response.internalProperties) {
+ if (prop.name === '[[FunctionLocation]]')
+ location = prop.value;
+ }
+ }
+ let functionName = null;
+ if (response.properties) {
+ for (const prop of response.properties) {
+ if (prop.name === 'name' && prop.value && prop.value.type === 'string')
+ functionName = prop.value;
+ if (prop.name === 'displayName' && prop.value && prop.value.type === 'string') {
+ functionName = prop.value;
+ break;
+ }
+ }
+ }
+ let debuggerLocation = null;
+ if (location) {
+ debuggerLocation = this.createRawLocationByScriptId(
+ location.value.scriptId, location.value.lineNumber, location.value.columnNumber);
+ }
+ return {location: debuggerLocation, functionName: functionName ? functionName.value : ''};
+ }
+ }
+
+ /**
+ * @param {number} scopeNumber
+ * @param {string} variableName
+ * @param {!Protocol.Runtime.CallArgument} newValue
+ * @param {string} callFrameId
+ * @return {!Promise<string|undefined>}
+ */
+ async setVariableValue(scopeNumber, variableName, newValue, callFrameId) {
+ const response = await this._agent.invoke_setVariableValue({scopeNumber, variableName, newValue, callFrameId});
+ const error = response[Protocol.Error];
+ if (error)
+ console.error(error);
+ return error;
+ }
+
+ /**
+ * @param {!Protocol.Debugger.BreakpointId} breakpointId
+ * @param {function(!Common.Event)} listener
+ * @param {!Object=} thisObject
+ */
+ addBreakpointListener(breakpointId, listener, thisObject) {
+ this._breakpointResolvedEventTarget.addEventListener(breakpointId, listener, thisObject);
+ }
+
+ /**
+ * @param {!Protocol.Debugger.BreakpointId} breakpointId
+ * @param {function(!Common.Event)} listener
+ * @param {!Object=} thisObject
+ */
+ removeBreakpointListener(breakpointId, listener, thisObject) {
+ this._breakpointResolvedEventTarget.removeEventListener(breakpointId, listener, thisObject);
+ }
+
+ /**
+ * @param {!Array<string>} patterns
+ * @return {!Promise<boolean>}
+ */
+ async setBlackboxPatterns(patterns) {
+ const response = await this._agent.invoke_setBlackboxPatterns({patterns});
+ const error = response[Protocol.Error];
+ if (error)
+ console.error(error);
+ return !error;
+ }
+
+ /**
+ * @override
+ */
+ dispose() {
+ this._sourceMapManager.dispose();
+ SDK.DebuggerModel._debuggerIdToModel.delete(this._debuggerId);
+ Common.moduleSetting('pauseOnExceptionEnabled').removeChangeListener(this._pauseOnExceptionStateChanged, this);
+ Common.moduleSetting('pauseOnCaughtException').removeChangeListener(this._pauseOnExceptionStateChanged, this);
+ Common.moduleSetting('disableAsyncStackTraces').removeChangeListener(this._asyncStackTracesStateChanged, this);
+ }
+
+ /**
+ * @override
+ * @return {!Promise}
+ */
+ async suspendModel() {
+ await this._disableDebugger();
+ }
+
+ /**
+ * @override
+ * @return {!Promise}
+ */
+ async resumeModel() {
+ await this._enableDebugger();
+ }
+
+ /**
+ * @param {string} string
+ * @return {string} string
+ */
+ _internString(string) {
+ if (!this._stringMap.has(string))
+ this._stringMap.set(string, string);
+ return this._stringMap.get(string);
+ }
+};
+
+/** @type {!Map<string, !SDK.DebuggerModel>} */
+SDK.DebuggerModel._debuggerIdToModel = new Map();
+
+/** @type {?Protocol.Runtime.StackTraceId} */
+SDK.DebuggerModel._scheduledPauseOnAsyncCall = null;
+
+SDK.SDKModel.register(SDK.DebuggerModel, SDK.Target.Capability.JS, true);
+
+/** @typedef {{location: ?SDK.DebuggerModel.Location, functionName: string}} */
+SDK.DebuggerModel.FunctionDetails;
+
+/**
+ * Keep these in sync with WebCore::V8Debugger
+ *
+ * @enum {string}
+ */
+SDK.DebuggerModel.PauseOnExceptionsState = {
+ DontPauseOnExceptions: 'none',
+ PauseOnAllExceptions: 'all',
+ PauseOnUncaughtExceptions: 'uncaught'
+};
+
+/** @enum {symbol} */
+SDK.DebuggerModel.Events = {
+ DebuggerWasEnabled: Symbol('DebuggerWasEnabled'),
+ DebuggerWasDisabled: Symbol('DebuggerWasDisabled'),
+ DebuggerPaused: Symbol('DebuggerPaused'),
+ DebuggerResumed: Symbol('DebuggerResumed'),
+ ParsedScriptSource: Symbol('ParsedScriptSource'),
+ FailedToParseScriptSource: Symbol('FailedToParseScriptSource'),
+ DiscardedAnonymousScriptSource: Symbol('DiscardedAnonymousScriptSource'),
+ GlobalObjectCleared: Symbol('GlobalObjectCleared'),
+ CallFrameSelected: Symbol('CallFrameSelected'),
+ ConsoleCommandEvaluatedInSelectedCallFrame: Symbol('ConsoleCommandEvaluatedInSelectedCallFrame')
+};
+
+/** @enum {string} */
+SDK.DebuggerModel.BreakReason = {
+ DOM: 'DOM',
+ EventListener: 'EventListener',
+ XHR: 'XHR',
+ Exception: 'exception',
+ PromiseRejection: 'promiseRejection',
+ Assert: 'assert',
+ DebugCommand: 'debugCommand',
+ OOM: 'OOM',
+ Other: 'other'
+};
+
+/** @enum {string} */
+SDK.DebuggerModel.BreakLocationType = {
+ Return: 'return',
+ Call: 'call',
+ DebuggerStatement: 'debuggerStatement'
+};
+
+SDK.DebuggerEventTypes = {
+ JavaScriptPause: 0,
+ JavaScriptBreakpoint: 1,
+ NativeBreakpoint: 2
+};
+
+SDK.DebuggerModel.ContinueToLocationTargetCallFrames = {
+ Any: 'any',
+ Current: 'current'
+};
+
+/** @typedef {{
+ * breakpointId: ?Protocol.Debugger.BreakpointId,
+ * locations: !Array<!SDK.DebuggerModel.Location>
+ * }}
+ */
+SDK.DebuggerModel.SetBreakpointResult;
+
+/**
+ * @implements {Protocol.DebuggerDispatcher}
+ * @unrestricted
+ */
+SDK.DebuggerDispatcher = class {
+ /**
+ * @param {!SDK.DebuggerModel} debuggerModel
+ */
+ constructor(debuggerModel) {
+ this._debuggerModel = debuggerModel;
+ }
+
+ /**
+ * @override
+ * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
+ * @param {string} reason
+ * @param {!Object=} auxData
+ * @param {!Array.<string>=} breakpointIds
+ * @param {!Protocol.Runtime.StackTrace=} asyncStackTrace
+ * @param {!Protocol.Runtime.StackTraceId=} asyncStackTraceId
+ * @param {!Protocol.Runtime.StackTraceId=} asyncCallStackTraceId
+ */
+ paused(callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId, asyncCallStackTraceId) {
+ this._debuggerModel._pausedScript(
+ callFrames, reason, auxData, breakpointIds || [], asyncStackTrace, asyncStackTraceId, asyncCallStackTraceId);
+ }
+
+ /**
+ * @override
+ */
+ resumed() {
+ this._debuggerModel._resumedScript();
+ }
+
+ /**
+ * @override
+ * @param {!Protocol.Runtime.ScriptId} scriptId
+ * @param {string} sourceURL
+ * @param {number} startLine
+ * @param {number} startColumn
+ * @param {number} endLine
+ * @param {number} endColumn
+ * @param {!Protocol.Runtime.ExecutionContextId} executionContextId
+ * @param {string} hash
+ * @param {*=} executionContextAuxData
+ * @param {boolean=} isLiveEdit
+ * @param {string=} sourceMapURL
+ * @param {boolean=} hasSourceURL
+ * @param {boolean=} isModule
+ * @param {number=} length
+ */
+ scriptParsed(
+ scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
+ executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURL, isModule, length) {
+ this._debuggerModel._parsedScriptSource(
+ scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
+ executionContextAuxData, !!isLiveEdit, sourceMapURL, !!hasSourceURL, false, length || 0);
+ }
+
+ /**
+ * @override
+ * @param {!Protocol.Runtime.ScriptId} scriptId
+ * @param {string} sourceURL
+ * @param {number} startLine
+ * @param {number} startColumn
+ * @param {number} endLine
+ * @param {number} endColumn
+ * @param {!Protocol.Runtime.ExecutionContextId} executionContextId
+ * @param {string} hash
+ * @param {*=} executionContextAuxData
+ * @param {string=} sourceMapURL
+ * @param {boolean=} hasSourceURL
+ * @param {boolean=} isModule
+ * @param {number=} length
+ */
+ scriptFailedToParse(
+ scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
+ executionContextAuxData, sourceMapURL, hasSourceURL, isModule, length) {
+ this._debuggerModel._parsedScriptSource(
+ scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
+ executionContextAuxData, false, sourceMapURL, !!hasSourceURL, true, length || 0);
+ }
+
+ /**
+ * @override
+ * @param {!Protocol.Debugger.BreakpointId} breakpointId
+ * @param {!Protocol.Debugger.Location} location
+ */
+ breakpointResolved(breakpointId, location) {
+ this._debuggerModel._breakpointResolved(breakpointId, location);
+ }
+};
+
+/**
+ * @unrestricted
+ */
+SDK.DebuggerModel.Location = class {
+ /**
+ * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {string} scriptId
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ */
+ constructor(debuggerModel, scriptId, lineNumber, columnNumber) {
+ this.debuggerModel = debuggerModel;
+ this.scriptId = scriptId;
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber || 0;
+ }
+
+ /**
+ * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!Protocol.Debugger.Location} payload
+ * @return {!SDK.DebuggerModel.Location}
+ */
+ static fromPayload(debuggerModel, payload) {
+ return new SDK.DebuggerModel.Location(debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumber);
+ }
+
+ /**
+ * @return {!Protocol.Debugger.Location}
+ */
+ payload() {
+ return {scriptId: this.scriptId, lineNumber: this.lineNumber, columnNumber: this.columnNumber};
+ }
+
+ /**
+ * @return {?SDK.Script}
+ */
+ script() {
+ return this.debuggerModel.scriptForId(this.scriptId);
+ }
+
+ /**
+ * @param {function()=} pausedCallback
+ */
+ continueToLocation(pausedCallback) {
+ if (pausedCallback)
+ this.debuggerModel._continueToLocationCallback = this._paused.bind(this, pausedCallback);
+ this.debuggerModel._agent.continueToLocation(
+ this.payload(), SDK.DebuggerModel.ContinueToLocationTargetCallFrames.Current);
+ }
+
+ /**
+ * @param {function()|undefined} pausedCallback
+ * @param {!SDK.DebuggerPausedDetails} debuggerPausedDetails
+ * @return {boolean}
+ */
+ _paused(pausedCallback, debuggerPausedDetails) {
+ const location = debuggerPausedDetails.callFrames[0].location();
+ if (location.scriptId === this.scriptId && location.lineNumber === this.lineNumber &&
+ location.columnNumber === this.columnNumber) {
+ pausedCallback();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @return {string}
+ */
+ id() {
+ return this.debuggerModel.target().id() + ':' + this.scriptId + ':' + this.lineNumber + ':' + this.columnNumber;
+ }
+};
+
+/**
+ * @unrestricted
+ */
+SDK.DebuggerModel.BreakLocation = class extends SDK.DebuggerModel.Location {
+ /**
+ * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {string} scriptId
+ * @param {number} lineNumber
+ * @param {number=} columnNumber
+ * @param {!Protocol.Debugger.BreakLocationType=} type
+ */
+ constructor(debuggerModel, scriptId, lineNumber, columnNumber, type) {
+ super(debuggerModel, scriptId, lineNumber, columnNumber);
+ if (type)
+ this.type = type;
+ }
+
+ /**
+ * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!Protocol.Debugger.BreakLocation} payload
+ * @return {!SDK.DebuggerModel.BreakLocation}
+ */
+ static fromPayload(debuggerModel, payload) {
+ return new SDK.DebuggerModel.BreakLocation(
+ debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumber, payload.type);
+ }
+};
+
+/**
+ * @unrestricted
+ */
+SDK.DebuggerModel.CallFrame = class {
+ /**
+ * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!SDK.Script} script
+ * @param {!Protocol.Debugger.CallFrame} payload
+ */
+ constructor(debuggerModel, script, payload) {
+ this.debuggerModel = debuggerModel;
+ this._script = script;
+ this._payload = payload;
+ this._location = SDK.DebuggerModel.Location.fromPayload(debuggerModel, payload.location);
+ this._scopeChain = [];
+ this._localScope = null;
+ for (let i = 0; i < payload.scopeChain.length; ++i) {
+ const scope = new SDK.DebuggerModel.Scope(this, i);
+ this._scopeChain.push(scope);
+ if (scope.type() === Protocol.Debugger.ScopeType.Local)
+ this._localScope = scope;
+ }
+ if (payload.functionLocation)
+ this._functionLocation = SDK.DebuggerModel.Location.fromPayload(debuggerModel, payload.functionLocation);
+ this._returnValue =
+ payload.returnValue ? this.debuggerModel._runtimeModel.createRemoteObject(payload.returnValue) : null;
+ }
+
+ /**
+ * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
+ * @return {!Array.<!SDK.DebuggerModel.CallFrame>}
+ */
+ static fromPayloadArray(debuggerModel, callFrames) {
+ const result = [];
+ for (let i = 0; i < callFrames.length; ++i) {
+ const callFrame = callFrames[i];
+ const script = debuggerModel.scriptForId(callFrame.location.scriptId);
+ if (script)
+ result.push(new SDK.DebuggerModel.CallFrame(debuggerModel, script, callFrame));
+ }
+ return result;
+ }
+
+ /**
+ * @return {!SDK.Script}
+ */
+ get script() {
+ return this._script;
+ }
+
+ /**
+ * @return {string}
+ */
+ get id() {
+ return this._payload.callFrameId;
+ }
+
+ /**
+ * @return {!Array.<!SDK.DebuggerModel.Scope>}
+ */
+ scopeChain() {
+ return this._scopeChain;
+ }
+
+ /**
+ * @return {?SDK.DebuggerModel.Scope}
+ */
+ localScope() {
+ return this._localScope;
+ }
+
+ /**
+ * @return {?SDK.RemoteObject}
+ */
+ thisObject() {
+ return this._payload.this ? this.debuggerModel._runtimeModel.createRemoteObject(this._payload.this) : null;
+ }
+
+ /**
+ * @return {?SDK.RemoteObject}
+ */
+ returnValue() {
+ return this._returnValue;
+ }
+
+ /**
+ * @param {string} expression
+ * @return {!Promise<?SDK.RemoteObject>}
+ */
+ async setReturnValue(expression) {
+ if (!this._returnValue)
+ return null;
+
+ const evaluateResponse = await this.debuggerModel._agent.invoke_evaluateOnCallFrame(
+ {callFrameId: this.id, expression: expression, silent: true, objectGroup: 'backtrace'});
+ if (evaluateResponse[Protocol.Error] || evaluateResponse.exceptionDetails)
+ return null;
+ const response = await this.debuggerModel._agent.invoke_setReturnValue({newValue: evaluateResponse.result});
+ if (response[Protocol.Error])
+ return null;
+ this._returnValue = this.debuggerModel._runtimeModel.createRemoteObject(evaluateResponse.result);
+ return this._returnValue;
+ }
+
+ /**
+ * @return {string}
+ */
+ get functionName() {
+ return this._payload.functionName;
+ }
+
+ /**
+ * @return {!SDK.DebuggerModel.Location}
+ */
+ location() {
+ return this._location;
+ }
+
+ /**
+ * @return {?SDK.DebuggerModel.Location}
+ */
+ functionLocation() {
+ return this._functionLocation || null;
+ }
+
+ /**
+ * @param {!SDK.RuntimeModel.EvaluationOptions} options
+ * @return {!Promise<!SDK.RuntimeModel.EvaluationResult>}
+ */
+ async evaluate(options) {
+ const runtimeModel = this.debuggerModel.runtimeModel();
+ if (options.throwOnSideEffect &&
+ (runtimeModel.hasSideEffectSupport() === false ||
+ (runtimeModel.hasSideEffectSupport() === null && !await runtimeModel.checkSideEffectSupport())))
+ return {error: 'Side-effect checks not supported by backend.'};
+
+ const response = await this.debuggerModel._agent.invoke_evaluateOnCallFrame({
+ callFrameId: this.id,
+ expression: options.expression,
+ objectGroup: options.objectGroup,
+ includeCommandLineAPI: options.includeCommandLineAPI,
+ silent: options.silent,
+ returnByValue: options.returnByValue,
+ generatePreview: options.generatePreview,
+ throwOnSideEffect: options.throwOnSideEffect
+ });
+ const error = response[Protocol.Error];
+ if (error) {
+ console.error(error);
+ return {error: error};
+ }
+ return {object: runtimeModel.createRemoteObject(response.result), exceptionDetails: response.exceptionDetails};
+ }
+
+ async restart() {
+ const response = await this.debuggerModel._agent.invoke_restartFrame({callFrameId: this._payload.callFrameId});
+ if (!response[Protocol.Error])
+ this.debuggerModel.stepInto();
+ }
+};
+
+
+/**
+ * @unrestricted
+ */
+SDK.DebuggerModel.Scope = class {
+ /**
+ * @param {!SDK.DebuggerModel.CallFrame} callFrame
+ * @param {number} ordinal
+ */
+ constructor(callFrame, ordinal) {
+ this._callFrame = callFrame;
+ this._payload = callFrame._payload.scopeChain[ordinal];
+ this._type = this._payload.type;
+ this._name = this._payload.name;
+ this._ordinal = ordinal;
+ this._startLocation = this._payload.startLocation ?
+ SDK.DebuggerModel.Location.fromPayload(callFrame.debuggerModel, this._payload.startLocation) :
+ null;
+ this._endLocation = this._payload.endLocation ?
+ SDK.DebuggerModel.Location.fromPayload(callFrame.debuggerModel, this._payload.endLocation) :
+ null;
+ }
+
+ /**
+ * @return {!SDK.DebuggerModel.CallFrame}
+ */
+ callFrame() {
+ return this._callFrame;
+ }
+
+ /**
+ * @return {string}
+ */
+ type() {
+ return this._type;
+ }
+
+ /**
+ * @return {string}
+ */
+ typeName() {
+ switch (this._type) {
+ case Protocol.Debugger.ScopeType.Local:
+ return Common.UIString('Local');
+ case Protocol.Debugger.ScopeType.Closure:
+ return Common.UIString('Closure');
+ case Protocol.Debugger.ScopeType.Catch:
+ return Common.UIString('Catch');
+ case Protocol.Debugger.ScopeType.Block:
+ return Common.UIString('Block');
+ case Protocol.Debugger.ScopeType.Script:
+ return Common.UIString('Script');
+ case Protocol.Debugger.ScopeType.With:
+ return Common.UIString('With Block');
+ case Protocol.Debugger.ScopeType.Global:
+ return Common.UIString('Global');
+ case Protocol.Debugger.ScopeType.Module:
+ return Common.UIString('Module');
+ }
+ return '';
+ }
+
+
+ /**
+ * @return {string|undefined}
+ */
+ name() {
+ return this._name;
+ }
+
+ /**
+ * @return {?SDK.DebuggerModel.Location}
+ */
+ startLocation() {
+ return this._startLocation;
+ }
+
+ /**
+ * @return {?SDK.DebuggerModel.Location}
+ */
+ endLocation() {
+ return this._endLocation;
+ }
+
+ /**
+ * @return {!SDK.RemoteObject}
+ */
+ object() {
+ if (this._object)
+ return this._object;
+ const runtimeModel = this._callFrame.debuggerModel._runtimeModel;
+
+ const declarativeScope =
+ this._type !== Protocol.Debugger.ScopeType.With && this._type !== Protocol.Debugger.ScopeType.Global;
+ if (declarativeScope) {
+ this._object = runtimeModel.createScopeRemoteObject(
+ this._payload.object, new SDK.ScopeRef(this._ordinal, this._callFrame.id));
+ } else {
+ this._object = runtimeModel.createRemoteObject(this._payload.object);
+ }
+
+ return this._object;
+ }
+
+ /**
+ * @return {string}
+ */
+ description() {
+ const declarativeScope =
+ this._type !== Protocol.Debugger.ScopeType.With && this._type !== Protocol.Debugger.ScopeType.Global;
+ return declarativeScope ? '' : (this._payload.object.description || '');
+ }
+};
+
+/**
+ * @unrestricted
+ */
+SDK.DebuggerPausedDetails = class {
+ /**
+ * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
+ * @param {string} reason
+ * @param {!Object|undefined} auxData
+ * @param {!Array.<string>} breakpointIds
+ * @param {!Protocol.Runtime.StackTrace=} asyncStackTrace
+ * @param {!Protocol.Runtime.StackTraceId=} asyncStackTraceId
+ */
+ constructor(debuggerModel, callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId) {
+ this.debuggerModel = debuggerModel;
+ this.callFrames = SDK.DebuggerModel.CallFrame.fromPayloadArray(debuggerModel, callFrames);
+ this.reason = reason;
+ this.auxData = auxData;
+ this.breakpointIds = breakpointIds;
+ if (asyncStackTrace)
+ this.asyncStackTrace = this._cleanRedundantFrames(asyncStackTrace);
+ this.asyncStackTraceId = asyncStackTraceId;
+ }
+
+ /**
+ * @return {?SDK.RemoteObject}
+ */
+ exception() {
+ if (this.reason !== SDK.DebuggerModel.BreakReason.Exception &&
+ this.reason !== SDK.DebuggerModel.BreakReason.PromiseRejection)
+ return null;
+ return this.debuggerModel._runtimeModel.createRemoteObject(
+ /** @type {!Protocol.Runtime.RemoteObject} */ (this.auxData));
+ }
+
+ /**
+ * @param {!Protocol.Runtime.StackTrace} asyncStackTrace
+ * @return {!Protocol.Runtime.StackTrace}
+ */
+ _cleanRedundantFrames(asyncStackTrace) {
+ let stack = asyncStackTrace;
+ let previous = null;
+ while (stack) {
+ if (stack.description === 'async function' && stack.callFrames.length)
+ stack.callFrames.shift();
+ if (previous && !stack.callFrames.length)
+ previous.parent = stack.parent;
+ else
+ previous = stack;
+ stack = stack.parent;
+ }
+ return asyncStackTrace;
+ }
+};