| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. | 13 * distribution. |
| 14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
| 17 * | 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | |
| 31 /** | 30 /** |
| 32 * @constructor | 31 * @unrestricted |
| 33 * @extends {WebInspector.SDKModel} | |
| 34 * @param {!WebInspector.Target} target | |
| 35 */ | 32 */ |
| 36 WebInspector.DebuggerModel = function(target) | 33 WebInspector.DebuggerModel = class extends WebInspector.SDKModel { |
| 37 { | 34 /** |
| 38 WebInspector.SDKModel.call(this, WebInspector.DebuggerModel, target); | 35 * @param {!WebInspector.Target} target |
| 36 */ |
| 37 constructor(target) { |
| 38 super(WebInspector.DebuggerModel, target); |
| 39 | 39 |
| 40 target.registerDebuggerDispatcher(new WebInspector.DebuggerDispatcher(this))
; | 40 target.registerDebuggerDispatcher(new WebInspector.DebuggerDispatcher(this))
; |
| 41 this._agent = target.debuggerAgent(); | 41 this._agent = target.debuggerAgent(); |
| 42 | 42 |
| 43 /** @type {?WebInspector.DebuggerPausedDetails} */ | 43 /** @type {?WebInspector.DebuggerPausedDetails} */ |
| 44 this._debuggerPausedDetails = null; | 44 this._debuggerPausedDetails = null; |
| 45 /** @type {!Object.<string, !WebInspector.Script>} */ | 45 /** @type {!Object.<string, !WebInspector.Script>} */ |
| 46 this._scripts = {}; | 46 this._scripts = {}; |
| 47 /** @type {!Map.<string, !Array.<!WebInspector.Script>>} */ | 47 /** @type {!Map.<string, !Array.<!WebInspector.Script>>} */ |
| 48 this._scriptsBySourceURL = new Map(); | 48 this._scriptsBySourceURL = new Map(); |
| 49 | 49 |
| 50 /** @type {!WebInspector.Object} */ | 50 /** @type {!WebInspector.Object} */ |
| 51 this._breakpointResolvedEventTarget = new WebInspector.Object(); | 51 this._breakpointResolvedEventTarget = new WebInspector.Object(); |
| 52 | 52 |
| 53 this._isPausing = false; | 53 this._isPausing = false; |
| 54 WebInspector.moduleSetting("pauseOnExceptionEnabled").addChangeListener(this
._pauseOnExceptionStateChanged, this); | 54 WebInspector.moduleSetting('pauseOnExceptionEnabled').addChangeListener(this
._pauseOnExceptionStateChanged, this); |
| 55 WebInspector.moduleSetting("pauseOnCaughtException").addChangeListener(this.
_pauseOnExceptionStateChanged, this); | 55 WebInspector.moduleSetting('pauseOnCaughtException').addChangeListener(this.
_pauseOnExceptionStateChanged, this); |
| 56 WebInspector.moduleSetting("enableAsyncStackTraces").addChangeListener(this.
asyncStackTracesStateChanged, this); | 56 WebInspector.moduleSetting('enableAsyncStackTraces').addChangeListener(this.
asyncStackTracesStateChanged, this); |
| 57 | 57 |
| 58 this.enableDebugger(); | 58 this.enableDebugger(); |
| 59 } |
| 60 |
| 61 /** |
| 62 * @return {!Array<!WebInspector.DebuggerModel>} |
| 63 */ |
| 64 static instances() { |
| 65 var result = []; |
| 66 for (var target of WebInspector.targetManager.targets()) { |
| 67 var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); |
| 68 if (debuggerModel) |
| 69 result.push(debuggerModel); |
| 70 } |
| 71 return result; |
| 72 } |
| 73 |
| 74 /** |
| 75 * @param {?WebInspector.Target} target |
| 76 * @return {?WebInspector.DebuggerModel} |
| 77 */ |
| 78 static fromTarget(target) { |
| 79 if (!target || !target.hasJSCapability()) |
| 80 return null; |
| 81 return /** @type {?WebInspector.DebuggerModel} */ (target.model(WebInspector
.DebuggerModel)); |
| 82 } |
| 83 |
| 84 /** |
| 85 * @return {boolean} |
| 86 */ |
| 87 debuggerEnabled() { |
| 88 return !!this._debuggerEnabled; |
| 89 } |
| 90 |
| 91 /** |
| 92 * @param {function()=} callback |
| 93 */ |
| 94 enableDebugger(callback) { |
| 95 if (this._debuggerEnabled) { |
| 96 if (callback) |
| 97 callback(); |
| 98 return; |
| 99 } |
| 100 this._agent.enable(callback); |
| 101 this._debuggerEnabled = true; |
| 102 this._pauseOnExceptionStateChanged(); |
| 103 this.asyncStackTracesStateChanged(); |
| 104 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasE
nabled); |
| 105 } |
| 106 |
| 107 /** |
| 108 * @param {function()=} callback |
| 109 */ |
| 110 disableDebugger(callback) { |
| 111 if (!this._debuggerEnabled) { |
| 112 if (callback) |
| 113 callback(); |
| 114 return; |
| 115 } |
| 116 |
| 117 this._agent.disable(callback); |
| 118 this._debuggerEnabled = false; |
| 119 this._isPausing = false; |
| 120 this.asyncStackTracesStateChanged(); |
| 121 this.globalObjectCleared(); |
| 122 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasD
isabled); |
| 123 } |
| 124 |
| 125 /** |
| 126 * @param {boolean} skip |
| 127 */ |
| 128 _skipAllPauses(skip) { |
| 129 if (this._skipAllPausesTimeout) { |
| 130 clearTimeout(this._skipAllPausesTimeout); |
| 131 delete this._skipAllPausesTimeout; |
| 132 } |
| 133 this._agent.setSkipAllPauses(skip); |
| 134 } |
| 135 |
| 136 /** |
| 137 * @param {number} timeout |
| 138 */ |
| 139 skipAllPausesUntilReloadOrTimeout(timeout) { |
| 140 if (this._skipAllPausesTimeout) |
| 141 clearTimeout(this._skipAllPausesTimeout); |
| 142 this._agent.setSkipAllPauses(true); |
| 143 // If reload happens before the timeout, the flag will be already unset and
the timeout callback won't change anything. |
| 144 this._skipAllPausesTimeout = setTimeout(this._skipAllPauses.bind(this, false
), timeout); |
| 145 } |
| 146 |
| 147 _pauseOnExceptionStateChanged() { |
| 148 var state; |
| 149 if (!WebInspector.moduleSetting('pauseOnExceptionEnabled').get()) { |
| 150 state = WebInspector.DebuggerModel.PauseOnExceptionsState.DontPauseOnExcep
tions; |
| 151 } else if (WebInspector.moduleSetting('pauseOnCaughtException').get()) { |
| 152 state = WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnAllExcept
ions; |
| 153 } else { |
| 154 state = WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnUncaughtE
xceptions; |
| 155 } |
| 156 this._agent.setPauseOnExceptions(state); |
| 157 } |
| 158 |
| 159 asyncStackTracesStateChanged() { |
| 160 const maxAsyncStackChainDepth = 4; |
| 161 var enabled = WebInspector.moduleSetting('enableAsyncStackTraces').get() &&
this._debuggerEnabled; |
| 162 this._agent.setAsyncCallStackDepth(enabled ? maxAsyncStackChainDepth : 0); |
| 163 } |
| 164 |
| 165 stepInto() { |
| 166 this._agent.stepInto(); |
| 167 } |
| 168 |
| 169 stepOver() { |
| 170 this._agent.stepOver(); |
| 171 } |
| 172 |
| 173 stepOut() { |
| 174 this._agent.stepOut(); |
| 175 } |
| 176 |
| 177 resume() { |
| 178 this._agent.resume(); |
| 179 this._isPausing = false; |
| 180 } |
| 181 |
| 182 pause() { |
| 183 this._isPausing = true; |
| 184 this._skipAllPauses(false); |
| 185 this._agent.pause(); |
| 186 } |
| 187 |
| 188 /** |
| 189 * @param {boolean} active |
| 190 */ |
| 191 setBreakpointsActive(active) { |
| 192 this._agent.setBreakpointsActive(active); |
| 193 } |
| 194 |
| 195 /** |
| 196 * @param {string} url |
| 197 * @param {number} lineNumber |
| 198 * @param {number=} columnNumber |
| 199 * @param {string=} condition |
| 200 * @param {function(?DebuggerAgent.BreakpointId, !Array.<!WebInspector.Debugge
rModel.Location>)=} callback |
| 201 */ |
| 202 setBreakpointByURL(url, lineNumber, columnNumber, condition, callback) { |
| 203 // Adjust column if needed. |
| 204 var minColumnNumber = 0; |
| 205 var scripts = this._scriptsBySourceURL.get(url) || []; |
| 206 for (var i = 0, l = scripts.length; i < l; ++i) { |
| 207 var script = scripts[i]; |
| 208 if (lineNumber === script.lineOffset) |
| 209 minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, script.col
umnOffset) : script.columnOffset; |
| 210 } |
| 211 columnNumber = Math.max(columnNumber, minColumnNumber); |
| 212 |
| 213 var target = this.target(); |
| 214 /** |
| 215 * @param {?Protocol.Error} error |
| 216 * @param {!DebuggerAgent.BreakpointId} breakpointId |
| 217 * @param {!Array.<!DebuggerAgent.Location>} locations |
| 218 * @this {WebInspector.DebuggerModel} |
| 219 */ |
| 220 function didSetBreakpoint(error, breakpointId, locations) { |
| 221 if (callback) { |
| 222 var rawLocations = locations ? |
| 223 locations.map( |
| 224 WebInspector.DebuggerModel.Location.fromPayload.bind(WebInspecto
r.DebuggerModel.Location, this)) : |
| 225 []; |
| 226 callback(error ? null : breakpointId, rawLocations); |
| 227 } |
| 228 } |
| 229 this._agent.setBreakpointByUrl(lineNumber, url, undefined, columnNumber, con
dition, didSetBreakpoint.bind(this)); |
| 230 } |
| 231 |
| 232 /** |
| 233 * @param {!WebInspector.DebuggerModel.Location} rawLocation |
| 234 * @param {string} condition |
| 235 * @param {function(?DebuggerAgent.BreakpointId, !Array.<!WebInspector.Debugge
rModel.Location>)=} callback |
| 236 */ |
| 237 setBreakpointBySourceId(rawLocation, condition, callback) { |
| 238 var target = this.target(); |
| 239 |
| 240 /** |
| 241 * @this {WebInspector.DebuggerModel} |
| 242 * @param {?Protocol.Error} error |
| 243 * @param {!DebuggerAgent.BreakpointId} breakpointId |
| 244 * @param {!DebuggerAgent.Location} actualLocation |
| 245 */ |
| 246 function didSetBreakpoint(error, breakpointId, actualLocation) { |
| 247 if (callback) { |
| 248 if (error || !actualLocation) { |
| 249 callback(null, []); |
| 250 return; |
| 251 } |
| 252 callback(breakpointId, [WebInspector.DebuggerModel.Location.fromPayload(
this, actualLocation)]); |
| 253 } |
| 254 } |
| 255 this._agent.setBreakpoint(rawLocation.payload(), condition, didSetBreakpoint
.bind(this)); |
| 256 } |
| 257 |
| 258 /** |
| 259 * @param {!DebuggerAgent.BreakpointId} breakpointId |
| 260 * @param {function()=} callback |
| 261 */ |
| 262 removeBreakpoint(breakpointId, callback) { |
| 263 this._agent.removeBreakpoint(breakpointId, innerCallback); |
| 264 |
| 265 /** |
| 266 * @param {?Protocol.Error} error |
| 267 */ |
| 268 function innerCallback(error) { |
| 269 if (error) |
| 270 console.error('Failed to remove breakpoint: ' + error); |
| 271 if (callback) |
| 272 callback(); |
| 273 } |
| 274 } |
| 275 |
| 276 /** |
| 277 * @param {!DebuggerAgent.BreakpointId} breakpointId |
| 278 * @param {!DebuggerAgent.Location} location |
| 279 */ |
| 280 _breakpointResolved(breakpointId, location) { |
| 281 this._breakpointResolvedEventTarget.dispatchEventToListeners( |
| 282 breakpointId, WebInspector.DebuggerModel.Location.fromPayload(this, loca
tion)); |
| 283 } |
| 284 |
| 285 globalObjectCleared() { |
| 286 this._setDebuggerPausedDetails(null); |
| 287 this._reset(); |
| 288 // TODO(dgozman): move clients to ExecutionContextDestroyed/ScriptCollected
events. |
| 289 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.GlobalObject
Cleared); |
| 290 } |
| 291 |
| 292 _reset() { |
| 293 this._scripts = {}; |
| 294 this._scriptsBySourceURL.clear(); |
| 295 } |
| 296 |
| 297 /** |
| 298 * @return {!Object.<string, !WebInspector.Script>} |
| 299 */ |
| 300 get scripts() { |
| 301 return this._scripts; |
| 302 } |
| 303 |
| 304 /** |
| 305 * @param {!RuntimeAgent.ScriptId} scriptId |
| 306 * @return {?WebInspector.Script} |
| 307 */ |
| 308 scriptForId(scriptId) { |
| 309 return this._scripts[scriptId] || null; |
| 310 } |
| 311 |
| 312 /** |
| 313 * @return {!Array.<!WebInspector.Script>} |
| 314 */ |
| 315 scriptsForSourceURL(sourceURL) { |
| 316 if (!sourceURL) |
| 317 return []; |
| 318 return this._scriptsBySourceURL.get(sourceURL) || []; |
| 319 } |
| 320 |
| 321 /** |
| 322 * @param {!RuntimeAgent.ScriptId} scriptId |
| 323 * @param {string} newSource |
| 324 * @param {function(?Protocol.Error, !RuntimeAgent.ExceptionDetails=)} callbac
k |
| 325 */ |
| 326 setScriptSource(scriptId, newSource, callback) { |
| 327 this._scripts[scriptId].editSource(newSource, this._didEditScriptSource.bind
(this, scriptId, newSource, callback)); |
| 328 } |
| 329 |
| 330 /** |
| 331 * @param {!RuntimeAgent.ScriptId} scriptId |
| 332 * @param {string} newSource |
| 333 * @param {function(?Protocol.Error, !RuntimeAgent.ExceptionDetails=)} callbac
k |
| 334 * @param {?Protocol.Error} error |
| 335 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails |
| 336 * @param {!Array.<!DebuggerAgent.CallFrame>=} callFrames |
| 337 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace |
| 338 * @param {boolean=} needsStepIn |
| 339 */ |
| 340 _didEditScriptSource( |
| 341 scriptId, |
| 342 newSource, |
| 343 callback, |
| 344 error, |
| 345 exceptionDetails, |
| 346 callFrames, |
| 347 asyncStackTrace, |
| 348 needsStepIn) { |
| 349 if (needsStepIn) { |
| 350 this.stepInto(); |
| 351 this._pendingLiveEditCallback = callback.bind(this, error, exceptionDetail
s); |
| 352 return; |
| 353 } |
| 354 |
| 355 if (!error && callFrames && callFrames.length) |
| 356 this._pausedScript( |
| 357 callFrames, this._debuggerPausedDetails.reason, this._debuggerPausedDe
tails.auxData, |
| 358 this._debuggerPausedDetails.breakpointIds, asyncStackTrace); |
| 359 callback(error, exceptionDetails); |
| 360 } |
| 361 |
| 362 /** |
| 363 * @return {?Array.<!WebInspector.DebuggerModel.CallFrame>} |
| 364 */ |
| 365 get callFrames() { |
| 366 return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFrames
: null; |
| 367 } |
| 368 |
| 369 /** |
| 370 * @return {?WebInspector.DebuggerPausedDetails} |
| 371 */ |
| 372 debuggerPausedDetails() { |
| 373 return this._debuggerPausedDetails; |
| 374 } |
| 375 |
| 376 /** |
| 377 * @param {?WebInspector.DebuggerPausedDetails} debuggerPausedDetails |
| 378 * @return {boolean} |
| 379 */ |
| 380 _setDebuggerPausedDetails(debuggerPausedDetails) { |
| 381 this._isPausing = false; |
| 382 this._debuggerPausedDetails = debuggerPausedDetails; |
| 383 if (this._debuggerPausedDetails) { |
| 384 if (Runtime.experiments.isEnabled('emptySourceMapAutoStepping')) { |
| 385 if (this.dispatchEventToListeners( |
| 386 WebInspector.DebuggerModel.Events.BeforeDebuggerPaused, this._de
buggerPausedDetails)) { |
| 387 return false; |
| 388 } |
| 389 } |
| 390 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPa
used, this._debuggerPausedDetails); |
| 391 } |
| 392 if (debuggerPausedDetails) |
| 393 this.setSelectedCallFrame(debuggerPausedDetails.callFrames[0]); |
| 394 else |
| 395 this.setSelectedCallFrame(null); |
| 396 return true; |
| 397 } |
| 398 |
| 399 /** |
| 400 * @param {!Array.<!DebuggerAgent.CallFrame>} callFrames |
| 401 * @param {string} reason |
| 402 * @param {!Object|undefined} auxData |
| 403 * @param {!Array.<string>} breakpointIds |
| 404 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace |
| 405 */ |
| 406 _pausedScript(callFrames, reason, auxData, breakpointIds, asyncStackTrace) { |
| 407 var pausedDetails = |
| 408 new WebInspector.DebuggerPausedDetails(this, callFrames, reason, auxData
, breakpointIds, asyncStackTrace); |
| 409 if (this._setDebuggerPausedDetails(pausedDetails)) { |
| 410 if (this._pendingLiveEditCallback) { |
| 411 var callback = this._pendingLiveEditCallback; |
| 412 delete this._pendingLiveEditCallback; |
| 413 callback(); |
| 414 } |
| 415 } else { |
| 416 this._agent.stepInto(); |
| 417 } |
| 418 } |
| 419 |
| 420 _resumedScript() { |
| 421 this._setDebuggerPausedDetails(null); |
| 422 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResu
med); |
| 423 } |
| 424 |
| 425 /** |
| 426 * @param {!RuntimeAgent.ScriptId} scriptId |
| 427 * @param {string} sourceURL |
| 428 * @param {number} startLine |
| 429 * @param {number} startColumn |
| 430 * @param {number} endLine |
| 431 * @param {number} endColumn |
| 432 * @param {!RuntimeAgent.ExecutionContextId} executionContextId |
| 433 * @param {string} hash |
| 434 * @param {*|undefined} executionContextAuxData |
| 435 * @param {boolean} isLiveEdit |
| 436 * @param {string=} sourceMapURL |
| 437 * @param {boolean=} hasSourceURL |
| 438 * @param {boolean=} hasSyntaxError |
| 439 * @return {!WebInspector.Script} |
| 440 */ |
| 441 _parsedScriptSource( |
| 442 scriptId, |
| 443 sourceURL, |
| 444 startLine, |
| 445 startColumn, |
| 446 endLine, |
| 447 endColumn, |
| 448 executionContextId, |
| 449 hash, |
| 450 executionContextAuxData, |
| 451 isLiveEdit, |
| 452 sourceMapURL, |
| 453 hasSourceURL, |
| 454 hasSyntaxError) { |
| 455 var isContentScript = false; |
| 456 if (executionContextAuxData && ('isDefault' in executionContextAuxData)) |
| 457 isContentScript = !executionContextAuxData['isDefault']; |
| 458 // Support file URL for node.js. |
| 459 if (this.target().isNodeJS() && sourceURL && sourceURL.startsWith('/')) |
| 460 sourceURL = WebInspector.ParsedURL.platformPathToURL(sourceURL); |
| 461 var script = new WebInspector.Script( |
| 462 this, scriptId, sourceURL, startLine, startColumn, endLine, endColumn, e
xecutionContextId, hash, |
| 463 isContentScript, isLiveEdit, sourceMapURL, hasSourceURL); |
| 464 this._registerScript(script); |
| 465 if (!hasSyntaxError) |
| 466 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScri
ptSource, script); |
| 467 else |
| 468 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.FailedToPa
rseScriptSource, script); |
| 469 return script; |
| 470 } |
| 471 |
| 472 /** |
| 473 * @param {!WebInspector.Script} script |
| 474 */ |
| 475 _registerScript(script) { |
| 476 this._scripts[script.scriptId] = script; |
| 477 if (script.isAnonymousScript()) |
| 478 return; |
| 479 |
| 480 var scripts = this._scriptsBySourceURL.get(script.sourceURL); |
| 481 if (!scripts) { |
| 482 scripts = []; |
| 483 this._scriptsBySourceURL.set(script.sourceURL, scripts); |
| 484 } |
| 485 scripts.push(script); |
| 486 } |
| 487 |
| 488 /** |
| 489 * @param {!WebInspector.Script} script |
| 490 * @param {number} lineNumber |
| 491 * @param {number} columnNumber |
| 492 * @return {?WebInspector.DebuggerModel.Location} |
| 493 */ |
| 494 createRawLocation(script, lineNumber, columnNumber) { |
| 495 if (script.sourceURL) |
| 496 return this.createRawLocationByURL(script.sourceURL, lineNumber, columnNum
ber); |
| 497 return new WebInspector.DebuggerModel.Location(this, script.scriptId, lineNu
mber, columnNumber); |
| 498 } |
| 499 |
| 500 /** |
| 501 * @param {string} sourceURL |
| 502 * @param {number} lineNumber |
| 503 * @param {number} columnNumber |
| 504 * @return {?WebInspector.DebuggerModel.Location} |
| 505 */ |
| 506 createRawLocationByURL(sourceURL, lineNumber, columnNumber) { |
| 507 var closestScript = null; |
| 508 var scripts = this._scriptsBySourceURL.get(sourceURL) || []; |
| 509 for (var i = 0, l = scripts.length; i < l; ++i) { |
| 510 var script = scripts[i]; |
| 511 if (!closestScript) |
| 512 closestScript = script; |
| 513 if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber &&
script.columnOffset > columnNumber)) |
| 514 continue; |
| 515 if (script.endLine < lineNumber || (script.endLine === lineNumber && scrip
t.endColumn <= columnNumber)) |
| 516 continue; |
| 517 closestScript = script; |
| 518 break; |
| 519 } |
| 520 return closestScript ? |
| 521 new WebInspector.DebuggerModel.Location(this, closestScript.scriptId, li
neNumber, columnNumber) : |
| 522 null; |
| 523 } |
| 524 |
| 525 /** |
| 526 * @param {!RuntimeAgent.ScriptId} scriptId |
| 527 * @param {number} lineNumber |
| 528 * @param {number} columnNumber |
| 529 * @return {?WebInspector.DebuggerModel.Location} |
| 530 */ |
| 531 createRawLocationByScriptId(scriptId, lineNumber, columnNumber) { |
| 532 var script = this.scriptForId(scriptId); |
| 533 return script ? this.createRawLocation(script, lineNumber, columnNumber) : n
ull; |
| 534 } |
| 535 |
| 536 /** |
| 537 * @param {!RuntimeAgent.StackTrace} stackTrace |
| 538 * @return {!Array<!WebInspector.DebuggerModel.Location>} |
| 539 */ |
| 540 createRawLocationsByStackTrace(stackTrace) { |
| 541 var frames = []; |
| 542 while (stackTrace) { |
| 543 for (var frame of stackTrace.callFrames) |
| 544 frames.push(frame); |
| 545 stackTrace = stackTrace.parent; |
| 546 } |
| 547 |
| 548 var rawLocations = []; |
| 549 for (var frame of frames) { |
| 550 var rawLocation = this.createRawLocationByScriptId(frame.scriptId, frame.l
ineNumber, frame.columnNumber); |
| 551 if (rawLocation) |
| 552 rawLocations.push(rawLocation); |
| 553 } |
| 554 return rawLocations; |
| 555 } |
| 556 |
| 557 /** |
| 558 * @return {boolean} |
| 559 */ |
| 560 isPaused() { |
| 561 return !!this.debuggerPausedDetails(); |
| 562 } |
| 563 |
| 564 /** |
| 565 * @return {boolean} |
| 566 */ |
| 567 isPausing() { |
| 568 return this._isPausing; |
| 569 } |
| 570 |
| 571 /** |
| 572 * @param {?WebInspector.DebuggerModel.CallFrame} callFrame |
| 573 */ |
| 574 setSelectedCallFrame(callFrame) { |
| 575 this._selectedCallFrame = callFrame; |
| 576 if (!this._selectedCallFrame) |
| 577 return; |
| 578 |
| 579 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.CallFrameSel
ected, callFrame); |
| 580 } |
| 581 |
| 582 /** |
| 583 * @return {?WebInspector.DebuggerModel.CallFrame} |
| 584 */ |
| 585 selectedCallFrame() { |
| 586 return this._selectedCallFrame; |
| 587 } |
| 588 |
| 589 /** |
| 590 * @param {string} code |
| 591 * @param {string} objectGroup |
| 592 * @param {boolean} includeCommandLineAPI |
| 593 * @param {boolean} silent |
| 594 * @param {boolean} returnByValue |
| 595 * @param {boolean} generatePreview |
| 596 * @param {function(?WebInspector.RemoteObject, !RuntimeAgent.ExceptionDetails
=)} callback |
| 597 */ |
| 598 evaluateOnSelectedCallFrame( |
| 599 code, |
| 600 objectGroup, |
| 601 includeCommandLineAPI, |
| 602 silent, |
| 603 returnByValue, |
| 604 generatePreview, |
| 605 callback) { |
| 606 /** |
| 607 * @param {?RuntimeAgent.RemoteObject} result |
| 608 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails |
| 609 * @this {WebInspector.DebuggerModel} |
| 610 */ |
| 611 function didEvaluate(result, exceptionDetails) { |
| 612 if (!result) |
| 613 callback(null); |
| 614 else |
| 615 callback(this.target().runtimeModel.createRemoteObject(result), exceptio
nDetails); |
| 616 } |
| 617 |
| 618 this.selectedCallFrame().evaluate( |
| 619 code, objectGroup, includeCommandLineAPI, silent, returnByValue, generat
ePreview, didEvaluate.bind(this)); |
| 620 } |
| 621 |
| 622 /** |
| 623 * @param {!WebInspector.RemoteObject} remoteObject |
| 624 * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>} |
| 625 */ |
| 626 functionDetailsPromise(remoteObject) { |
| 627 return remoteObject.getAllPropertiesPromise(/* accessorPropertiesOnly */ fal
se).then(buildDetails.bind(this)); |
| 628 |
| 629 /** |
| 630 * @param {!{properties: ?Array.<!WebInspector.RemoteObjectProperty>, intern
alProperties: ?Array.<!WebInspector.RemoteObjectProperty>}} response |
| 631 * @return {?WebInspector.DebuggerModel.FunctionDetails} |
| 632 * @this {!WebInspector.DebuggerModel} |
| 633 */ |
| 634 function buildDetails(response) { |
| 635 if (!response) |
| 636 return null; |
| 637 var location = null; |
| 638 if (response.internalProperties) { |
| 639 for (var prop of response.internalProperties) { |
| 640 if (prop.name === '[[FunctionLocation]]') |
| 641 location = prop.value; |
| 642 } |
| 643 } |
| 644 var functionName = null; |
| 645 if (response.properties) { |
| 646 for (var prop of response.properties) { |
| 647 if (prop.name === 'name' && prop.value && prop.value.type === 'string'
) |
| 648 functionName = prop.value; |
| 649 if (prop.name === 'displayName' && prop.value && prop.value.type === '
string') { |
| 650 functionName = prop.value; |
| 651 break; |
| 652 } |
| 653 } |
| 654 } |
| 655 var debuggerLocation = null; |
| 656 if (location) |
| 657 debuggerLocation = this.createRawLocationByScriptId( |
| 658 location.value.scriptId, location.value.lineNumber, location.value.c
olumnNumber); |
| 659 return {location: debuggerLocation, functionName: functionName ? functionN
ame.value : ''}; |
| 660 } |
| 661 } |
| 662 |
| 663 /** |
| 664 * @param {number} scopeNumber |
| 665 * @param {string} variableName |
| 666 * @param {!RuntimeAgent.CallArgument} newValue |
| 667 * @param {string} callFrameId |
| 668 * @param {function(string=)=} callback |
| 669 */ |
| 670 setVariableValue(scopeNumber, variableName, newValue, callFrameId, callback) { |
| 671 this._agent.setVariableValue(scopeNumber, variableName, newValue, callFrameI
d, innerCallback); |
| 672 |
| 673 /** |
| 674 * @param {?Protocol.Error} error |
| 675 */ |
| 676 function innerCallback(error) { |
| 677 if (error) { |
| 678 console.error(error); |
| 679 if (callback) |
| 680 callback(error); |
| 681 return; |
| 682 } |
| 683 if (callback) |
| 684 callback(); |
| 685 } |
| 686 } |
| 687 |
| 688 /** |
| 689 * @param {!DebuggerAgent.BreakpointId} breakpointId |
| 690 * @param {function(!WebInspector.Event)} listener |
| 691 * @param {!Object=} thisObject |
| 692 */ |
| 693 addBreakpointListener(breakpointId, listener, thisObject) { |
| 694 this._breakpointResolvedEventTarget.addEventListener(breakpointId, listener,
thisObject); |
| 695 } |
| 696 |
| 697 /** |
| 698 * @param {!DebuggerAgent.BreakpointId} breakpointId |
| 699 * @param {function(!WebInspector.Event)} listener |
| 700 * @param {!Object=} thisObject |
| 701 */ |
| 702 removeBreakpointListener(breakpointId, listener, thisObject) { |
| 703 this._breakpointResolvedEventTarget.removeEventListener(breakpointId, listen
er, thisObject); |
| 704 } |
| 705 |
| 706 /** |
| 707 * @param {!Array<string>} patterns |
| 708 * @return {!Promise<boolean>} |
| 709 */ |
| 710 setBlackboxPatterns(patterns) { |
| 711 var callback; |
| 712 var promise = new Promise(fulfill => callback = fulfill); |
| 713 this._agent.setBlackboxPatterns(patterns, patternsUpdated); |
| 714 return promise; |
| 715 |
| 716 /** |
| 717 * @param {?Protocol.Error} error |
| 718 */ |
| 719 function patternsUpdated(error) { |
| 720 if (error) |
| 721 console.error(error); |
| 722 callback(!error); |
| 723 } |
| 724 } |
| 725 |
| 726 /** |
| 727 * @override |
| 728 */ |
| 729 dispose() { |
| 730 WebInspector.moduleSetting('pauseOnExceptionEnabled') |
| 731 .removeChangeListener(this._pauseOnExceptionStateChanged, this); |
| 732 WebInspector.moduleSetting('pauseOnCaughtException').removeChangeListener(th
is._pauseOnExceptionStateChanged, this); |
| 733 WebInspector.moduleSetting('enableAsyncStackTraces').removeChangeListener(th
is.asyncStackTracesStateChanged, this); |
| 734 } |
| 735 |
| 736 /** |
| 737 * @override |
| 738 * @return {!Promise} |
| 739 */ |
| 740 suspendModel() { |
| 741 return new Promise(promiseBody.bind(this)); |
| 742 |
| 743 /** |
| 744 * @param {function()} fulfill |
| 745 * @this {WebInspector.DebuggerModel} |
| 746 */ |
| 747 function promiseBody(fulfill) { |
| 748 this.disableDebugger(fulfill); |
| 749 } |
| 750 } |
| 751 |
| 752 /** |
| 753 * @override |
| 754 * @return {!Promise} |
| 755 */ |
| 756 resumeModel() { |
| 757 return new Promise(promiseBody.bind(this)); |
| 758 |
| 759 /** |
| 760 * @param {function()} fulfill |
| 761 * @this {WebInspector.DebuggerModel} |
| 762 */ |
| 763 function promiseBody(fulfill) { |
| 764 this.enableDebugger(fulfill); |
| 765 } |
| 766 } |
| 59 }; | 767 }; |
| 60 | 768 |
| 61 /** @typedef {{location: ?WebInspector.DebuggerModel.Location, functionName: str
ing}} */ | 769 /** @typedef {{location: ?WebInspector.DebuggerModel.Location, functionName: str
ing}} */ |
| 62 WebInspector.DebuggerModel.FunctionDetails; | 770 WebInspector.DebuggerModel.FunctionDetails; |
| 63 | 771 |
| 64 /** | 772 /** |
| 65 * Keep these in sync with WebCore::V8Debugger | 773 * Keep these in sync with WebCore::V8Debugger |
| 66 * | 774 * |
| 67 * @enum {string} | 775 * @enum {string} |
| 68 */ | 776 */ |
| 69 WebInspector.DebuggerModel.PauseOnExceptionsState = { | 777 WebInspector.DebuggerModel.PauseOnExceptionsState = { |
| 70 DontPauseOnExceptions : "none", | 778 DontPauseOnExceptions: 'none', |
| 71 PauseOnAllExceptions : "all", | 779 PauseOnAllExceptions: 'all', |
| 72 PauseOnUncaughtExceptions: "uncaught" | 780 PauseOnUncaughtExceptions: 'uncaught' |
| 73 }; | 781 }; |
| 74 | 782 |
| 75 /** @enum {symbol} */ | 783 /** @enum {symbol} */ |
| 76 WebInspector.DebuggerModel.Events = { | 784 WebInspector.DebuggerModel.Events = { |
| 77 DebuggerWasEnabled: Symbol("DebuggerWasEnabled"), | 785 DebuggerWasEnabled: Symbol('DebuggerWasEnabled'), |
| 78 DebuggerWasDisabled: Symbol("DebuggerWasDisabled"), | 786 DebuggerWasDisabled: Symbol('DebuggerWasDisabled'), |
| 79 BeforeDebuggerPaused: Symbol("BeforeDebuggerPaused"), | 787 BeforeDebuggerPaused: Symbol('BeforeDebuggerPaused'), |
| 80 DebuggerPaused: Symbol("DebuggerPaused"), | 788 DebuggerPaused: Symbol('DebuggerPaused'), |
| 81 DebuggerResumed: Symbol("DebuggerResumed"), | 789 DebuggerResumed: Symbol('DebuggerResumed'), |
| 82 ParsedScriptSource: Symbol("ParsedScriptSource"), | 790 ParsedScriptSource: Symbol('ParsedScriptSource'), |
| 83 FailedToParseScriptSource: Symbol("FailedToParseScriptSource"), | 791 FailedToParseScriptSource: Symbol('FailedToParseScriptSource'), |
| 84 GlobalObjectCleared: Symbol("GlobalObjectCleared"), | 792 GlobalObjectCleared: Symbol('GlobalObjectCleared'), |
| 85 CallFrameSelected: Symbol("CallFrameSelected"), | 793 CallFrameSelected: Symbol('CallFrameSelected'), |
| 86 ConsoleCommandEvaluatedInSelectedCallFrame: Symbol("ConsoleCommandEvaluatedI
nSelectedCallFrame") | 794 ConsoleCommandEvaluatedInSelectedCallFrame: Symbol('ConsoleCommandEvaluatedInS
electedCallFrame') |
| 87 }; | 795 }; |
| 88 | 796 |
| 89 /** @enum {string} */ | 797 /** @enum {string} */ |
| 90 WebInspector.DebuggerModel.BreakReason = { | 798 WebInspector.DebuggerModel.BreakReason = { |
| 91 DOM: "DOM", | 799 DOM: 'DOM', |
| 92 EventListener: "EventListener", | 800 EventListener: 'EventListener', |
| 93 XHR: "XHR", | 801 XHR: 'XHR', |
| 94 Exception: "exception", | 802 Exception: 'exception', |
| 95 PromiseRejection: "promiseRejection", | 803 PromiseRejection: 'promiseRejection', |
| 96 Assert: "assert", | 804 Assert: 'assert', |
| 97 DebugCommand: "debugCommand", | 805 DebugCommand: 'debugCommand', |
| 98 Other: "other" | 806 Other: 'other' |
| 99 }; | 807 }; |
| 100 | 808 |
| 101 WebInspector.DebuggerModel.prototype = { | 809 WebInspector.DebuggerEventTypes = { |
| 102 /** | 810 JavaScriptPause: 0, |
| 103 * @return {boolean} | 811 JavaScriptBreakpoint: 1, |
| 104 */ | 812 NativeBreakpoint: 2 |
| 105 debuggerEnabled: function() | |
| 106 { | |
| 107 return !!this._debuggerEnabled; | |
| 108 }, | |
| 109 | |
| 110 /** | |
| 111 * @param {function()=} callback | |
| 112 */ | |
| 113 enableDebugger: function(callback) | |
| 114 { | |
| 115 if (this._debuggerEnabled) { | |
| 116 if (callback) | |
| 117 callback(); | |
| 118 return; | |
| 119 } | |
| 120 this._agent.enable(callback); | |
| 121 this._debuggerEnabled = true; | |
| 122 this._pauseOnExceptionStateChanged(); | |
| 123 this.asyncStackTracesStateChanged(); | |
| 124 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Debugger
WasEnabled); | |
| 125 }, | |
| 126 | |
| 127 /** | |
| 128 * @param {function()=} callback | |
| 129 */ | |
| 130 disableDebugger: function(callback) | |
| 131 { | |
| 132 if (!this._debuggerEnabled) { | |
| 133 if (callback) | |
| 134 callback(); | |
| 135 return; | |
| 136 } | |
| 137 | |
| 138 this._agent.disable(callback); | |
| 139 this._debuggerEnabled = false; | |
| 140 this._isPausing = false; | |
| 141 this.asyncStackTracesStateChanged(); | |
| 142 this.globalObjectCleared(); | |
| 143 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Debugger
WasDisabled); | |
| 144 }, | |
| 145 | |
| 146 /** | |
| 147 * @param {boolean} skip | |
| 148 */ | |
| 149 _skipAllPauses: function(skip) | |
| 150 { | |
| 151 if (this._skipAllPausesTimeout) { | |
| 152 clearTimeout(this._skipAllPausesTimeout); | |
| 153 delete this._skipAllPausesTimeout; | |
| 154 } | |
| 155 this._agent.setSkipAllPauses(skip); | |
| 156 }, | |
| 157 | |
| 158 /** | |
| 159 * @param {number} timeout | |
| 160 */ | |
| 161 skipAllPausesUntilReloadOrTimeout: function(timeout) | |
| 162 { | |
| 163 if (this._skipAllPausesTimeout) | |
| 164 clearTimeout(this._skipAllPausesTimeout); | |
| 165 this._agent.setSkipAllPauses(true); | |
| 166 // If reload happens before the timeout, the flag will be already unset
and the timeout callback won't change anything. | |
| 167 this._skipAllPausesTimeout = setTimeout(this._skipAllPauses.bind(this, f
alse), timeout); | |
| 168 }, | |
| 169 | |
| 170 _pauseOnExceptionStateChanged: function() | |
| 171 { | |
| 172 var state; | |
| 173 if (!WebInspector.moduleSetting("pauseOnExceptionEnabled").get()) { | |
| 174 state = WebInspector.DebuggerModel.PauseOnExceptionsState.DontPauseO
nExceptions; | |
| 175 } else if (WebInspector.moduleSetting("pauseOnCaughtException").get()) { | |
| 176 state = WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnAll
Exceptions; | |
| 177 } else { | |
| 178 state = WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnUnc
aughtExceptions; | |
| 179 } | |
| 180 this._agent.setPauseOnExceptions(state); | |
| 181 }, | |
| 182 | |
| 183 asyncStackTracesStateChanged: function() | |
| 184 { | |
| 185 const maxAsyncStackChainDepth = 4; | |
| 186 var enabled = WebInspector.moduleSetting("enableAsyncStackTraces").get()
&& this._debuggerEnabled; | |
| 187 this._agent.setAsyncCallStackDepth(enabled ? maxAsyncStackChainDepth : 0
); | |
| 188 }, | |
| 189 | |
| 190 stepInto: function() | |
| 191 { | |
| 192 this._agent.stepInto(); | |
| 193 }, | |
| 194 | |
| 195 stepOver: function() | |
| 196 { | |
| 197 this._agent.stepOver(); | |
| 198 }, | |
| 199 | |
| 200 stepOut: function() | |
| 201 { | |
| 202 this._agent.stepOut(); | |
| 203 }, | |
| 204 | |
| 205 resume: function() | |
| 206 { | |
| 207 this._agent.resume(); | |
| 208 this._isPausing = false; | |
| 209 }, | |
| 210 | |
| 211 pause: function() | |
| 212 { | |
| 213 this._isPausing = true; | |
| 214 this._skipAllPauses(false); | |
| 215 this._agent.pause(); | |
| 216 }, | |
| 217 | |
| 218 /** | |
| 219 * @param {boolean} active | |
| 220 */ | |
| 221 setBreakpointsActive: function(active) | |
| 222 { | |
| 223 this._agent.setBreakpointsActive(active); | |
| 224 }, | |
| 225 | |
| 226 /** | |
| 227 * @param {string} url | |
| 228 * @param {number} lineNumber | |
| 229 * @param {number=} columnNumber | |
| 230 * @param {string=} condition | |
| 231 * @param {function(?DebuggerAgent.BreakpointId, !Array.<!WebInspector.Debug
gerModel.Location>)=} callback | |
| 232 */ | |
| 233 setBreakpointByURL: function(url, lineNumber, columnNumber, condition, callb
ack) | |
| 234 { | |
| 235 // Adjust column if needed. | |
| 236 var minColumnNumber = 0; | |
| 237 var scripts = this._scriptsBySourceURL.get(url) || []; | |
| 238 for (var i = 0, l = scripts.length; i < l; ++i) { | |
| 239 var script = scripts[i]; | |
| 240 if (lineNumber === script.lineOffset) | |
| 241 minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, sc
ript.columnOffset) : script.columnOffset; | |
| 242 } | |
| 243 columnNumber = Math.max(columnNumber, minColumnNumber); | |
| 244 | |
| 245 var target = this.target(); | |
| 246 /** | |
| 247 * @param {?Protocol.Error} error | |
| 248 * @param {!DebuggerAgent.BreakpointId} breakpointId | |
| 249 * @param {!Array.<!DebuggerAgent.Location>} locations | |
| 250 * @this {WebInspector.DebuggerModel} | |
| 251 */ | |
| 252 function didSetBreakpoint(error, breakpointId, locations) | |
| 253 { | |
| 254 if (callback) { | |
| 255 var rawLocations = locations ? locations.map(WebInspector.Debugg
erModel.Location.fromPayload.bind(WebInspector.DebuggerModel.Location, this)) :
[]; | |
| 256 callback(error ? null : breakpointId, rawLocations); | |
| 257 } | |
| 258 } | |
| 259 this._agent.setBreakpointByUrl(lineNumber, url, undefined, columnNumber,
condition, didSetBreakpoint.bind(this)); | |
| 260 }, | |
| 261 | |
| 262 /** | |
| 263 * @param {!WebInspector.DebuggerModel.Location} rawLocation | |
| 264 * @param {string} condition | |
| 265 * @param {function(?DebuggerAgent.BreakpointId, !Array.<!WebInspector.Debug
gerModel.Location>)=} callback | |
| 266 */ | |
| 267 setBreakpointBySourceId: function(rawLocation, condition, callback) | |
| 268 { | |
| 269 var target = this.target(); | |
| 270 | |
| 271 /** | |
| 272 * @this {WebInspector.DebuggerModel} | |
| 273 * @param {?Protocol.Error} error | |
| 274 * @param {!DebuggerAgent.BreakpointId} breakpointId | |
| 275 * @param {!DebuggerAgent.Location} actualLocation | |
| 276 */ | |
| 277 function didSetBreakpoint(error, breakpointId, actualLocation) | |
| 278 { | |
| 279 if (callback) { | |
| 280 if (error || !actualLocation) { | |
| 281 callback(null, []); | |
| 282 return; | |
| 283 } | |
| 284 callback(breakpointId, [WebInspector.DebuggerModel.Location.from
Payload(this, actualLocation)]); | |
| 285 } | |
| 286 } | |
| 287 this._agent.setBreakpoint(rawLocation.payload(), condition, didSetBreakp
oint.bind(this)); | |
| 288 }, | |
| 289 | |
| 290 /** | |
| 291 * @param {!DebuggerAgent.BreakpointId} breakpointId | |
| 292 * @param {function()=} callback | |
| 293 */ | |
| 294 removeBreakpoint: function(breakpointId, callback) | |
| 295 { | |
| 296 this._agent.removeBreakpoint(breakpointId, innerCallback); | |
| 297 | |
| 298 /** | |
| 299 * @param {?Protocol.Error} error | |
| 300 */ | |
| 301 function innerCallback(error) | |
| 302 { | |
| 303 if (error) | |
| 304 console.error("Failed to remove breakpoint: " + error); | |
| 305 if (callback) | |
| 306 callback(); | |
| 307 } | |
| 308 }, | |
| 309 | |
| 310 /** | |
| 311 * @param {!DebuggerAgent.BreakpointId} breakpointId | |
| 312 * @param {!DebuggerAgent.Location} location | |
| 313 */ | |
| 314 _breakpointResolved: function(breakpointId, location) | |
| 315 { | |
| 316 this._breakpointResolvedEventTarget.dispatchEventToListeners(breakpointI
d, WebInspector.DebuggerModel.Location.fromPayload(this, location)); | |
| 317 }, | |
| 318 | |
| 319 globalObjectCleared: function() | |
| 320 { | |
| 321 this._setDebuggerPausedDetails(null); | |
| 322 this._reset(); | |
| 323 // TODO(dgozman): move clients to ExecutionContextDestroyed/ScriptCollec
ted events. | |
| 324 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.GlobalOb
jectCleared); | |
| 325 }, | |
| 326 | |
| 327 _reset: function() | |
| 328 { | |
| 329 this._scripts = {}; | |
| 330 this._scriptsBySourceURL.clear(); | |
| 331 }, | |
| 332 | |
| 333 /** | |
| 334 * @return {!Object.<string, !WebInspector.Script>} | |
| 335 */ | |
| 336 get scripts() | |
| 337 { | |
| 338 return this._scripts; | |
| 339 }, | |
| 340 | |
| 341 /** | |
| 342 * @param {!RuntimeAgent.ScriptId} scriptId | |
| 343 * @return {?WebInspector.Script} | |
| 344 */ | |
| 345 scriptForId: function(scriptId) | |
| 346 { | |
| 347 return this._scripts[scriptId] || null; | |
| 348 }, | |
| 349 | |
| 350 /** | |
| 351 * @return {!Array.<!WebInspector.Script>} | |
| 352 */ | |
| 353 scriptsForSourceURL: function(sourceURL) | |
| 354 { | |
| 355 if (!sourceURL) | |
| 356 return []; | |
| 357 return this._scriptsBySourceURL.get(sourceURL) || []; | |
| 358 }, | |
| 359 | |
| 360 /** | |
| 361 * @param {!RuntimeAgent.ScriptId} scriptId | |
| 362 * @param {string} newSource | |
| 363 * @param {function(?Protocol.Error, !RuntimeAgent.ExceptionDetails=)} callb
ack | |
| 364 */ | |
| 365 setScriptSource: function(scriptId, newSource, callback) | |
| 366 { | |
| 367 this._scripts[scriptId].editSource(newSource, this._didEditScriptSource.
bind(this, scriptId, newSource, callback)); | |
| 368 }, | |
| 369 | |
| 370 /** | |
| 371 * @param {!RuntimeAgent.ScriptId} scriptId | |
| 372 * @param {string} newSource | |
| 373 * @param {function(?Protocol.Error, !RuntimeAgent.ExceptionDetails=)} callb
ack | |
| 374 * @param {?Protocol.Error} error | |
| 375 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails | |
| 376 * @param {!Array.<!DebuggerAgent.CallFrame>=} callFrames | |
| 377 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace | |
| 378 * @param {boolean=} needsStepIn | |
| 379 */ | |
| 380 _didEditScriptSource: function(scriptId, newSource, callback, error, excepti
onDetails, callFrames, asyncStackTrace, needsStepIn) | |
| 381 { | |
| 382 if (needsStepIn) { | |
| 383 this.stepInto(); | |
| 384 this._pendingLiveEditCallback = callback.bind(this, error, exception
Details); | |
| 385 return; | |
| 386 } | |
| 387 | |
| 388 if (!error && callFrames && callFrames.length) | |
| 389 this._pausedScript(callFrames, this._debuggerPausedDetails.reason, t
his._debuggerPausedDetails.auxData, this._debuggerPausedDetails.breakpointIds, a
syncStackTrace); | |
| 390 callback(error, exceptionDetails); | |
| 391 }, | |
| 392 | |
| 393 /** | |
| 394 * @return {?Array.<!WebInspector.DebuggerModel.CallFrame>} | |
| 395 */ | |
| 396 get callFrames() | |
| 397 { | |
| 398 return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFra
mes : null; | |
| 399 }, | |
| 400 | |
| 401 /** | |
| 402 * @return {?WebInspector.DebuggerPausedDetails} | |
| 403 */ | |
| 404 debuggerPausedDetails: function() | |
| 405 { | |
| 406 return this._debuggerPausedDetails; | |
| 407 }, | |
| 408 | |
| 409 /** | |
| 410 * @param {?WebInspector.DebuggerPausedDetails} debuggerPausedDetails | |
| 411 * @return {boolean} | |
| 412 */ | |
| 413 _setDebuggerPausedDetails: function(debuggerPausedDetails) | |
| 414 { | |
| 415 this._isPausing = false; | |
| 416 this._debuggerPausedDetails = debuggerPausedDetails; | |
| 417 if (this._debuggerPausedDetails) { | |
| 418 if (Runtime.experiments.isEnabled("emptySourceMapAutoStepping")) { | |
| 419 if (this.dispatchEventToListeners(WebInspector.DebuggerModel.Eve
nts.BeforeDebuggerPaused, this._debuggerPausedDetails)) { | |
| 420 return false; | |
| 421 } | |
| 422 } | |
| 423 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Debu
ggerPaused, this._debuggerPausedDetails); | |
| 424 } | |
| 425 if (debuggerPausedDetails) | |
| 426 this.setSelectedCallFrame(debuggerPausedDetails.callFrames[0]); | |
| 427 else | |
| 428 this.setSelectedCallFrame(null); | |
| 429 return true; | |
| 430 }, | |
| 431 | |
| 432 /** | |
| 433 * @param {!Array.<!DebuggerAgent.CallFrame>} callFrames | |
| 434 * @param {string} reason | |
| 435 * @param {!Object|undefined} auxData | |
| 436 * @param {!Array.<string>} breakpointIds | |
| 437 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace | |
| 438 */ | |
| 439 _pausedScript: function(callFrames, reason, auxData, breakpointIds, asyncSta
ckTrace) | |
| 440 { | |
| 441 var pausedDetails = new WebInspector.DebuggerPausedDetails(this, callFra
mes, reason, auxData, breakpointIds, asyncStackTrace); | |
| 442 if (this._setDebuggerPausedDetails(pausedDetails)) { | |
| 443 if (this._pendingLiveEditCallback) { | |
| 444 var callback = this._pendingLiveEditCallback; | |
| 445 delete this._pendingLiveEditCallback; | |
| 446 callback(); | |
| 447 } | |
| 448 } else { | |
| 449 this._agent.stepInto(); | |
| 450 } | |
| 451 }, | |
| 452 | |
| 453 _resumedScript: function() | |
| 454 { | |
| 455 this._setDebuggerPausedDetails(null); | |
| 456 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Debugger
Resumed); | |
| 457 }, | |
| 458 | |
| 459 /** | |
| 460 * @param {!RuntimeAgent.ScriptId} scriptId | |
| 461 * @param {string} sourceURL | |
| 462 * @param {number} startLine | |
| 463 * @param {number} startColumn | |
| 464 * @param {number} endLine | |
| 465 * @param {number} endColumn | |
| 466 * @param {!RuntimeAgent.ExecutionContextId} executionContextId | |
| 467 * @param {string} hash | |
| 468 * @param {*|undefined} executionContextAuxData | |
| 469 * @param {boolean} isLiveEdit | |
| 470 * @param {string=} sourceMapURL | |
| 471 * @param {boolean=} hasSourceURL | |
| 472 * @param {boolean=} hasSyntaxError | |
| 473 * @return {!WebInspector.Script} | |
| 474 */ | |
| 475 _parsedScriptSource: function(scriptId, sourceURL, startLine, startColumn, e
ndLine, endColumn, executionContextId, hash, executionContextAuxData, isLiveEdit
, sourceMapURL, hasSourceURL, hasSyntaxError) | |
| 476 { | |
| 477 var isContentScript = false; | |
| 478 if (executionContextAuxData && ("isDefault" in executionContextAuxData)) | |
| 479 isContentScript = !executionContextAuxData["isDefault"]; | |
| 480 // Support file URL for node.js. | |
| 481 if (this.target().isNodeJS() && sourceURL && sourceURL.startsWith("/")) | |
| 482 sourceURL = WebInspector.ParsedURL.platformPathToURL(sourceURL); | |
| 483 var script = new WebInspector.Script(this, scriptId, sourceURL, startLin
e, startColumn, endLine, endColumn, executionContextId, hash, isContentScript, i
sLiveEdit, sourceMapURL, hasSourceURL); | |
| 484 this._registerScript(script); | |
| 485 if (!hasSyntaxError) | |
| 486 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Pars
edScriptSource, script); | |
| 487 else | |
| 488 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Fail
edToParseScriptSource, script); | |
| 489 return script; | |
| 490 }, | |
| 491 | |
| 492 /** | |
| 493 * @param {!WebInspector.Script} script | |
| 494 */ | |
| 495 _registerScript: function(script) | |
| 496 { | |
| 497 this._scripts[script.scriptId] = script; | |
| 498 if (script.isAnonymousScript()) | |
| 499 return; | |
| 500 | |
| 501 var scripts = this._scriptsBySourceURL.get(script.sourceURL); | |
| 502 if (!scripts) { | |
| 503 scripts = []; | |
| 504 this._scriptsBySourceURL.set(script.sourceURL, scripts); | |
| 505 } | |
| 506 scripts.push(script); | |
| 507 }, | |
| 508 | |
| 509 /** | |
| 510 * @param {!WebInspector.Script} script | |
| 511 * @param {number} lineNumber | |
| 512 * @param {number} columnNumber | |
| 513 * @return {?WebInspector.DebuggerModel.Location} | |
| 514 */ | |
| 515 createRawLocation: function(script, lineNumber, columnNumber) | |
| 516 { | |
| 517 if (script.sourceURL) | |
| 518 return this.createRawLocationByURL(script.sourceURL, lineNumber, col
umnNumber); | |
| 519 return new WebInspector.DebuggerModel.Location(this, script.scriptId, li
neNumber, columnNumber); | |
| 520 }, | |
| 521 | |
| 522 /** | |
| 523 * @param {string} sourceURL | |
| 524 * @param {number} lineNumber | |
| 525 * @param {number} columnNumber | |
| 526 * @return {?WebInspector.DebuggerModel.Location} | |
| 527 */ | |
| 528 createRawLocationByURL: function(sourceURL, lineNumber, columnNumber) | |
| 529 { | |
| 530 var closestScript = null; | |
| 531 var scripts = this._scriptsBySourceURL.get(sourceURL) || []; | |
| 532 for (var i = 0, l = scripts.length; i < l; ++i) { | |
| 533 var script = scripts[i]; | |
| 534 if (!closestScript) | |
| 535 closestScript = script; | |
| 536 if (script.lineOffset > lineNumber || (script.lineOffset === lineNum
ber && script.columnOffset > columnNumber)) | |
| 537 continue; | |
| 538 if (script.endLine < lineNumber || (script.endLine === lineNumber &&
script.endColumn <= columnNumber)) | |
| 539 continue; | |
| 540 closestScript = script; | |
| 541 break; | |
| 542 } | |
| 543 return closestScript ? new WebInspector.DebuggerModel.Location(this, clo
sestScript.scriptId, lineNumber, columnNumber) : null; | |
| 544 }, | |
| 545 | |
| 546 /** | |
| 547 * @param {!RuntimeAgent.ScriptId} scriptId | |
| 548 * @param {number} lineNumber | |
| 549 * @param {number} columnNumber | |
| 550 * @return {?WebInspector.DebuggerModel.Location} | |
| 551 */ | |
| 552 createRawLocationByScriptId: function(scriptId, lineNumber, columnNumber) | |
| 553 { | |
| 554 var script = this.scriptForId(scriptId); | |
| 555 return script ? this.createRawLocation(script, lineNumber, columnNumber)
: null; | |
| 556 }, | |
| 557 | |
| 558 /** | |
| 559 * @param {!RuntimeAgent.StackTrace} stackTrace | |
| 560 * @return {!Array<!WebInspector.DebuggerModel.Location>} | |
| 561 */ | |
| 562 createRawLocationsByStackTrace: function(stackTrace) | |
| 563 { | |
| 564 var frames = []; | |
| 565 while (stackTrace) { | |
| 566 for (var frame of stackTrace.callFrames) | |
| 567 frames.push(frame); | |
| 568 stackTrace = stackTrace.parent; | |
| 569 } | |
| 570 | |
| 571 var rawLocations = []; | |
| 572 for (var frame of frames) { | |
| 573 var rawLocation = this.createRawLocationByScriptId(frame.scriptId, f
rame.lineNumber, frame.columnNumber); | |
| 574 if (rawLocation) | |
| 575 rawLocations.push(rawLocation); | |
| 576 } | |
| 577 return rawLocations; | |
| 578 }, | |
| 579 | |
| 580 /** | |
| 581 * @return {boolean} | |
| 582 */ | |
| 583 isPaused: function() | |
| 584 { | |
| 585 return !!this.debuggerPausedDetails(); | |
| 586 }, | |
| 587 | |
| 588 /** | |
| 589 * @return {boolean} | |
| 590 */ | |
| 591 isPausing: function() | |
| 592 { | |
| 593 return this._isPausing; | |
| 594 }, | |
| 595 | |
| 596 /** | |
| 597 * @param {?WebInspector.DebuggerModel.CallFrame} callFrame | |
| 598 */ | |
| 599 setSelectedCallFrame: function(callFrame) | |
| 600 { | |
| 601 this._selectedCallFrame = callFrame; | |
| 602 if (!this._selectedCallFrame) | |
| 603 return; | |
| 604 | |
| 605 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.CallFram
eSelected, callFrame); | |
| 606 }, | |
| 607 | |
| 608 /** | |
| 609 * @return {?WebInspector.DebuggerModel.CallFrame} | |
| 610 */ | |
| 611 selectedCallFrame: function() | |
| 612 { | |
| 613 return this._selectedCallFrame; | |
| 614 }, | |
| 615 | |
| 616 /** | |
| 617 * @param {string} code | |
| 618 * @param {string} objectGroup | |
| 619 * @param {boolean} includeCommandLineAPI | |
| 620 * @param {boolean} silent | |
| 621 * @param {boolean} returnByValue | |
| 622 * @param {boolean} generatePreview | |
| 623 * @param {function(?WebInspector.RemoteObject, !RuntimeAgent.ExceptionDetai
ls=)} callback | |
| 624 */ | |
| 625 evaluateOnSelectedCallFrame: function(code, objectGroup, includeCommandLineA
PI, silent, returnByValue, generatePreview, callback) | |
| 626 { | |
| 627 /** | |
| 628 * @param {?RuntimeAgent.RemoteObject} result | |
| 629 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails | |
| 630 * @this {WebInspector.DebuggerModel} | |
| 631 */ | |
| 632 function didEvaluate(result, exceptionDetails) | |
| 633 { | |
| 634 if (!result) | |
| 635 callback(null); | |
| 636 else | |
| 637 callback(this.target().runtimeModel.createRemoteObject(result),
exceptionDetails); | |
| 638 } | |
| 639 | |
| 640 this.selectedCallFrame().evaluate(code, objectGroup, includeCommandLineA
PI, silent, returnByValue, generatePreview, didEvaluate.bind(this)); | |
| 641 }, | |
| 642 | |
| 643 /** | |
| 644 * @param {!WebInspector.RemoteObject} remoteObject | |
| 645 * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>} | |
| 646 */ | |
| 647 functionDetailsPromise: function(remoteObject) | |
| 648 { | |
| 649 return remoteObject.getAllPropertiesPromise(/* accessorPropertiesOnly */
false).then(buildDetails.bind(this)); | |
| 650 | |
| 651 /** | |
| 652 * @param {!{properties: ?Array.<!WebInspector.RemoteObjectProperty>, in
ternalProperties: ?Array.<!WebInspector.RemoteObjectProperty>}} response | |
| 653 * @return {?WebInspector.DebuggerModel.FunctionDetails} | |
| 654 * @this {!WebInspector.DebuggerModel} | |
| 655 */ | |
| 656 function buildDetails(response) | |
| 657 { | |
| 658 if (!response) | |
| 659 return null; | |
| 660 var location = null; | |
| 661 if (response.internalProperties) { | |
| 662 for (var prop of response.internalProperties) { | |
| 663 if (prop.name === "[[FunctionLocation]]") | |
| 664 location = prop.value; | |
| 665 } | |
| 666 } | |
| 667 var functionName = null; | |
| 668 if (response.properties) { | |
| 669 for (var prop of response.properties) { | |
| 670 if (prop.name === "name" && prop.value && prop.value.type ==
= "string") | |
| 671 functionName = prop.value; | |
| 672 if (prop.name === "displayName" && prop.value && prop.value.
type === "string") { | |
| 673 functionName = prop.value; | |
| 674 break; | |
| 675 } | |
| 676 } | |
| 677 } | |
| 678 var debuggerLocation = null; | |
| 679 if (location) | |
| 680 debuggerLocation = this.createRawLocationByScriptId(location.val
ue.scriptId, location.value.lineNumber, location.value.columnNumber); | |
| 681 return { location: debuggerLocation, functionName: functionName ? fu
nctionName.value : "" }; | |
| 682 } | |
| 683 }, | |
| 684 | |
| 685 /** | |
| 686 * @param {number} scopeNumber | |
| 687 * @param {string} variableName | |
| 688 * @param {!RuntimeAgent.CallArgument} newValue | |
| 689 * @param {string} callFrameId | |
| 690 * @param {function(string=)=} callback | |
| 691 */ | |
| 692 setVariableValue: function(scopeNumber, variableName, newValue, callFrameId,
callback) | |
| 693 { | |
| 694 this._agent.setVariableValue(scopeNumber, variableName, newValue, callFr
ameId, innerCallback); | |
| 695 | |
| 696 /** | |
| 697 * @param {?Protocol.Error} error | |
| 698 */ | |
| 699 function innerCallback(error) | |
| 700 { | |
| 701 if (error) { | |
| 702 console.error(error); | |
| 703 if (callback) | |
| 704 callback(error); | |
| 705 return; | |
| 706 } | |
| 707 if (callback) | |
| 708 callback(); | |
| 709 } | |
| 710 }, | |
| 711 | |
| 712 /** | |
| 713 * @param {!DebuggerAgent.BreakpointId} breakpointId | |
| 714 * @param {function(!WebInspector.Event)} listener | |
| 715 * @param {!Object=} thisObject | |
| 716 */ | |
| 717 addBreakpointListener: function(breakpointId, listener, thisObject) | |
| 718 { | |
| 719 this._breakpointResolvedEventTarget.addEventListener(breakpointId, liste
ner, thisObject); | |
| 720 }, | |
| 721 | |
| 722 /** | |
| 723 * @param {!DebuggerAgent.BreakpointId} breakpointId | |
| 724 * @param {function(!WebInspector.Event)} listener | |
| 725 * @param {!Object=} thisObject | |
| 726 */ | |
| 727 removeBreakpointListener: function(breakpointId, listener, thisObject) | |
| 728 { | |
| 729 this._breakpointResolvedEventTarget.removeEventListener(breakpointId, li
stener, thisObject); | |
| 730 }, | |
| 731 | |
| 732 /** | |
| 733 * @param {!Array<string>} patterns | |
| 734 * @return {!Promise<boolean>} | |
| 735 */ | |
| 736 setBlackboxPatterns: function(patterns) | |
| 737 { | |
| 738 var callback; | |
| 739 var promise = new Promise(fulfill => callback = fulfill); | |
| 740 this._agent.setBlackboxPatterns(patterns, patternsUpdated); | |
| 741 return promise; | |
| 742 | |
| 743 /** | |
| 744 * @param {?Protocol.Error} error | |
| 745 */ | |
| 746 function patternsUpdated(error) | |
| 747 { | |
| 748 if (error) | |
| 749 console.error(error); | |
| 750 callback(!error); | |
| 751 } | |
| 752 }, | |
| 753 | |
| 754 dispose: function() | |
| 755 { | |
| 756 WebInspector.moduleSetting("pauseOnExceptionEnabled").removeChangeListen
er(this._pauseOnExceptionStateChanged, this); | |
| 757 WebInspector.moduleSetting("pauseOnCaughtException").removeChangeListene
r(this._pauseOnExceptionStateChanged, this); | |
| 758 WebInspector.moduleSetting("enableAsyncStackTraces").removeChangeListene
r(this.asyncStackTracesStateChanged, this); | |
| 759 }, | |
| 760 | |
| 761 /** | |
| 762 * @override | |
| 763 * @return {!Promise} | |
| 764 */ | |
| 765 suspendModel: function() | |
| 766 { | |
| 767 return new Promise(promiseBody.bind(this)); | |
| 768 | |
| 769 /** | |
| 770 * @param {function()} fulfill | |
| 771 * @this {WebInspector.DebuggerModel} | |
| 772 */ | |
| 773 function promiseBody(fulfill) | |
| 774 { | |
| 775 this.disableDebugger(fulfill); | |
| 776 } | |
| 777 }, | |
| 778 | |
| 779 /** | |
| 780 * @override | |
| 781 * @return {!Promise} | |
| 782 */ | |
| 783 resumeModel: function() | |
| 784 { | |
| 785 return new Promise(promiseBody.bind(this)); | |
| 786 | |
| 787 /** | |
| 788 * @param {function()} fulfill | |
| 789 * @this {WebInspector.DebuggerModel} | |
| 790 */ | |
| 791 function promiseBody(fulfill) | |
| 792 { | |
| 793 this.enableDebugger(fulfill); | |
| 794 } | |
| 795 }, | |
| 796 | |
| 797 __proto__: WebInspector.SDKModel.prototype | |
| 798 }; | 813 }; |
| 799 | 814 |
| 800 WebInspector.DebuggerEventTypes = { | 815 /** |
| 801 JavaScriptPause: 0, | 816 * @implements {DebuggerAgent.Dispatcher} |
| 802 JavaScriptBreakpoint: 1, | 817 * @unrestricted |
| 803 NativeBreakpoint: 2 | 818 */ |
| 819 WebInspector.DebuggerDispatcher = class { |
| 820 /** |
| 821 * @param {!WebInspector.DebuggerModel} debuggerModel |
| 822 */ |
| 823 constructor(debuggerModel) { |
| 824 this._debuggerModel = debuggerModel; |
| 825 } |
| 826 |
| 827 /** |
| 828 * @override |
| 829 * @param {!Array.<!DebuggerAgent.CallFrame>} callFrames |
| 830 * @param {string} reason |
| 831 * @param {!Object=} auxData |
| 832 * @param {!Array.<string>=} breakpointIds |
| 833 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace |
| 834 */ |
| 835 paused(callFrames, reason, auxData, breakpointIds, asyncStackTrace) { |
| 836 this._debuggerModel._pausedScript(callFrames, reason, auxData, breakpointIds
|| [], asyncStackTrace); |
| 837 } |
| 838 |
| 839 /** |
| 840 * @override |
| 841 */ |
| 842 resumed() { |
| 843 this._debuggerModel._resumedScript(); |
| 844 } |
| 845 |
| 846 /** |
| 847 * @override |
| 848 * @param {!RuntimeAgent.ScriptId} scriptId |
| 849 * @param {string} sourceURL |
| 850 * @param {number} startLine |
| 851 * @param {number} startColumn |
| 852 * @param {number} endLine |
| 853 * @param {number} endColumn |
| 854 * @param {!RuntimeAgent.ExecutionContextId} executionContextId |
| 855 * @param {string} hash |
| 856 * @param {*=} executionContextAuxData |
| 857 * @param {boolean=} isLiveEdit |
| 858 * @param {string=} sourceMapURL |
| 859 * @param {boolean=} hasSourceURL |
| 860 */ |
| 861 scriptParsed( |
| 862 scriptId, |
| 863 sourceURL, |
| 864 startLine, |
| 865 startColumn, |
| 866 endLine, |
| 867 endColumn, |
| 868 executionContextId, |
| 869 hash, |
| 870 executionContextAuxData, |
| 871 isLiveEdit, |
| 872 sourceMapURL, |
| 873 hasSourceURL) { |
| 874 this._debuggerModel._parsedScriptSource( |
| 875 scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executi
onContextId, hash, |
| 876 executionContextAuxData, !!isLiveEdit, sourceMapURL, hasSourceURL, false
); |
| 877 } |
| 878 |
| 879 /** |
| 880 * @override |
| 881 * @param {!RuntimeAgent.ScriptId} scriptId |
| 882 * @param {string} sourceURL |
| 883 * @param {number} startLine |
| 884 * @param {number} startColumn |
| 885 * @param {number} endLine |
| 886 * @param {number} endColumn |
| 887 * @param {!RuntimeAgent.ExecutionContextId} executionContextId |
| 888 * @param {string} hash |
| 889 * @param {*=} executionContextAuxData |
| 890 * @param {string=} sourceMapURL |
| 891 * @param {boolean=} hasSourceURL |
| 892 */ |
| 893 scriptFailedToParse( |
| 894 scriptId, |
| 895 sourceURL, |
| 896 startLine, |
| 897 startColumn, |
| 898 endLine, |
| 899 endColumn, |
| 900 executionContextId, |
| 901 hash, |
| 902 executionContextAuxData, |
| 903 sourceMapURL, |
| 904 hasSourceURL) { |
| 905 this._debuggerModel._parsedScriptSource( |
| 906 scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executi
onContextId, hash, |
| 907 executionContextAuxData, false, sourceMapURL, hasSourceURL, true); |
| 908 } |
| 909 |
| 910 /** |
| 911 * @override |
| 912 * @param {!DebuggerAgent.BreakpointId} breakpointId |
| 913 * @param {!DebuggerAgent.Location} location |
| 914 */ |
| 915 breakpointResolved(breakpointId, location) { |
| 916 this._debuggerModel._breakpointResolved(breakpointId, location); |
| 917 } |
| 804 }; | 918 }; |
| 805 | 919 |
| 806 /** | 920 /** |
| 807 * @constructor | 921 * @unrestricted |
| 808 * @implements {DebuggerAgent.Dispatcher} | |
| 809 * @param {!WebInspector.DebuggerModel} debuggerModel | |
| 810 */ | 922 */ |
| 811 WebInspector.DebuggerDispatcher = function(debuggerModel) | 923 WebInspector.DebuggerModel.Location = class extends WebInspector.SDKObject { |
| 812 { | 924 /** |
| 813 this._debuggerModel = debuggerModel; | 925 * @param {!WebInspector.DebuggerModel} debuggerModel |
| 814 }; | 926 * @param {string} scriptId |
| 815 | 927 * @param {number} lineNumber |
| 816 WebInspector.DebuggerDispatcher.prototype = { | 928 * @param {number=} columnNumber |
| 817 /** | 929 */ |
| 818 * @override | 930 constructor(debuggerModel, scriptId, lineNumber, columnNumber) { |
| 819 * @param {!Array.<!DebuggerAgent.CallFrame>} callFrames | 931 super(debuggerModel.target()); |
| 820 * @param {string} reason | |
| 821 * @param {!Object=} auxData | |
| 822 * @param {!Array.<string>=} breakpointIds | |
| 823 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace | |
| 824 */ | |
| 825 paused: function(callFrames, reason, auxData, breakpointIds, asyncStackTrace
) | |
| 826 { | |
| 827 this._debuggerModel._pausedScript(callFrames, reason, auxData, breakpoin
tIds || [], asyncStackTrace); | |
| 828 }, | |
| 829 | |
| 830 /** | |
| 831 * @override | |
| 832 */ | |
| 833 resumed: function() | |
| 834 { | |
| 835 this._debuggerModel._resumedScript(); | |
| 836 }, | |
| 837 | |
| 838 /** | |
| 839 * @override | |
| 840 * @param {!RuntimeAgent.ScriptId} scriptId | |
| 841 * @param {string} sourceURL | |
| 842 * @param {number} startLine | |
| 843 * @param {number} startColumn | |
| 844 * @param {number} endLine | |
| 845 * @param {number} endColumn | |
| 846 * @param {!RuntimeAgent.ExecutionContextId} executionContextId | |
| 847 * @param {string} hash | |
| 848 * @param {*=} executionContextAuxData | |
| 849 * @param {boolean=} isLiveEdit | |
| 850 * @param {string=} sourceMapURL | |
| 851 * @param {boolean=} hasSourceURL | |
| 852 */ | |
| 853 scriptParsed: function(scriptId, sourceURL, startLine, startColumn, endLine,
endColumn, executionContextId, hash, executionContextAuxData, isLiveEdit, sourc
eMapURL, hasSourceURL) | |
| 854 { | |
| 855 this._debuggerModel._parsedScriptSource(scriptId, sourceURL, startLine,
startColumn, endLine, endColumn, executionContextId, hash, executionContextAuxDa
ta, !!isLiveEdit, sourceMapURL, hasSourceURL, false); | |
| 856 }, | |
| 857 | |
| 858 /** | |
| 859 * @override | |
| 860 * @param {!RuntimeAgent.ScriptId} scriptId | |
| 861 * @param {string} sourceURL | |
| 862 * @param {number} startLine | |
| 863 * @param {number} startColumn | |
| 864 * @param {number} endLine | |
| 865 * @param {number} endColumn | |
| 866 * @param {!RuntimeAgent.ExecutionContextId} executionContextId | |
| 867 * @param {string} hash | |
| 868 * @param {*=} executionContextAuxData | |
| 869 * @param {string=} sourceMapURL | |
| 870 * @param {boolean=} hasSourceURL | |
| 871 */ | |
| 872 scriptFailedToParse: function(scriptId, sourceURL, startLine, startColumn, e
ndLine, endColumn, executionContextId, hash, executionContextAuxData, sourceMapU
RL, hasSourceURL) | |
| 873 { | |
| 874 this._debuggerModel._parsedScriptSource(scriptId, sourceURL, startLine,
startColumn, endLine, endColumn, executionContextId, hash, executionContextAuxDa
ta, false, sourceMapURL, hasSourceURL, true); | |
| 875 }, | |
| 876 | |
| 877 /** | |
| 878 * @override | |
| 879 * @param {!DebuggerAgent.BreakpointId} breakpointId | |
| 880 * @param {!DebuggerAgent.Location} location | |
| 881 */ | |
| 882 breakpointResolved: function(breakpointId, location) | |
| 883 { | |
| 884 this._debuggerModel._breakpointResolved(breakpointId, location); | |
| 885 } | |
| 886 }; | |
| 887 | |
| 888 /** | |
| 889 * @constructor | |
| 890 * @extends {WebInspector.SDKObject} | |
| 891 * @param {!WebInspector.DebuggerModel} debuggerModel | |
| 892 * @param {string} scriptId | |
| 893 * @param {number} lineNumber | |
| 894 * @param {number=} columnNumber | |
| 895 */ | |
| 896 WebInspector.DebuggerModel.Location = function(debuggerModel, scriptId, lineNumb
er, columnNumber) | |
| 897 { | |
| 898 WebInspector.SDKObject.call(this, debuggerModel.target()); | |
| 899 this._debuggerModel = debuggerModel; | 932 this._debuggerModel = debuggerModel; |
| 900 this.scriptId = scriptId; | 933 this.scriptId = scriptId; |
| 901 this.lineNumber = lineNumber; | 934 this.lineNumber = lineNumber; |
| 902 this.columnNumber = columnNumber || 0; | 935 this.columnNumber = columnNumber || 0; |
| 936 } |
| 937 |
| 938 /** |
| 939 * @param {!WebInspector.DebuggerModel} debuggerModel |
| 940 * @param {!DebuggerAgent.Location} payload |
| 941 * @return {!WebInspector.DebuggerModel.Location} |
| 942 */ |
| 943 static fromPayload(debuggerModel, payload) { |
| 944 return new WebInspector.DebuggerModel.Location( |
| 945 debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumbe
r); |
| 946 } |
| 947 |
| 948 /** |
| 949 * @return {!DebuggerAgent.Location} |
| 950 */ |
| 951 payload() { |
| 952 return {scriptId: this.scriptId, lineNumber: this.lineNumber, columnNumber:
this.columnNumber}; |
| 953 } |
| 954 |
| 955 /** |
| 956 * @return {?WebInspector.Script} |
| 957 */ |
| 958 script() { |
| 959 return this._debuggerModel.scriptForId(this.scriptId); |
| 960 } |
| 961 |
| 962 continueToLocation() { |
| 963 this._debuggerModel._agent.continueToLocation(this.payload()); |
| 964 } |
| 965 |
| 966 /** |
| 967 * @return {string} |
| 968 */ |
| 969 id() { |
| 970 return this.target().id() + ':' + this.scriptId + ':' + this.lineNumber + ':
' + this.columnNumber; |
| 971 } |
| 903 }; | 972 }; |
| 904 | 973 |
| 974 |
| 905 /** | 975 /** |
| 906 * @param {!WebInspector.DebuggerModel} debuggerModel | 976 * @unrestricted |
| 907 * @param {!DebuggerAgent.Location} payload | |
| 908 * @return {!WebInspector.DebuggerModel.Location} | |
| 909 */ | 977 */ |
| 910 WebInspector.DebuggerModel.Location.fromPayload = function(debuggerModel, payloa
d) | 978 WebInspector.DebuggerModel.CallFrame = class extends WebInspector.SDKObject { |
| 911 { | 979 /** |
| 912 return new WebInspector.DebuggerModel.Location(debuggerModel, payload.script
Id, payload.lineNumber, payload.columnNumber); | 980 * @param {!WebInspector.DebuggerModel} debuggerModel |
| 913 }; | 981 * @param {!WebInspector.Script} script |
| 914 | 982 * @param {!DebuggerAgent.CallFrame} payload |
| 915 WebInspector.DebuggerModel.Location.prototype = { | 983 */ |
| 916 /** | 984 constructor(debuggerModel, script, payload) { |
| 917 * @return {!DebuggerAgent.Location} | |
| 918 */ | |
| 919 payload: function() | |
| 920 { | |
| 921 return { scriptId: this.scriptId, lineNumber: this.lineNumber, columnNum
ber: this.columnNumber }; | |
| 922 }, | |
| 923 | |
| 924 /** | |
| 925 * @return {?WebInspector.Script} | |
| 926 */ | |
| 927 script: function() | |
| 928 { | |
| 929 return this._debuggerModel.scriptForId(this.scriptId); | |
| 930 }, | |
| 931 | |
| 932 continueToLocation: function() | |
| 933 { | |
| 934 this._debuggerModel._agent.continueToLocation(this.payload()); | |
| 935 }, | |
| 936 | |
| 937 /** | |
| 938 * @return {string} | |
| 939 */ | |
| 940 id: function() | |
| 941 { | |
| 942 return this.target().id() + ":" + this.scriptId + ":" + this.lineNumber
+ ":" + this.columnNumber; | |
| 943 }, | |
| 944 | |
| 945 __proto__: WebInspector.SDKObject.prototype | |
| 946 }; | |
| 947 | |
| 948 /** | |
| 949 * @constructor | |
| 950 * @extends {WebInspector.SDKObject} | |
| 951 * @param {!WebInspector.DebuggerModel} debuggerModel | |
| 952 * @param {!WebInspector.Script} script | |
| 953 * @param {!DebuggerAgent.CallFrame} payload | |
| 954 */ | |
| 955 WebInspector.DebuggerModel.CallFrame = function(debuggerModel, script, payload) | |
| 956 { | |
| 957 var target = debuggerModel.target(); | 985 var target = debuggerModel.target(); |
| 958 WebInspector.SDKObject.call(this, target); | 986 super(target); |
| 959 this.debuggerModel = debuggerModel; | 987 this.debuggerModel = debuggerModel; |
| 960 this._debuggerAgent = debuggerModel._agent; | 988 this._debuggerAgent = debuggerModel._agent; |
| 961 this._script = script; | 989 this._script = script; |
| 962 this._payload = payload; | 990 this._payload = payload; |
| 963 this._location = WebInspector.DebuggerModel.Location.fromPayload(debuggerMod
el, payload.location); | 991 this._location = WebInspector.DebuggerModel.Location.fromPayload(debuggerMod
el, payload.location); |
| 964 this._scopeChain = []; | 992 this._scopeChain = []; |
| 965 this._localScope = null; | 993 this._localScope = null; |
| 966 for (var i = 0; i < payload.scopeChain.length; ++i) { | 994 for (var i = 0; i < payload.scopeChain.length; ++i) { |
| 967 var scope = new WebInspector.DebuggerModel.Scope(this, i); | 995 var scope = new WebInspector.DebuggerModel.Scope(this, i); |
| 968 this._scopeChain.push(scope); | 996 this._scopeChain.push(scope); |
| 969 if (scope.type() === DebuggerAgent.ScopeType.Local) | 997 if (scope.type() === DebuggerAgent.ScopeType.Local) |
| 970 this._localScope = scope; | 998 this._localScope = scope; |
| 971 } | 999 } |
| 972 if (payload.functionLocation) | 1000 if (payload.functionLocation) |
| 973 this._functionLocation = WebInspector.DebuggerModel.Location.fromPayload
(debuggerModel, payload.functionLocation); | 1001 this._functionLocation = WebInspector.DebuggerModel.Location.fromPayload(d
ebuggerModel, payload.functionLocation); |
| 974 }; | 1002 } |
| 975 | 1003 |
| 976 /** | 1004 /** |
| 977 * @param {!WebInspector.DebuggerModel} debuggerModel | 1005 * @param {!WebInspector.DebuggerModel} debuggerModel |
| 978 * @param {!Array.<!DebuggerAgent.CallFrame>} callFrames | 1006 * @param {!Array.<!DebuggerAgent.CallFrame>} callFrames |
| 979 * @return {!Array.<!WebInspector.DebuggerModel.CallFrame>} | 1007 * @return {!Array.<!WebInspector.DebuggerModel.CallFrame>} |
| 980 */ | 1008 */ |
| 981 WebInspector.DebuggerModel.CallFrame.fromPayloadArray = function(debuggerModel,
callFrames) | 1009 static fromPayloadArray(debuggerModel, callFrames) { |
| 982 { | |
| 983 var result = []; | 1010 var result = []; |
| 984 for (var i = 0; i < callFrames.length; ++i) { | 1011 for (var i = 0; i < callFrames.length; ++i) { |
| 985 var callFrame = callFrames[i]; | 1012 var callFrame = callFrames[i]; |
| 986 var script = debuggerModel.scriptForId(callFrame.location.scriptId); | 1013 var script = debuggerModel.scriptForId(callFrame.location.scriptId); |
| 987 if (script) | 1014 if (script) |
| 988 result.push(new WebInspector.DebuggerModel.CallFrame(debuggerModel,
script, callFrame)); | 1015 result.push(new WebInspector.DebuggerModel.CallFrame(debuggerModel, scri
pt, callFrame)); |
| 989 } | 1016 } |
| 990 return result; | 1017 return result; |
| 1018 } |
| 1019 |
| 1020 /** |
| 1021 * @return {!WebInspector.Script} |
| 1022 */ |
| 1023 get script() { |
| 1024 return this._script; |
| 1025 } |
| 1026 |
| 1027 /** |
| 1028 * @return {string} |
| 1029 */ |
| 1030 get id() { |
| 1031 return this._payload.callFrameId; |
| 1032 } |
| 1033 |
| 1034 /** |
| 1035 * @return {!Array.<!WebInspector.DebuggerModel.Scope>} |
| 1036 */ |
| 1037 scopeChain() { |
| 1038 return this._scopeChain; |
| 1039 } |
| 1040 |
| 1041 /** |
| 1042 * @return {?WebInspector.DebuggerModel.Scope} |
| 1043 */ |
| 1044 localScope() { |
| 1045 return this._localScope; |
| 1046 } |
| 1047 |
| 1048 /** |
| 1049 * @return {?WebInspector.RemoteObject} |
| 1050 */ |
| 1051 thisObject() { |
| 1052 return this._payload.this ? this.target().runtimeModel.createRemoteObject(th
is._payload.this) : null; |
| 1053 } |
| 1054 |
| 1055 /** |
| 1056 * @return {?WebInspector.RemoteObject} |
| 1057 */ |
| 1058 returnValue() { |
| 1059 return this._payload.returnValue ? this.target().runtimeModel.createRemoteOb
ject(this._payload.returnValue) : null; |
| 1060 } |
| 1061 |
| 1062 /** |
| 1063 * @return {string} |
| 1064 */ |
| 1065 get functionName() { |
| 1066 return this._payload.functionName; |
| 1067 } |
| 1068 |
| 1069 /** |
| 1070 * @return {!WebInspector.DebuggerModel.Location} |
| 1071 */ |
| 1072 location() { |
| 1073 return this._location; |
| 1074 } |
| 1075 |
| 1076 /** |
| 1077 * @return {?WebInspector.DebuggerModel.Location} |
| 1078 */ |
| 1079 functionLocation() { |
| 1080 return this._functionLocation || null; |
| 1081 } |
| 1082 |
| 1083 /** |
| 1084 * @param {string} code |
| 1085 * @param {string} objectGroup |
| 1086 * @param {boolean} includeCommandLineAPI |
| 1087 * @param {boolean} silent |
| 1088 * @param {boolean} returnByValue |
| 1089 * @param {boolean} generatePreview |
| 1090 * @param {function(?RuntimeAgent.RemoteObject, !RuntimeAgent.ExceptionDetails
=)} callback |
| 1091 */ |
| 1092 evaluate(code, objectGroup, includeCommandLineAPI, silent, returnByValue, gene
ratePreview, callback) { |
| 1093 /** |
| 1094 * @param {?Protocol.Error} error |
| 1095 * @param {!RuntimeAgent.RemoteObject} result |
| 1096 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails |
| 1097 */ |
| 1098 function didEvaluateOnCallFrame(error, result, exceptionDetails) { |
| 1099 if (error) { |
| 1100 console.error(error); |
| 1101 callback(null); |
| 1102 return; |
| 1103 } |
| 1104 callback(result, exceptionDetails); |
| 1105 } |
| 1106 this._debuggerAgent.evaluateOnCallFrame( |
| 1107 this._payload.callFrameId, code, objectGroup, includeCommandLineAPI, sil
ent, returnByValue, generatePreview, |
| 1108 didEvaluateOnCallFrame); |
| 1109 } |
| 1110 |
| 1111 /** |
| 1112 * @param {function(?Protocol.Error=)=} callback |
| 1113 */ |
| 1114 restart(callback) { |
| 1115 /** |
| 1116 * @param {?Protocol.Error} error |
| 1117 * @param {!Array.<!DebuggerAgent.CallFrame>=} callFrames |
| 1118 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace |
| 1119 * @this {WebInspector.DebuggerModel.CallFrame} |
| 1120 */ |
| 1121 function protocolCallback(error, callFrames, asyncStackTrace) { |
| 1122 if (!error) |
| 1123 this.debuggerModel.stepInto(); |
| 1124 if (callback) |
| 1125 callback(error); |
| 1126 } |
| 1127 this._debuggerAgent.restartFrame(this._payload.callFrameId, protocolCallback
.bind(this)); |
| 1128 } |
| 1129 |
| 1130 /** |
| 1131 * @param {function(!Object)} callback |
| 1132 */ |
| 1133 variableNames(callback) { |
| 1134 var result = {this: true}; |
| 1135 |
| 1136 function propertiesCollected(properties) { |
| 1137 for (var i = 0; properties && i < properties.length; ++i) |
| 1138 result[properties[i].name] = true; |
| 1139 if (--pendingRequests === 0) |
| 1140 callback(result); |
| 1141 } |
| 1142 |
| 1143 var scopeChain = this.scopeChain(); |
| 1144 var pendingRequests = scopeChain.length; |
| 1145 for (var i = 0; i < scopeChain.length; ++i) { |
| 1146 var scope = scopeChain[i]; |
| 1147 var object = scope.object(); |
| 1148 object.getAllProperties(false, propertiesCollected); |
| 1149 } |
| 1150 } |
| 991 }; | 1151 }; |
| 992 | 1152 |
| 993 WebInspector.DebuggerModel.CallFrame.prototype = { | |
| 994 /** | |
| 995 * @return {!WebInspector.Script} | |
| 996 */ | |
| 997 get script() | |
| 998 { | |
| 999 return this._script; | |
| 1000 }, | |
| 1001 | |
| 1002 /** | |
| 1003 * @return {string} | |
| 1004 */ | |
| 1005 get id() | |
| 1006 { | |
| 1007 return this._payload.callFrameId; | |
| 1008 }, | |
| 1009 | |
| 1010 /** | |
| 1011 * @return {!Array.<!WebInspector.DebuggerModel.Scope>} | |
| 1012 */ | |
| 1013 scopeChain: function() | |
| 1014 { | |
| 1015 return this._scopeChain; | |
| 1016 }, | |
| 1017 | |
| 1018 /** | |
| 1019 * @return {?WebInspector.DebuggerModel.Scope} | |
| 1020 */ | |
| 1021 localScope: function() | |
| 1022 { | |
| 1023 return this._localScope; | |
| 1024 }, | |
| 1025 | |
| 1026 /** | |
| 1027 * @return {?WebInspector.RemoteObject} | |
| 1028 */ | |
| 1029 thisObject: function() | |
| 1030 { | |
| 1031 return this._payload.this ? this.target().runtimeModel.createRemoteObjec
t(this._payload.this) : null; | |
| 1032 }, | |
| 1033 | |
| 1034 /** | |
| 1035 * @return {?WebInspector.RemoteObject} | |
| 1036 */ | |
| 1037 returnValue: function() | |
| 1038 { | |
| 1039 return this._payload.returnValue ? this.target().runtimeModel.createRem
oteObject(this._payload.returnValue) : null; | |
| 1040 }, | |
| 1041 | |
| 1042 /** | |
| 1043 * @return {string} | |
| 1044 */ | |
| 1045 get functionName() | |
| 1046 { | |
| 1047 return this._payload.functionName; | |
| 1048 }, | |
| 1049 | |
| 1050 /** | |
| 1051 * @return {!WebInspector.DebuggerModel.Location} | |
| 1052 */ | |
| 1053 location: function() | |
| 1054 { | |
| 1055 return this._location; | |
| 1056 }, | |
| 1057 | |
| 1058 /** | |
| 1059 * @return {?WebInspector.DebuggerModel.Location} | |
| 1060 */ | |
| 1061 functionLocation: function() | |
| 1062 { | |
| 1063 return this._functionLocation || null; | |
| 1064 }, | |
| 1065 | |
| 1066 /** | |
| 1067 * @param {string} code | |
| 1068 * @param {string} objectGroup | |
| 1069 * @param {boolean} includeCommandLineAPI | |
| 1070 * @param {boolean} silent | |
| 1071 * @param {boolean} returnByValue | |
| 1072 * @param {boolean} generatePreview | |
| 1073 * @param {function(?RuntimeAgent.RemoteObject, !RuntimeAgent.ExceptionDetai
ls=)} callback | |
| 1074 */ | |
| 1075 evaluate: function(code, objectGroup, includeCommandLineAPI, silent, returnB
yValue, generatePreview, callback) | |
| 1076 { | |
| 1077 /** | |
| 1078 * @param {?Protocol.Error} error | |
| 1079 * @param {!RuntimeAgent.RemoteObject} result | |
| 1080 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails | |
| 1081 */ | |
| 1082 function didEvaluateOnCallFrame(error, result, exceptionDetails) | |
| 1083 { | |
| 1084 if (error) { | |
| 1085 console.error(error); | |
| 1086 callback(null); | |
| 1087 return; | |
| 1088 } | |
| 1089 callback(result, exceptionDetails); | |
| 1090 } | |
| 1091 this._debuggerAgent.evaluateOnCallFrame(this._payload.callFrameId, code,
objectGroup, includeCommandLineAPI, silent, returnByValue, generatePreview, did
EvaluateOnCallFrame); | |
| 1092 }, | |
| 1093 | |
| 1094 /** | |
| 1095 * @param {function(?Protocol.Error=)=} callback | |
| 1096 */ | |
| 1097 restart: function(callback) | |
| 1098 { | |
| 1099 /** | |
| 1100 * @param {?Protocol.Error} error | |
| 1101 * @param {!Array.<!DebuggerAgent.CallFrame>=} callFrames | |
| 1102 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace | |
| 1103 * @this {WebInspector.DebuggerModel.CallFrame} | |
| 1104 */ | |
| 1105 function protocolCallback(error, callFrames, asyncStackTrace) | |
| 1106 { | |
| 1107 if (!error) | |
| 1108 this.debuggerModel.stepInto(); | |
| 1109 if (callback) | |
| 1110 callback(error); | |
| 1111 } | |
| 1112 this._debuggerAgent.restartFrame(this._payload.callFrameId, protocolCall
back.bind(this)); | |
| 1113 }, | |
| 1114 | |
| 1115 /** | |
| 1116 * @param {function(!Object)} callback | |
| 1117 */ | |
| 1118 variableNames: function(callback) | |
| 1119 { | |
| 1120 var result = { this: true }; | |
| 1121 | |
| 1122 function propertiesCollected(properties) | |
| 1123 { | |
| 1124 for (var i = 0; properties && i < properties.length; ++i) | |
| 1125 result[properties[i].name] = true; | |
| 1126 if (--pendingRequests === 0) | |
| 1127 callback(result); | |
| 1128 } | |
| 1129 | |
| 1130 var scopeChain = this.scopeChain(); | |
| 1131 var pendingRequests = scopeChain.length; | |
| 1132 for (var i = 0; i < scopeChain.length; ++i) { | |
| 1133 var scope = scopeChain[i]; | |
| 1134 var object = scope.object(); | |
| 1135 object.getAllProperties(false, propertiesCollected); | |
| 1136 } | |
| 1137 }, | |
| 1138 | |
| 1139 __proto__: WebInspector.SDKObject.prototype | |
| 1140 }; | |
| 1141 | 1153 |
| 1142 /** | 1154 /** |
| 1143 * @constructor | 1155 * @unrestricted |
| 1144 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame | |
| 1145 * @param {number} ordinal | |
| 1146 */ | 1156 */ |
| 1147 WebInspector.DebuggerModel.Scope = function(callFrame, ordinal) | 1157 WebInspector.DebuggerModel.Scope = class { |
| 1148 { | 1158 /** |
| 1159 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame |
| 1160 * @param {number} ordinal |
| 1161 */ |
| 1162 constructor(callFrame, ordinal) { |
| 1149 this._callFrame = callFrame; | 1163 this._callFrame = callFrame; |
| 1150 this._payload = callFrame._payload.scopeChain[ordinal]; | 1164 this._payload = callFrame._payload.scopeChain[ordinal]; |
| 1151 this._type = this._payload.type; | 1165 this._type = this._payload.type; |
| 1152 this._name = this._payload.name; | 1166 this._name = this._payload.name; |
| 1153 this._ordinal = ordinal; | 1167 this._ordinal = ordinal; |
| 1154 this._startLocation = this._payload.startLocation ? WebInspector.DebuggerMod
el.Location.fromPayload(callFrame.debuggerModel, this._payload.startLocation) :
null; | 1168 this._startLocation = this._payload.startLocation ? |
| 1155 this._endLocation = this._payload.endLocation ? WebInspector.DebuggerModel.L
ocation.fromPayload(callFrame.debuggerModel, this._payload.endLocation) : null; | 1169 WebInspector.DebuggerModel.Location.fromPayload(callFrame.debuggerModel,
this._payload.startLocation) : |
| 1170 null; |
| 1171 this._endLocation = this._payload.endLocation ? |
| 1172 WebInspector.DebuggerModel.Location.fromPayload(callFrame.debuggerModel,
this._payload.endLocation) : |
| 1173 null; |
| 1174 } |
| 1175 |
| 1176 /** |
| 1177 * @return {!WebInspector.DebuggerModel.CallFrame} |
| 1178 */ |
| 1179 callFrame() { |
| 1180 return this._callFrame; |
| 1181 } |
| 1182 |
| 1183 /** |
| 1184 * @return {string} |
| 1185 */ |
| 1186 type() { |
| 1187 return this._type; |
| 1188 } |
| 1189 |
| 1190 /** |
| 1191 * @return {string|undefined} |
| 1192 */ |
| 1193 name() { |
| 1194 return this._name; |
| 1195 } |
| 1196 |
| 1197 /** |
| 1198 * @return {?WebInspector.DebuggerModel.Location} |
| 1199 */ |
| 1200 startLocation() { |
| 1201 return this._startLocation; |
| 1202 } |
| 1203 |
| 1204 /** |
| 1205 * @return {?WebInspector.DebuggerModel.Location} |
| 1206 */ |
| 1207 endLocation() { |
| 1208 return this._endLocation; |
| 1209 } |
| 1210 |
| 1211 /** |
| 1212 * @return {!WebInspector.RemoteObject} |
| 1213 */ |
| 1214 object() { |
| 1215 if (this._object) |
| 1216 return this._object; |
| 1217 var runtimeModel = this._callFrame.target().runtimeModel; |
| 1218 |
| 1219 var declarativeScope = this._type !== DebuggerAgent.ScopeType.With && this._
type !== DebuggerAgent.ScopeType.Global; |
| 1220 if (declarativeScope) |
| 1221 this._object = runtimeModel.createScopeRemoteObject( |
| 1222 this._payload.object, new WebInspector.ScopeRef(this._ordinal, this._c
allFrame.id)); |
| 1223 else |
| 1224 this._object = runtimeModel.createRemoteObject(this._payload.object); |
| 1225 |
| 1226 return this._object; |
| 1227 } |
| 1228 |
| 1229 /** |
| 1230 * @return {string} |
| 1231 */ |
| 1232 description() { |
| 1233 var declarativeScope = this._type !== DebuggerAgent.ScopeType.With && this._
type !== DebuggerAgent.ScopeType.Global; |
| 1234 return declarativeScope ? '' : (this._payload.object.description || ''); |
| 1235 } |
| 1156 }; | 1236 }; |
| 1157 | 1237 |
| 1158 WebInspector.DebuggerModel.Scope.prototype = { | |
| 1159 /** | |
| 1160 * @return {!WebInspector.DebuggerModel.CallFrame} | |
| 1161 */ | |
| 1162 callFrame: function() | |
| 1163 { | |
| 1164 return this._callFrame; | |
| 1165 }, | |
| 1166 | |
| 1167 /** | |
| 1168 * @return {string} | |
| 1169 */ | |
| 1170 type: function() | |
| 1171 { | |
| 1172 return this._type; | |
| 1173 }, | |
| 1174 | |
| 1175 /** | |
| 1176 * @return {string|undefined} | |
| 1177 */ | |
| 1178 name: function() | |
| 1179 { | |
| 1180 return this._name; | |
| 1181 }, | |
| 1182 | |
| 1183 /** | |
| 1184 * @return {?WebInspector.DebuggerModel.Location} | |
| 1185 */ | |
| 1186 startLocation: function() | |
| 1187 { | |
| 1188 return this._startLocation; | |
| 1189 }, | |
| 1190 | |
| 1191 /** | |
| 1192 * @return {?WebInspector.DebuggerModel.Location} | |
| 1193 */ | |
| 1194 endLocation: function() | |
| 1195 { | |
| 1196 return this._endLocation; | |
| 1197 }, | |
| 1198 | |
| 1199 /** | |
| 1200 * @return {!WebInspector.RemoteObject} | |
| 1201 */ | |
| 1202 object: function() | |
| 1203 { | |
| 1204 if (this._object) | |
| 1205 return this._object; | |
| 1206 var runtimeModel = this._callFrame.target().runtimeModel; | |
| 1207 | |
| 1208 var declarativeScope = this._type !== DebuggerAgent.ScopeType.With && th
is._type !== DebuggerAgent.ScopeType.Global; | |
| 1209 if (declarativeScope) | |
| 1210 this._object = runtimeModel.createScopeRemoteObject(this._payload.ob
ject, new WebInspector.ScopeRef(this._ordinal, this._callFrame.id)); | |
| 1211 else | |
| 1212 this._object = runtimeModel.createRemoteObject(this._payload.object)
; | |
| 1213 | |
| 1214 return this._object; | |
| 1215 }, | |
| 1216 | |
| 1217 /** | |
| 1218 * @return {string} | |
| 1219 */ | |
| 1220 description: function() | |
| 1221 { | |
| 1222 var declarativeScope = this._type !== DebuggerAgent.ScopeType.With && th
is._type !== DebuggerAgent.ScopeType.Global; | |
| 1223 return declarativeScope ? "" : (this._payload.object.description || ""); | |
| 1224 } | |
| 1225 }; | |
| 1226 | |
| 1227 /** | 1238 /** |
| 1228 * @constructor | 1239 * @unrestricted |
| 1229 * @extends {WebInspector.SDKObject} | |
| 1230 * @param {!WebInspector.DebuggerModel} debuggerModel | |
| 1231 * @param {!Array.<!DebuggerAgent.CallFrame>} callFrames | |
| 1232 * @param {string} reason | |
| 1233 * @param {!Object|undefined} auxData | |
| 1234 * @param {!Array.<string>} breakpointIds | |
| 1235 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace | |
| 1236 */ | 1240 */ |
| 1237 WebInspector.DebuggerPausedDetails = function(debuggerModel, callFrames, reason,
auxData, breakpointIds, asyncStackTrace) | 1241 WebInspector.DebuggerPausedDetails = class extends WebInspector.SDKObject { |
| 1238 { | 1242 /** |
| 1239 WebInspector.SDKObject.call(this, debuggerModel.target()); | 1243 * @param {!WebInspector.DebuggerModel} debuggerModel |
| 1244 * @param {!Array.<!DebuggerAgent.CallFrame>} callFrames |
| 1245 * @param {string} reason |
| 1246 * @param {!Object|undefined} auxData |
| 1247 * @param {!Array.<string>} breakpointIds |
| 1248 * @param {!RuntimeAgent.StackTrace=} asyncStackTrace |
| 1249 */ |
| 1250 constructor(debuggerModel, callFrames, reason, auxData, breakpointIds, asyncSt
ackTrace) { |
| 1251 super(debuggerModel.target()); |
| 1240 this.debuggerModel = debuggerModel; | 1252 this.debuggerModel = debuggerModel; |
| 1241 this.callFrames = WebInspector.DebuggerModel.CallFrame.fromPayloadArray(debu
ggerModel, callFrames); | 1253 this.callFrames = WebInspector.DebuggerModel.CallFrame.fromPayloadArray(debu
ggerModel, callFrames); |
| 1242 this.reason = reason; | 1254 this.reason = reason; |
| 1243 this.auxData = auxData; | 1255 this.auxData = auxData; |
| 1244 this.breakpointIds = breakpointIds; | 1256 this.breakpointIds = breakpointIds; |
| 1245 if (asyncStackTrace) | 1257 if (asyncStackTrace) |
| 1246 this.asyncStackTrace = this._cleanRedundantFrames(asyncStackTrace); | 1258 this.asyncStackTrace = this._cleanRedundantFrames(asyncStackTrace); |
| 1259 } |
| 1260 |
| 1261 /** |
| 1262 * @return {?WebInspector.RemoteObject} |
| 1263 */ |
| 1264 exception() { |
| 1265 if (this.reason !== WebInspector.DebuggerModel.BreakReason.Exception && |
| 1266 this.reason !== WebInspector.DebuggerModel.BreakReason.PromiseRejection) |
| 1267 return null; |
| 1268 return this.target().runtimeModel.createRemoteObject(/** @type {!RuntimeAgen
t.RemoteObject} */ (this.auxData)); |
| 1269 } |
| 1270 |
| 1271 /** |
| 1272 * @param {!RuntimeAgent.StackTrace} asyncStackTrace |
| 1273 * @return {!RuntimeAgent.StackTrace} |
| 1274 */ |
| 1275 _cleanRedundantFrames(asyncStackTrace) { |
| 1276 var stack = asyncStackTrace; |
| 1277 var previous = null; |
| 1278 while (stack) { |
| 1279 if (stack.description === 'async function' && stack.callFrames.length) |
| 1280 stack.callFrames.shift(); |
| 1281 if (previous && !stack.callFrames.length) |
| 1282 previous.parent = stack.parent; |
| 1283 else |
| 1284 previous = stack; |
| 1285 stack = stack.parent; |
| 1286 } |
| 1287 return asyncStackTrace; |
| 1288 } |
| 1247 }; | 1289 }; |
| 1248 | 1290 |
| 1249 WebInspector.DebuggerPausedDetails.prototype = { | 1291 |
| 1250 /** | |
| 1251 * @return {?WebInspector.RemoteObject} | |
| 1252 */ | |
| 1253 exception: function() | |
| 1254 { | |
| 1255 if (this.reason !== WebInspector.DebuggerModel.BreakReason.Exception &&
this.reason !== WebInspector.DebuggerModel.BreakReason.PromiseRejection) | |
| 1256 return null; | |
| 1257 return this.target().runtimeModel.createRemoteObject(/** @type {!Runtime
Agent.RemoteObject} */(this.auxData)); | |
| 1258 }, | |
| 1259 | |
| 1260 /** | |
| 1261 * @param {!RuntimeAgent.StackTrace} asyncStackTrace | |
| 1262 * @return {!RuntimeAgent.StackTrace} | |
| 1263 */ | |
| 1264 _cleanRedundantFrames: function(asyncStackTrace) | |
| 1265 { | |
| 1266 var stack = asyncStackTrace; | |
| 1267 var previous = null; | |
| 1268 while (stack) { | |
| 1269 if (stack.description === "async function" && stack.callFrames.lengt
h) | |
| 1270 stack.callFrames.shift(); | |
| 1271 if (previous && !stack.callFrames.length) | |
| 1272 previous.parent = stack.parent; | |
| 1273 else | |
| 1274 previous = stack; | |
| 1275 stack = stack.parent; | |
| 1276 } | |
| 1277 return asyncStackTrace; | |
| 1278 }, | |
| 1279 | |
| 1280 __proto__: WebInspector.SDKObject.prototype | |
| 1281 }; | |
| 1282 | |
| 1283 /** | |
| 1284 * @return {!Array<!WebInspector.DebuggerModel>} | |
| 1285 */ | |
| 1286 WebInspector.DebuggerModel.instances = function() | |
| 1287 { | |
| 1288 var result = []; | |
| 1289 for (var target of WebInspector.targetManager.targets()) { | |
| 1290 var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); | |
| 1291 if (debuggerModel) | |
| 1292 result.push(debuggerModel); | |
| 1293 } | |
| 1294 return result; | |
| 1295 }; | |
| 1296 | |
| 1297 /** | |
| 1298 * @param {?WebInspector.Target} target | |
| 1299 * @return {?WebInspector.DebuggerModel} | |
| 1300 */ | |
| 1301 WebInspector.DebuggerModel.fromTarget = function(target) | |
| 1302 { | |
| 1303 if (!target || !target.hasJSCapability()) | |
| 1304 return null; | |
| 1305 return /** @type {?WebInspector.DebuggerModel} */ (target.model(WebInspector
.DebuggerModel)); | |
| 1306 }; | |
| OLD | NEW |