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