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