d012cff2aafc0d4c51cb523fe87eccea0a232667
[WebKit-https.git] / WebCore / page / inspector / ScriptsPanel.js
1 /*
2  * Copyright (C) 2008 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.ScriptsPanel = function()
27 {
28     WebInspector.Panel.call(this);
29
30     this.element.addStyleClass("scripts");
31
32     this.topStatusBar = document.createElement("div");
33     this.topStatusBar.className = "status-bar";
34     this.topStatusBar.id = "scripts-status-bar";
35     this.element.appendChild(this.topStatusBar);
36
37     this.backButton = document.createElement("button");
38     this.backButton.className = "status-bar-item";
39     this.backButton.id = "scripts-back";
40     this.backButton.title = WebInspector.UIString("Show the previous script resource.");
41     this.backButton.disabled = true;
42     this.backButton.appendChild(document.createElement("img"));
43
44     // FIXME: append the back button element to the top status bar when it is implemented.
45     // this.topStatusBar.appendChild(this.backButton);
46
47     this.forwardButton = document.createElement("button");
48     this.forwardButton.className = "status-bar-item";
49     this.forwardButton.id = "scripts-forward";
50     this.forwardButton.title = WebInspector.UIString("Show the next script resource.");
51     this.forwardButton.disabled = true;
52     this.forwardButton.appendChild(document.createElement("img"));
53
54     // FIXME: append the forward button element to the top status bar when it is implemented.
55     // this.topStatusBar.appendChild(this.forwardButton);
56
57     this.filesSelectElement = document.createElement("select");
58     this.filesSelectElement.className = "status-bar-item";
59     this.filesSelectElement.id = "scripts-files";
60     this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
61     this.topStatusBar.appendChild(this.filesSelectElement);
62
63     this.functionsSelectElement = document.createElement("select");
64     this.functionsSelectElement.className = "status-bar-item";
65     this.functionsSelectElement.id = "scripts-functions";
66
67     // FIXME: append the functions select element to the top status bar when it is implemented.
68     // this.topStatusBar.appendChild(this.functionsSelectElement);
69
70     this.sidebarButtonsElement = document.createElement("div");
71     this.sidebarButtonsElement.id = "scripts-sidebar-buttons";
72     this.topStatusBar.appendChild(this.sidebarButtonsElement);
73
74     this.pauseButton = document.createElement("button");
75     this.pauseButton.className = "status-bar-item";
76     this.pauseButton.id = "scripts-pause";
77     this.pauseButton.title = WebInspector.UIString("Pause script execution.");
78     this.pauseButton.disabled = true;
79     this.pauseButton.appendChild(document.createElement("img"));
80     this.pauseButton.addEventListener("click", this._togglePause.bind(this), false);
81     this.sidebarButtonsElement.appendChild(this.pauseButton);
82
83     this.stepOverButton = document.createElement("button");
84     this.stepOverButton.className = "status-bar-item";
85     this.stepOverButton.id = "scripts-step-over";
86     this.stepOverButton.title = WebInspector.UIString("Step over next function call.");
87     this.stepOverButton.disabled = true;
88     this.stepOverButton.addEventListener("click", this._stepOverClicked.bind(this), false);
89     this.stepOverButton.appendChild(document.createElement("img"));
90     this.sidebarButtonsElement.appendChild(this.stepOverButton);
91
92     this.stepIntoButton = document.createElement("button");
93     this.stepIntoButton.className = "status-bar-item";
94     this.stepIntoButton.id = "scripts-step-into";
95     this.stepIntoButton.title = WebInspector.UIString("Step into next function call.");
96     this.stepIntoButton.disabled = true;
97     this.stepIntoButton.addEventListener("click", this._stepIntoClicked.bind(this), false);
98     this.stepIntoButton.appendChild(document.createElement("img"));
99     this.sidebarButtonsElement.appendChild(this.stepIntoButton);
100
101     this.stepOutButton = document.createElement("button");
102     this.stepOutButton.className = "status-bar-item";
103     this.stepOutButton.id = "scripts-step-out";
104     this.stepOutButton.title = WebInspector.UIString("Step out of current function.");
105     this.stepOutButton.disabled = true;
106     this.stepOutButton.addEventListener("click", this._stepOutClicked.bind(this), false);
107     this.stepOutButton.appendChild(document.createElement("img"));
108     this.sidebarButtonsElement.appendChild(this.stepOutButton);
109
110     this.debuggerStatusElement = document.createElement("div");
111     this.debuggerStatusElement.id = "scripts-debugger-status";
112     this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);
113
114     this.scriptResourceViews = document.createElement("div");
115     this.scriptResourceViews.id = "script-resource-views";
116
117     this.sidebarElement = document.createElement("div");
118     this.sidebarElement.id = "scripts-sidebar";
119
120     this.sidebarResizeElement = document.createElement("div");
121     this.sidebarResizeElement.className = "sidebar-resizer-vertical";
122     this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
123
124     this.sidebarResizeWidgetElement = document.createElement("div");
125     this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
126     this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
127     this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
128
129     this.sidebarPanes = {};
130     this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
131     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
132     this.sidebarPanes.breakpoints = new WebInspector.BreakpointsSidebarPane();
133
134     for (var pane in this.sidebarPanes)
135         this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
136
137     // FIXME: remove the following line of code when the Breakpoints pane has content.
138     this.sidebarElement.removeChild(this.sidebarPanes.breakpoints.element);
139
140     this.sidebarPanes.callstack.expanded = true;
141     this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
142
143     this.sidebarPanes.scopechain.expanded = true;
144
145     this.attachOverlayElement = document.createElement("div");
146     this.attachOverlayElement.id = "scripts-attach-overlay";
147
148     var headerElement = document.createElement("h1");
149     headerElement.textContent = WebInspector.UIString("Starting debugging will reload the inspected page.");
150     this.attachOverlayElement.appendChild(headerElement);
151
152     this.attachOverlayElement.appendChild(document.createElement("br"));
153
154     var attachButton = document.createElement("button");
155     attachButton.textContent = WebInspector.UIString("Start Debugging");
156     attachButton.addEventListener("click", this._toggleDebugging.bind(this), false);
157     this.attachOverlayElement.appendChild(attachButton);
158
159     this.element.appendChild(this.attachOverlayElement);
160     this.element.appendChild(this.scriptResourceViews);
161     this.element.appendChild(this.sidebarElement);
162     this.element.appendChild(this.sidebarResizeElement);
163
164     this.debuggingButton = document.createElement("button");
165     this.debuggingButton.id = "scripts-debugging-status-bar-item";
166     this.debuggingButton.className = "status-bar-item";
167     this.debuggingButton.addEventListener("click", this._toggleDebugging.bind(this), false);
168
169     this.pauseOnExceptionButtons = document.createElement("button");
170     this.pauseOnExceptionButtons.id = "scripts-pause-on-exceptions-status-bar-item";
171     this.pauseOnExceptionButtons.className = "status-bar-item";
172     this.pauseOnExceptionButtons.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
173
174     this._breakpointsURLMap = {};
175
176     this.reset();
177 }
178
179 WebInspector.ScriptsPanel.prototype = {
180     toolbarItemClass: "scripts",
181
182     get toolbarItemLabel()
183     {
184         return WebInspector.UIString("Scripts");
185     },
186
187     get statusBarItems()
188     {
189         return [this.debuggingButton, this.pauseOnExceptionButtons];
190     },
191
192     get paused()
193     {
194         return this._paused;
195     },
196
197     show: function()
198     {
199         WebInspector.Panel.prototype.show.call(this);
200         this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
201
202         if (this.visibleView) {
203             if (this.visibleView instanceof WebInspector.ResourceView)
204                 this.visibleView.headersVisible = false;
205             this.visibleView.show(this.scriptResourceViews);
206         }
207     },
208
209     addScript: function(sourceID, sourceURL, source, startingLine, errorLine, errorMessage)
210     {
211         var script = new WebInspector.Script(sourceID, sourceURL, source, startingLine, errorLine, errorMessage);
212
213         if (sourceURL in WebInspector.resourceURLMap) {
214             var resource = WebInspector.resourceURLMap[sourceURL];
215             resource.addScript(script);
216         }
217
218         if (sourceURL in this._breakpointsURLMap && sourceID) {
219             var breakpoints = this._breakpointsURLMap[sourceURL];
220             var breakpointsLength = breakpoints.length;
221             for (var i = 0; i < breakpointsLength; ++i) {
222                 var breakpoint = breakpoints[i];
223                 if (startingLine <= breakpoint.line)
224                     breakpoint.sourceID = sourceID;
225             }
226
227             InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
228         }
229
230         if (sourceID)
231             this._sourceIDMap[sourceID] = (resource || script);
232
233         this._addScriptToFilesMenu(script);
234     },
235
236     addBreakpoint: function(breakpoint)
237     {
238         this.sidebarPanes.breakpoints.addBreakpoint(breakpoint);
239
240         var sourceFrame;
241         if (breakpoint.url) {
242             if (!(breakpoint.url in this._breakpointsURLMap))
243                 this._breakpointsURLMap[breakpoint.url] = [];
244             this._breakpointsURLMap[breakpoint.url].unshift(breakpoint);
245
246             if (breakpoint.url in WebInspector.resourceURLMap) {
247                 var resource = WebInspector.resourceURLMap[breakpoint.url];
248                 sourceFrame = this._sourceFrameForScriptOrResource(resource);
249             }
250         }
251
252         if (breakpoint.sourceID && !sourceFrame) {
253             var object = this._sourceIDMap[breakpoint.sourceID]
254             sourceFrame = this._sourceFrameForScriptOrResource(object);
255         }
256
257         if (sourceFrame)
258             sourceFrame.addBreakpoint(breakpoint);
259     },
260
261     removeBreakpoint: function(breakpoint)
262     {
263         this.sidebarPanes.breakpoints.removeBreakpoint(breakpoint);
264
265         var sourceFrame;
266         if (breakpoint.url && breakpoint.url in this._breakpointsURLMap) {
267             var breakpoints = this._breakpointsURLMap[breakpoint.url];
268             breakpoints.remove(breakpoint);
269             if (!breakpoints.length)
270                 delete this._breakpointsURLMap[breakpoint.url];
271
272             if (breakpoint.url in WebInspector.resourceURLMap) {
273                 var resource = WebInspector.resourceURLMap[breakpoint.url];
274                 sourceFrame = this._sourceFrameForScriptOrResource(resource);
275             }
276         }
277
278         if (breakpoint.sourceID && !sourceFrame) {
279             var object = this._sourceIDMap[breakpoint.sourceID]
280             sourceFrame = this._sourceFrameForScriptOrResource(object);
281         }
282
283         if (sourceFrame)
284             sourceFrame.removeBreakpoint(breakpoint);
285     },
286
287     evaluateInSelectedCallFrame: function(code)
288     {
289         var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
290         if (!this._paused || !selectedCallFrame)
291             return;
292         var result = selectedCallFrame.evaluate(code);
293         this.sidebarPanes.scopechain.update(selectedCallFrame);
294         return result;
295     },
296
297     debuggerPaused: function()
298     {
299         this._paused = true;
300         this._waitingToPause = false;
301         this._stepping = false;
302
303         this._updateDebuggerButtons();
304
305         var callStackPane = this.sidebarPanes.callstack;
306         var currentFrame = InspectorController.currentCallFrame();
307         callStackPane.update(currentFrame);
308         callStackPane.selectedCallFrame = currentFrame;
309     },
310
311     debuggerAttached: function()
312     {
313         this.reset();
314     },
315
316     debuggerDetached: function()
317     {
318         this.reset();
319     },
320
321     reset: function()
322     {
323         this.visibleView = null;
324
325         if (!InspectorController.debuggerAttached()) {
326             this._paused = false;
327             this._waitingToPause = false;
328             this._stepping = false;
329         }
330
331         this._clearInterface();
332
333         this._scriptsForURLsInFilesSelect = {};
334         this.filesSelectElement.removeChildren();
335         this.functionsSelectElement.removeChildren();
336         this.scriptResourceViews.removeChildren();
337
338         if (this._sourceIDMap) {
339             for (var sourceID in this._sourceIDMap) {
340                 var object = this._sourceIDMap[sourceID];
341                 if (object instanceof WebInspector.Resource)
342                     object.removeAllScripts();
343             }
344         }
345
346         this._sourceIDMap = {};
347     },
348
349     get visibleView()
350     {
351         return this._visibleView;
352     },
353
354     set visibleView(x)
355     {
356         if (this._visibleView === x)
357             return;
358
359         if (this._visibleView)
360             this._visibleView.hide();
361
362         this._visibleView = x;
363
364         if (x)
365             x.show(this.scriptResourceViews);
366     },
367
368     showScript: function(script, line)
369     {
370         this._showScriptOrResource(script, line);
371     },
372
373     showResource: function(resource, line)
374     {
375         this._showScriptOrResource(resource, line);
376     },
377
378     scriptViewForScript: function(script)
379     {
380         if (!script)
381             return null;
382         if (!script._scriptView)
383             script._scriptView = new WebInspector.ScriptView(script);
384         return script._scriptView;
385     },
386
387     sourceFrameForScript: function(script)
388     {
389         var view = this.scriptViewForScript(script);
390         if (!view)
391             return null;
392
393         // Setting up the source frame requires that we be attached.
394         if (!this.element.parentNode)
395             this.attach();
396
397         view.setupSourceFrameIfNeeded();
398         return view.sourceFrame;
399     },
400
401     _sourceFrameForScriptOrResource: function(scriptOrResource)
402     {
403         if (scriptOrResource instanceof WebInspector.Resource)
404             return WebInspector.panels.resources.sourceFrameForResource(scriptOrResource);
405         if (scriptOrResource instanceof WebInspector.Script)
406             return this.sourceFrameForScript(scriptOrResource);
407     },
408
409     _showScriptOrResource: function(scriptOrResource, line)
410     {
411         if (!scriptOrResource)
412             return;
413
414         var view;
415         if (scriptOrResource instanceof WebInspector.Resource) {
416             view = WebInspector.panels.resources.resourceViewForResource(scriptOrResource);
417             view.headersVisible = false;
418
419             if (scriptOrResource.url in this._breakpointsURLMap) {
420                 var sourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
421                 if (sourceFrame && !sourceFrame.breakpoints.length) {
422                     var breakpoints = this._breakpointsURLMap[scriptOrResource.url];
423                     var breakpointsLength = breakpoints.length;
424                     for (var i = 0; i < breakpointsLength; ++i)
425                         sourceFrame.addBreakpoint(breakpoints[i]);
426                 }
427             }
428         } else if (scriptOrResource instanceof WebInspector.Script)
429             view = this.scriptViewForScript(scriptOrResource);
430
431         if (!view)
432             return;
433
434         this.visibleView = view;
435
436         if (line && view.revealLine)
437             view.revealLine(line);
438
439         var option;
440         if (scriptOrResource instanceof WebInspector.Script) {
441             option = script.filesSelectOption;
442             console.assert(option);
443         } else {
444             var url = scriptOrResource.url;
445             var script = this._scriptsForURLsInFilesSelect[url];
446             if (script)
447                option = script.filesSelectOption;
448         }
449
450         if (option)
451             this.filesSelectElement.selectedIndex = option.index;
452     },
453
454     _addScriptToFilesMenu: function(script)
455     {
456         if (script.resource && this._scriptsForURLsInFilesSelect[script.sourceURL])
457             return;
458
459         this._scriptsForURLsInFilesSelect[script.sourceURL] = script;
460
461         var select = this.filesSelectElement;
462
463         // FIXME: Append in some meaningful order.
464         var option = document.createElement("option");
465         option.representedObject = (script.resource || script);
466         option.text = (script.sourceURL ? script.sourceURL.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "") : "(eval script)");
467         select.appendChild(option);
468
469         script.filesSelectOption = option;
470
471         // Call _showScriptOrResource if the option we just appended ended up being selected.
472         // This will happen for the first item added to the menu.
473         if (select.options[select.selectedIndex] === option)
474             this._showScriptOrResource(option.representedObject);
475     },
476
477     _clearCurrentExecutionLine: function()
478     {
479         if (this._executionSourceFrame)
480             this._executionSourceFrame.executionLine = 0;
481         delete this._executionSourceFrame;
482     },
483
484     _callFrameSelected: function()
485     {
486         this._clearCurrentExecutionLine();
487
488         var callStackPane = this.sidebarPanes.callstack;
489         var currentFrame = callStackPane.selectedCallFrame;
490         if (!currentFrame)
491             return;
492
493         this.sidebarPanes.scopechain.update(currentFrame);
494
495         var scriptOrResource = this._sourceIDMap[currentFrame.sourceIdentifier];
496         this._showScriptOrResource(scriptOrResource, currentFrame.line);
497
498         this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
499         if (this._executionSourceFrame)
500             this._executionSourceFrame.executionLine = currentFrame.line;
501     },
502
503     _changeVisibleFile: function(event)
504     {
505         var select = this.filesSelectElement;
506         this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
507     },
508
509     _startSidebarResizeDrag: function(event)
510     {
511         WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "col-resize");
512
513         if (event.target === this.sidebarResizeWidgetElement)
514             this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft));
515         else
516             this._dragOffset = 0;
517     },
518
519     _endSidebarResizeDrag: function(event)
520     {
521         WebInspector.elementDragEnd(event);
522
523         delete this._dragOffset;
524     },
525
526     _sidebarResizeDrag: function(event)
527     {
528         var x = event.pageX + this._dragOffset;
529         var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
530
531         this.sidebarElement.style.width = newWidth + "px";
532         this.sidebarButtonsElement.style.width = newWidth + "px";
533         this.scriptResourceViews.style.right = newWidth + "px";
534         this.sidebarResizeWidgetElement.style.right = newWidth + "px";
535         this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
536
537         event.preventDefault();
538     },
539
540     _updatePauseOnExceptionsButton: function()
541     {
542         if (InspectorController.pauseOnExceptions()) {
543             this.pauseOnExceptionButtons.title = WebInspector.UIString("Don't pause on exceptions.");
544             this.pauseOnExceptionButtons.addStyleClass("toggled-on");
545         } else {
546             this.pauseOnExceptionButtons.title = WebInspector.UIString("Pause on exceptions.");
547             this.pauseOnExceptionButtons.removeStyleClass("toggled-on");
548         }
549     },
550
551     _updateDebuggerButtons: function()
552     {
553         if (InspectorController.debuggerAttached()) {
554             this.debuggingButton.title = WebInspector.UIString("Stop debugging.");
555             this.debuggingButton.addStyleClass("toggled-on");
556             this.pauseButton.disabled = false;
557
558             if (this.attachOverlayElement.parentNode)
559                 this.attachOverlayElement.parentNode.removeChild(this.attachOverlayElement);
560         } else {
561             this.debuggingButton.title = WebInspector.UIString("Start debugging and reload inspected page.");
562             this.debuggingButton.removeStyleClass("toggled-on");
563             this.pauseButton.disabled = true;
564
565             this.element.appendChild(this.attachOverlayElement);
566         }
567
568         this._updatePauseOnExceptionsButton();
569
570         if (this._paused) {
571             this.pauseButton.addStyleClass("paused");
572
573             this.pauseButton.disabled = false;
574             this.stepOverButton.disabled = false;
575             this.stepIntoButton.disabled = false;
576             this.stepOutButton.disabled = false;
577
578             this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
579         } else {
580             this.pauseButton.removeStyleClass("paused");
581
582             this.pauseButton.disabled = this._waitingToPause;
583             this.stepOverButton.disabled = true;
584             this.stepIntoButton.disabled = true;
585             this.stepOutButton.disabled = true;
586
587             if (this._waitingToPause)
588                 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
589             else if (this._stepping)
590                 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
591             else
592                 this.debuggerStatusElement.textContent = "";
593         }
594     },
595
596     _clearInterface: function()
597     {
598         this.sidebarPanes.callstack.update(null);
599         this.sidebarPanes.scopechain.update(null);
600
601         this._clearCurrentExecutionLine();
602         this._updateDebuggerButtons();
603     },
604
605     _toggleDebugging: function()
606     {
607         this._paused = false;
608         this._waitingToPause = false;
609         this._stepping = false;
610
611         if (InspectorController.debuggerAttached())
612             InspectorController.stopDebugging();
613         else
614             InspectorController.startDebuggingAndReloadInspectedPage();
615
616         this._clearInterface();
617     },
618
619     _togglePauseOnExceptions: function()
620     {
621         InspectorController.setPauseOnExceptions(!InspectorController.pauseOnExceptions());
622         this._updatePauseOnExceptionsButton();
623     },
624
625     _togglePause: function()
626     {
627         if (this._paused) {
628             this._paused = false;
629             this._waitingToPause = false;
630             InspectorController.resumeDebugger();
631         } else {
632             this._stepping = false;
633             this._waitingToPause = true;
634             InspectorController.pauseInDebugger();
635         }
636
637         this._clearInterface();
638     },
639
640     _stepOverClicked: function()
641     {
642         this._paused = false;
643         this._stepping = true;
644
645         this._clearInterface();
646
647         InspectorController.stepOverStatementInDebugger();
648     },
649
650     _stepIntoClicked: function()
651     {
652         this._paused = false;
653         this._stepping = true;
654
655         this._clearInterface();
656
657         InspectorController.stepIntoStatementInDebugger();
658     },
659
660     _stepOutClicked: function()
661     {
662         this._paused = false;
663         this._stepping = true;
664
665         this._clearInterface();
666
667         InspectorController.stepOutOfFunctionInDebugger();
668     }
669 }
670
671 WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;