1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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. 29 */ 30 31 /** 32 * @constructor 33 * @extends {WebInspector.Object} 34 */ 35 WebInspector.DebuggerModel = function() 36 { 37 InspectorBackend.registerDebuggerDispatcher(new WebInspector.DebuggerDispatcher(this)); 38 39 this._debuggerPausedDetails = null; 40 /** 41 * @type {Object.<string, WebInspector.Script>} 42 */ 43 this._scripts = {}; 44 /** @type {!Object.<!string, !Array.<!WebInspector.Script>>} */ 45 this._scriptsBySourceURL = {}; 46 47 this._canSetScriptSource = false; 48 this._breakpointsActive = true; 49 50 WebInspector.settings.pauseOnExceptionStateString = WebInspector.settings.createSetting("pauseOnExceptionStateString", WebInspector.DebuggerModel.PauseOnExceptionsState.DontPauseOnExceptions); 51 WebInspector.settings.pauseOnExceptionStateString.addChangeListener(this._pauseOnExceptionStateChanged, this); 52 53 this.enableDebugger(); 54 55 WebInspector.DebuggerModel.applySkipStackFrameSettings(); 56 } 57 58 // Keep these in sync with WebCore::ScriptDebugServer 59 WebInspector.DebuggerModel.PauseOnExceptionsState = { 60 DontPauseOnExceptions : "none", 61 PauseOnAllExceptions : "all", 62 PauseOnUncaughtExceptions: "uncaught" 63 }; 64 65 /** 66 * @constructor 67 * @implements {WebInspector.RawLocation} 68 * @param {string} scriptId 69 * @param {number} lineNumber 70 * @param {number} columnNumber 71 */ 72 WebInspector.DebuggerModel.Location = function(scriptId, lineNumber, columnNumber) 73 { 74 this.scriptId = scriptId; 75 this.lineNumber = lineNumber; 76 this.columnNumber = columnNumber; 77 } 78 79 WebInspector.DebuggerModel.Events = { 80 DebuggerWasEnabled: "DebuggerWasEnabled", 81 DebuggerWasDisabled: "DebuggerWasDisabled", 82 DebuggerPaused: "DebuggerPaused", 83 DebuggerResumed: "DebuggerResumed", 84 ParsedScriptSource: "ParsedScriptSource", 85 FailedToParseScriptSource: "FailedToParseScriptSource", 86 BreakpointResolved: "BreakpointResolved", 87 GlobalObjectCleared: "GlobalObjectCleared", 88 CallFrameSelected: "CallFrameSelected", 89 ExecutionLineChanged: "ExecutionLineChanged", 90 ConsoleCommandEvaluatedInSelectedCallFrame: "ConsoleCommandEvaluatedInSelectedCallFrame", 91 BreakpointsActiveStateChanged: "BreakpointsActiveStateChanged" 92 } 93 94 WebInspector.DebuggerModel.BreakReason = { 95 DOM: "DOM", 96 EventListener: "EventListener", 97 XHR: "XHR", 98 Exception: "exception", 99 Assert: "assert", 100 CSPViolation: "CSPViolation", 101 DebugCommand: "debugCommand" 102 } 103 104 WebInspector.DebuggerModel.prototype = { 105 /** 106 * @return {boolean} 107 */ 108 debuggerEnabled: function() 109 { 110 return !!this._debuggerEnabled; 111 }, 112 113 enableDebugger: function() 114 { 115 if (this._debuggerEnabled) 116 return; 117 118 function callback(error, result) 119 { 120 this._canSetScriptSource = result; 121 } 122 DebuggerAgent.canSetScriptSource(callback.bind(this)); 123 DebuggerAgent.enable(this._debuggerWasEnabled.bind(this)); 124 }, 125 126 disableDebugger: function() 127 { 128 if (!this._debuggerEnabled) 129 return; 130 131 DebuggerAgent.disable(this._debuggerWasDisabled.bind(this)); 132 }, 133 134 /** 135 * @return {boolean} 136 */ 137 canSetScriptSource: function() 138 { 139 return this._canSetScriptSource; 140 }, 141 142 _debuggerWasEnabled: function() 143 { 144 this._debuggerEnabled = true; 145 this._pauseOnExceptionStateChanged(); 146 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasEnabled); 147 }, 148 149 _pauseOnExceptionStateChanged: function() 150 { 151 DebuggerAgent.setPauseOnExceptions(WebInspector.settings.pauseOnExceptionStateString.get()); 152 }, 153 154 _debuggerWasDisabled: function() 155 { 156 this._debuggerEnabled = false; 157 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasDisabled); 158 }, 159 160 /** 161 * @param {WebInspector.DebuggerModel.Location} rawLocation 162 */ 163 continueToLocation: function(rawLocation) 164 { 165 DebuggerAgent.continueToLocation(rawLocation); 166 }, 167 168 /** 169 * @param {WebInspector.DebuggerModel.Location} rawLocation 170 * @param {string} condition 171 * @param {function(?DebuggerAgent.BreakpointId, Array.<WebInspector.DebuggerModel.Location>):void=} callback 172 */ 173 setBreakpointByScriptLocation: function(rawLocation, condition, callback) 174 { 175 var script = this.scriptForId(rawLocation.scriptId); 176 if (script.sourceURL) 177 this.setBreakpointByURL(script.sourceURL, rawLocation.lineNumber, rawLocation.columnNumber, condition, callback); 178 else 179 this.setBreakpointBySourceId(rawLocation, condition, callback); 180 }, 181 182 /** 183 * @param {string} url 184 * @param {number} lineNumber 185 * @param {number=} columnNumber 186 * @param {string=} condition 187 * @param {function(?DebuggerAgent.BreakpointId, Array.<WebInspector.DebuggerModel.Location>)=} callback 188 */ 189 setBreakpointByURL: function(url, lineNumber, columnNumber, condition, callback) 190 { 191 // Adjust column if needed. 192 var minColumnNumber = 0; 193 var scripts = this._scriptsBySourceURL[url] || []; 194 for (var i = 0, l = scripts.length; i < l; ++i) { 195 var script = scripts[i]; 196 if (lineNumber === script.lineOffset) 197 minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, script.columnOffset) : script.columnOffset; 198 } 199 columnNumber = Math.max(columnNumber, minColumnNumber); 200 201 /** 202 * @this {WebInspector.DebuggerModel} 203 * @param {?Protocol.Error} error 204 * @param {DebuggerAgent.BreakpointId} breakpointId 205 * @param {Array.<DebuggerAgent.Location>} locations 206 */ 207 function didSetBreakpoint(error, breakpointId, locations) 208 { 209 if (callback) { 210 var rawLocations = /** @type {Array.<WebInspector.DebuggerModel.Location>} */ (locations); 211 callback(error ? null : breakpointId, rawLocations); 212 } 213 } 214 DebuggerAgent.setBreakpointByUrl(lineNumber, url, undefined, columnNumber, condition, undefined, didSetBreakpoint.bind(this)); 215 WebInspector.userMetrics.ScriptsBreakpointSet.record(); 216 }, 217 218 /** 219 * @param {WebInspector.DebuggerModel.Location} rawLocation 220 * @param {string} condition 221 * @param {function(?DebuggerAgent.BreakpointId, Array.<WebInspector.DebuggerModel.Location>)=} callback 222 */ 223 setBreakpointBySourceId: function(rawLocation, condition, callback) 224 { 225 /** 226 * @this {WebInspector.DebuggerModel} 227 * @param {?Protocol.Error} error 228 * @param {DebuggerAgent.BreakpointId} breakpointId 229 * @param {DebuggerAgent.Location} actualLocation 230 */ 231 function didSetBreakpoint(error, breakpointId, actualLocation) 232 { 233 if (callback) { 234 var rawLocation = /** @type {WebInspector.DebuggerModel.Location} */ (actualLocation); 235 callback(error ? null : breakpointId, [rawLocation]); 236 } 237 } 238 DebuggerAgent.setBreakpoint(rawLocation, condition, didSetBreakpoint.bind(this)); 239 WebInspector.userMetrics.ScriptsBreakpointSet.record(); 240 }, 241 242 /** 243 * @param {DebuggerAgent.BreakpointId} breakpointId 244 * @param {function(?Protocol.Error)=} callback 245 */ 246 removeBreakpoint: function(breakpointId, callback) 247 { 248 DebuggerAgent.removeBreakpoint(breakpointId, callback); 249 }, 250 251 /** 252 * @param {DebuggerAgent.BreakpointId} breakpointId 253 * @param {DebuggerAgent.Location} location 254 */ 255 _breakpointResolved: function(breakpointId, location) 256 { 257 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointResolved, {breakpointId: breakpointId, location: location}); 258 }, 259 260 _globalObjectCleared: function() 261 { 262 this._setDebuggerPausedDetails(null); 263 this._reset(); 264 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.GlobalObjectCleared); 265 }, 266 267 _reset: function() 268 { 269 this._scripts = {}; 270 this._scriptsBySourceURL = {}; 271 }, 272 273 /** 274 * @return {Object.<string, WebInspector.Script>} 275 */ 276 get scripts() 277 { 278 return this._scripts; 279 }, 280 281 /** 282 * @param {DebuggerAgent.ScriptId} scriptId 283 * @return {WebInspector.Script} 284 */ 285 scriptForId: function(scriptId) 286 { 287 return this._scripts[scriptId] || null; 288 }, 289 290 /** 291 * @return {!Array.<!WebInspector.Script>} 292 */ 293 scriptsForSourceURL: function(sourceURL) 294 { 295 if (!sourceURL) 296 return []; 297 return this._scriptsBySourceURL[sourceURL] || []; 298 }, 299 300 /** 301 * @param {DebuggerAgent.ScriptId} scriptId 302 * @param {string} newSource 303 * @param {function(?Protocol.Error, DebuggerAgent.SetScriptSourceError=)} callback 304 */ 305 setScriptSource: function(scriptId, newSource, callback) 306 { 307 this._scripts[scriptId].editSource(newSource, this._didEditScriptSource.bind(this, scriptId, newSource, callback)); 308 }, 309 310 /** 311 * @param {DebuggerAgent.ScriptId} scriptId 312 * @param {string} newSource 313 * @param {function(?Protocol.Error, DebuggerAgent.SetScriptSourceError=)} callback 314 * @param {?Protocol.Error} error 315 * @param {DebuggerAgent.SetScriptSourceError=} errorData 316 * @param {Array.<DebuggerAgent.CallFrame>=} callFrames 317 */ 318 _didEditScriptSource: function(scriptId, newSource, callback, error, errorData, callFrames) 319 { 320 callback(error, errorData); 321 if (!error && callFrames && callFrames.length) 322 this._pausedScript(callFrames, this._debuggerPausedDetails.reason, this._debuggerPausedDetails.auxData, this._debuggerPausedDetails.breakpointIds); 323 }, 324 325 /** 326 * @return {Array.<DebuggerAgent.CallFrame>} 327 */ 328 get callFrames() 329 { 330 return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFrames : null; 331 }, 332 333 /** 334 * @return {?WebInspector.DebuggerPausedDetails} 335 */ 336 debuggerPausedDetails: function() 337 { 338 return this._debuggerPausedDetails; 339 }, 340 341 /** 342 * @param {?WebInspector.DebuggerPausedDetails} debuggerPausedDetails 343 */ 344 _setDebuggerPausedDetails: function(debuggerPausedDetails) 345 { 346 if (this._debuggerPausedDetails) 347 this._debuggerPausedDetails.dispose(); 348 this._debuggerPausedDetails = debuggerPausedDetails; 349 if (this._debuggerPausedDetails) 350 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPausedDetails); 351 if (debuggerPausedDetails) { 352 this.setSelectedCallFrame(debuggerPausedDetails.callFrames[0]); 353 DebuggerAgent.setOverlayMessage(WebInspector.UIString("Paused in debugger")); 354 } else { 355 this.setSelectedCallFrame(null); 356 DebuggerAgent.setOverlayMessage(); 357 } 358 }, 359 360 /** 361 * @param {Array.<DebuggerAgent.CallFrame>} callFrames 362 * @param {string} reason 363 * @param {Object|undefined} auxData 364 * @param {Array.<string>} breakpointIds 365 */ 366 _pausedScript: function(callFrames, reason, auxData, breakpointIds) 367 { 368 this._setDebuggerPausedDetails(new WebInspector.DebuggerPausedDetails(this, callFrames, reason, auxData, breakpointIds)); 369 }, 370 371 _resumedScript: function() 372 { 373 this._setDebuggerPausedDetails(null); 374 if (this._executionLineLiveLocation) 375 this._executionLineLiveLocation.dispose(); 376 this._executionLineLiveLocation = null; 377 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed); 378 }, 379 380 /** 381 * @param {DebuggerAgent.ScriptId} scriptId 382 * @param {string} sourceURL 383 * @param {number} startLine 384 * @param {number} startColumn 385 * @param {number} endLine 386 * @param {number} endColumn 387 * @param {boolean} isContentScript 388 * @param {string=} sourceMapURL 389 * @param {boolean=} hasSourceURL 390 */ 391 _parsedScriptSource: function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL, hasSourceURL) 392 { 393 var script = new WebInspector.Script(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL, hasSourceURL); 394 this._registerScript(script); 395 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScriptSource, script); 396 }, 397 398 /** 399 * @param {WebInspector.Script} script 400 */ 401 _registerScript: function(script) 402 { 403 this._scripts[script.scriptId] = script; 404 if (script.isAnonymousScript()) 405 return; 406 407 var scripts = this._scriptsBySourceURL[script.sourceURL]; 408 if (!scripts) { 409 scripts = []; 410 this._scriptsBySourceURL[script.sourceURL] = scripts; 411 } 412 scripts.push(script); 413 }, 414 415 /** 416 * @param {WebInspector.Script} script 417 * @param {number} lineNumber 418 * @param {number} columnNumber 419 * @return {WebInspector.DebuggerModel.Location} 420 */ 421 createRawLocation: function(script, lineNumber, columnNumber) 422 { 423 if (script.sourceURL) 424 return this.createRawLocationByURL(script.sourceURL, lineNumber, columnNumber) 425 return new WebInspector.DebuggerModel.Location(script.scriptId, lineNumber, columnNumber); 426 }, 427 428 /** 429 * @param {string} sourceURL 430 * @param {number} lineNumber 431 * @param {number} columnNumber 432 * @return {WebInspector.DebuggerModel.Location} 433 */ 434 createRawLocationByURL: function(sourceURL, lineNumber, columnNumber) 435 { 436 var closestScript = null; 437 var scripts = this._scriptsBySourceURL[sourceURL] || []; 438 for (var i = 0, l = scripts.length; i < l; ++i) { 439 var script = scripts[i]; 440 if (!closestScript) 441 closestScript = script; 442 if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber)) 443 continue; 444 if (script.endLine < lineNumber || (script.endLine === lineNumber && script.endColumn <= columnNumber)) 445 continue; 446 closestScript = script; 447 break; 448 } 449 return closestScript ? new WebInspector.DebuggerModel.Location(closestScript.scriptId, lineNumber, columnNumber) : null; 450 }, 451 452 /** 453 * @return {boolean} 454 */ 455 isPaused: function() 456 { 457 return !!this.debuggerPausedDetails(); 458 }, 459 460 /** 461 * @param {?WebInspector.DebuggerModel.CallFrame} callFrame 462 */ 463 setSelectedCallFrame: function(callFrame) 464 { 465 if (this._executionLineLiveLocation) 466 this._executionLineLiveLocation.dispose(); 467 delete this._executionLineLiveLocation; 468 469 this._selectedCallFrame = callFrame; 470 if (!this._selectedCallFrame) 471 return; 472 473 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.CallFrameSelected, callFrame); 474 475 function updateExecutionLine(uiLocation) 476 { 477 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ExecutionLineChanged, uiLocation); 478 } 479 this._executionLineLiveLocation = callFrame.script.createLiveLocation(callFrame.location, updateExecutionLine.bind(this)); 480 }, 481 482 /** 483 * @return {?WebInspector.DebuggerModel.CallFrame} 484 */ 485 selectedCallFrame: function() 486 { 487 return this._selectedCallFrame; 488 }, 489 490 /** 491 * @param {string} code 492 * @param {string} objectGroup 493 * @param {boolean} includeCommandLineAPI 494 * @param {boolean} doNotPauseOnExceptionsAndMuteConsole 495 * @param {boolean} returnByValue 496 * @param {boolean} generatePreview 497 * @param {function(?WebInspector.RemoteObject, boolean, RuntimeAgent.RemoteObject=)} callback 498 */ 499 evaluateOnSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, callback) 500 { 501 /** 502 * @param {?RuntimeAgent.RemoteObject} result 503 * @param {boolean=} wasThrown 504 */ 505 function didEvaluate(result, wasThrown) 506 { 507 if (returnByValue) 508 callback(null, !!wasThrown, wasThrown ? null : result); 509 else 510 callback(WebInspector.RemoteObject.fromPayload(result), !!wasThrown); 511 512 if (objectGroup === "console") 513 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame); 514 } 515 516 this.selectedCallFrame().evaluate(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, didEvaluate.bind(this)); 517 }, 518 519 /** 520 * @param {function(Object)} callback 521 */ 522 getSelectedCallFrameVariables: function(callback) 523 { 524 var result = { this: true }; 525 526 var selectedCallFrame = this._selectedCallFrame; 527 if (!selectedCallFrame) 528 callback(result); 529 530 var pendingRequests = 0; 531 532 function propertiesCollected(properties) 533 { 534 for (var i = 0; properties && i < properties.length; ++i) 535 result[properties[i].name] = true; 536 if (--pendingRequests == 0) 537 callback(result); 538 } 539 540 for (var i = 0; i < selectedCallFrame.scopeChain.length; ++i) { 541 var scope = selectedCallFrame.scopeChain[i]; 542 var object = WebInspector.RemoteObject.fromPayload(scope.object); 543 pendingRequests++; 544 object.getAllProperties(false, propertiesCollected); 545 } 546 }, 547 548 /** 549 * @param {boolean} active 550 */ 551 setBreakpointsActive: function(active) 552 { 553 if (this._breakpointsActive === active) 554 return; 555 this._breakpointsActive = active; 556 DebuggerAgent.setBreakpointsActive(active); 557 this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, active); 558 }, 559 560 /** 561 * @return {boolean} 562 */ 563 breakpointsActive: function() 564 { 565 return this._breakpointsActive; 566 }, 567 568 /** 569 * @param {WebInspector.DebuggerModel.Location} rawLocation 570 * @param {function(WebInspector.UILocation):(boolean|undefined)} updateDelegate 571 * @return {WebInspector.Script.Location} 572 */ 573 createLiveLocation: function(rawLocation, updateDelegate) 574 { 575 var script = this._scripts[rawLocation.scriptId]; 576 return script.createLiveLocation(rawLocation, updateDelegate); 577 }, 578 579 /** 580 * @param {WebInspector.DebuggerModel.Location} rawLocation 581 * @return {?WebInspector.UILocation} 582 */ 583 rawLocationToUILocation: function(rawLocation) 584 { 585 var script = this._scripts[rawLocation.scriptId]; 586 if (!script) 587 return null; 588 return script.rawLocationToUILocation(rawLocation.lineNumber, rawLocation.columnNumber); 589 }, 590 591 /** 592 * Handles notification from JavaScript VM about updated stack (liveedit or frame restart action). 593 * @this {WebInspector.DebuggerModel} 594 * @param {Array.<DebuggerAgent.CallFrame>=} newCallFrames 595 * @param {Object=} details 596 */ 597 callStackModified: function(newCallFrames, details) 598 { 599 // FIXME: declare this property in protocol and in JavaScript. 600 if (details && details["stack_update_needs_step_in"]) 601 DebuggerAgent.stepInto(); 602 else { 603 if (newCallFrames && newCallFrames.length) 604 this._pausedScript(newCallFrames, this._debuggerPausedDetails.reason, this._debuggerPausedDetails.auxData, this._debuggerPausedDetails.breakpointIds); 605 606 } 607 }, 608 609 __proto__: WebInspector.Object.prototype 610 } 611 612 WebInspector.DebuggerModel.applySkipStackFrameSettings = function() 613 { 614 if (!WebInspector.experimentsSettings.frameworksDebuggingSupport.isEnabled()) 615 return; 616 var settings = WebInspector.settings; 617 var patternParameter = settings.skipStackFramesSwitch.get() ? settings.skipStackFramesPattern.get() : undefined; 618 DebuggerAgent.skipStackFrames(patternParameter); 619 } 620 621 WebInspector.DebuggerEventTypes = { 622 JavaScriptPause: 0, 623 JavaScriptBreakpoint: 1, 624 NativeBreakpoint: 2 625 }; 626 627 /** 628 * @constructor 629 * @implements {DebuggerAgent.Dispatcher} 630 * @param {WebInspector.DebuggerModel} debuggerModel 631 */ 632 WebInspector.DebuggerDispatcher = function(debuggerModel) 633 { 634 this._debuggerModel = debuggerModel; 635 } 636 637 WebInspector.DebuggerDispatcher.prototype = { 638 /** 639 * @param {Array.<DebuggerAgent.CallFrame>} callFrames 640 * @param {string} reason 641 * @param {Object=} auxData 642 * @param {Array.<string>=} breakpointIds 643 */ 644 paused: function(callFrames, reason, auxData, breakpointIds) 645 { 646 this._debuggerModel._pausedScript(callFrames, reason, auxData, breakpointIds || []); 647 }, 648 649 resumed: function() 650 { 651 this._debuggerModel._resumedScript(); 652 }, 653 654 globalObjectCleared: function() 655 { 656 this._debuggerModel._globalObjectCleared(); 657 }, 658 659 /** 660 * @param {DebuggerAgent.ScriptId} scriptId 661 * @param {string} sourceURL 662 * @param {number} startLine 663 * @param {number} startColumn 664 * @param {number} endLine 665 * @param {number} endColumn 666 * @param {boolean=} isContentScript 667 * @param {string=} sourceMapURL 668 * @param {boolean=} hasSourceURL 669 */ 670 scriptParsed: function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL, hasSourceURL) 671 { 672 this._debuggerModel._parsedScriptSource(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, !!isContentScript, sourceMapURL, hasSourceURL); 673 }, 674 675 /** 676 * @param {string} sourceURL 677 * @param {string} source 678 * @param {number} startingLine 679 * @param {number} errorLine 680 * @param {string} errorMessage 681 */ 682 scriptFailedToParse: function(sourceURL, source, startingLine, errorLine, errorMessage) 683 { 684 }, 685 686 /** 687 * @param {DebuggerAgent.BreakpointId} breakpointId 688 * @param {DebuggerAgent.Location} location 689 */ 690 breakpointResolved: function(breakpointId, location) 691 { 692 this._debuggerModel._breakpointResolved(breakpointId, location); 693 } 694 } 695 696 /** 697 * @constructor 698 * @param {WebInspector.Script} script 699 * @param {DebuggerAgent.CallFrame} payload 700 */ 701 WebInspector.DebuggerModel.CallFrame = function(script, payload) 702 { 703 this._script = script; 704 this._payload = payload; 705 this._locations = []; 706 } 707 708 WebInspector.DebuggerModel.CallFrame.prototype = { 709 /** 710 * @return {WebInspector.Script} 711 */ 712 get script() 713 { 714 return this._script; 715 }, 716 717 /** 718 * @return {string} 719 */ 720 get type() 721 { 722 return this._payload.type; 723 }, 724 725 /** 726 * @return {string} 727 */ 728 get id() 729 { 730 return this._payload.callFrameId; 731 }, 732 733 /** 734 * @return {Array.<DebuggerAgent.Scope>} 735 */ 736 get scopeChain() 737 { 738 return this._payload.scopeChain; 739 }, 740 741 /** 742 * @return {RuntimeAgent.RemoteObject} 743 */ 744 get this() 745 { 746 return this._payload.this; 747 }, 748 749 /** 750 * @return {string} 751 */ 752 get functionName() 753 { 754 return this._payload.functionName; 755 }, 756 757 /** 758 * @return {WebInspector.DebuggerModel.Location} 759 */ 760 get location() 761 { 762 var rawLocation = /** @type {WebInspector.DebuggerModel.Location} */ (this._payload.location); 763 return rawLocation; 764 }, 765 766 /** 767 * @param {string} code 768 * @param {string} objectGroup 769 * @param {boolean} includeCommandLineAPI 770 * @param {boolean} doNotPauseOnExceptionsAndMuteConsole 771 * @param {boolean} returnByValue 772 * @param {boolean} generatePreview 773 * @param {function(?RuntimeAgent.RemoteObject, boolean=)=} callback 774 */ 775 evaluate: function(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, callback) 776 { 777 /** 778 * @this {WebInspector.DebuggerModel.CallFrame} 779 * @param {?Protocol.Error} error 780 * @param {RuntimeAgent.RemoteObject} result 781 * @param {boolean=} wasThrown 782 */ 783 function didEvaluateOnCallFrame(error, result, wasThrown) 784 { 785 if (error) { 786 console.error(error); 787 callback(null, false); 788 return; 789 } 790 callback(result, wasThrown); 791 } 792 DebuggerAgent.evaluateOnCallFrame(this._payload.callFrameId, code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, didEvaluateOnCallFrame.bind(this)); 793 }, 794 795 /** 796 * @param {function(?Protocol.Error=)=} callback 797 */ 798 restart: function(callback) 799 { 800 /** 801 * @this {WebInspector.DebuggerModel.CallFrame} 802 * @param {?Protocol.Error} error 803 * @param {Array.<DebuggerAgent.CallFrame>=} callFrames 804 * @param {Object=} details 805 */ 806 function protocolCallback(error, callFrames, details) 807 { 808 if (!error) 809 WebInspector.debuggerModel.callStackModified(callFrames, details); 810 if (callback) 811 callback(error); 812 } 813 DebuggerAgent.restartFrame(this._payload.callFrameId, protocolCallback); 814 }, 815 816 /** 817 * @param {function(WebInspector.UILocation):(boolean|undefined)} updateDelegate 818 */ 819 createLiveLocation: function(updateDelegate) 820 { 821 var location = this._script.createLiveLocation(this.location, updateDelegate); 822 this._locations.push(location); 823 return location; 824 }, 825 826 dispose: function(updateDelegate) 827 { 828 for (var i = 0; i < this._locations.length; ++i) 829 this._locations[i].dispose(); 830 this._locations = []; 831 } 832 } 833 834 /** 835 * @constructor 836 * @param {WebInspector.DebuggerModel} model 837 * @param {Array.<DebuggerAgent.CallFrame>} callFrames 838 * @param {string} reason 839 * @param {Object|undefined} auxData 840 * @param {Array.<string>} breakpointIds 841 */ 842 WebInspector.DebuggerPausedDetails = function(model, callFrames, reason, auxData, breakpointIds) 843 { 844 this.callFrames = []; 845 for (var i = 0; i < callFrames.length; ++i) { 846 var callFrame = callFrames[i]; 847 var script = model.scriptForId(callFrame.location.scriptId); 848 if (script) 849 this.callFrames.push(new WebInspector.DebuggerModel.CallFrame(script, callFrame)); 850 } 851 this.reason = reason; 852 this.auxData = auxData; 853 this.breakpointIds = breakpointIds; 854 } 855 856 WebInspector.DebuggerPausedDetails.prototype = { 857 dispose: function() 858 { 859 for (var i = 0; i < this.callFrames.length; ++i) { 860 var callFrame = this.callFrames[i]; 861 callFrame.dispose(); 862 } 863 } 864 } 865 866 /** 867 * @type {?WebInspector.DebuggerModel} 868 */ 869 WebInspector.debuggerModel = null; 870