Web Inspector: Don't throw exceptions when we don't have a callstack
[WebKit-https.git] / Source / WebCore / inspector / front-end / ScriptsPanel.js
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 importScript("BreakpointsSidebarPane.js");
28 importScript("CallStackSidebarPane.js");
29 importScript("FilteredItemSelectionDialog.js");
30 importScript("JavaScriptSourceFrame.js");
31 importScript("NavigatorOverlayController.js");
32 importScript("NavigatorView.js");
33 importScript("RevisionHistoryView.js");
34 importScript("ScopeChainSidebarPane.js");
35 importScript("ScriptsNavigator.js");
36 importScript("ScriptsSearchScope.js");
37 importScript("SnippetJavaScriptSourceFrame.js");
38 importScript("StyleSheetOutlineDialog.js");
39 importScript("TabbedEditorContainer.js");
40 importScript("UISourceCodeFrame.js");
41 importScript("WatchExpressionsSidebarPane.js");
42 importScript("WorkersSidebarPane.js");
43
44 /**
45  * @constructor
46  * @implements {WebInspector.TabbedEditorContainerDelegate}
47  * @implements {WebInspector.ContextMenu.Provider}
48  * @extends {WebInspector.Panel}
49  * @param {WebInspector.Workspace=} workspaceForTest
50  */
51 WebInspector.ScriptsPanel = function(workspaceForTest)
52 {
53     WebInspector.Panel.call(this, "scripts");
54     this.registerRequiredCSS("scriptsPanel.css");
55
56     WebInspector.settings.navigatorWasOnceHidden = WebInspector.settings.createSetting("navigatorWasOnceHidden", false);
57     WebInspector.settings.debuggerSidebarHidden = WebInspector.settings.createSetting("debuggerSidebarHidden", false);
58
59     this._workspace = workspaceForTest || WebInspector.workspace;
60
61     function viewGetter()
62     {
63         return this.visibleView;
64     }
65     WebInspector.GoToLineDialog.install(this, viewGetter.bind(this));
66
67     var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Sources Panel"));
68     this.debugToolbar = this._createDebugToolbar();
69
70     const initialDebugSidebarWidth = 225;
71     const minimumDebugSidebarWidthPercent = 50;
72     this.createSidebarView(this.element, WebInspector.SidebarView.SidebarPosition.Right, initialDebugSidebarWidth);
73     this.splitView.element.id = "scripts-split-view";
74     this.splitView.setMinimumSidebarWidth(Preferences.minScriptsSidebarWidth);
75     this.splitView.setMinimumMainWidthPercent(minimumDebugSidebarWidthPercent);
76
77     this.sidebarElement.appendChild(this.debugToolbar);
78
79     this.debugSidebarResizeWidgetElement = document.createElement("div");
80     this.debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
81     this.splitView.installResizer(this.debugSidebarResizeWidgetElement);
82
83     // Create scripts navigator
84     const initialNavigatorWidth = 225;
85     const minimumViewsContainerWidthPercent = 50;
86     this.editorView = new WebInspector.SidebarView(WebInspector.SidebarView.SidebarPosition.Left, "scriptsPanelNavigatorSidebarWidth", initialNavigatorWidth);
87     this.editorView.element.tabIndex = 0;
88
89     this.editorView.setMinimumSidebarWidth(Preferences.minScriptsSidebarWidth);
90     this.editorView.setMinimumMainWidthPercent(minimumViewsContainerWidthPercent);
91     this.editorView.show(this.splitView.mainElement);
92
93     this._navigator = new WebInspector.ScriptsNavigator();
94     this._navigator.view.show(this.editorView.sidebarElement);
95
96     this._editorContainer = new WebInspector.TabbedEditorContainer(this, "previouslyViewedFiles");
97     this._editorContainer.show(this.editorView.mainElement);
98
99     this._navigatorController = new WebInspector.NavigatorOverlayController(this.editorView, this._navigator.view, this._editorContainer.view);
100
101     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ScriptSelected, this._scriptSelected, this);
102     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.SnippetCreationRequested, this._snippetCreationRequested, this);
103     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ItemRenamingRequested, this._itemRenamingRequested, this);
104     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.FileRenamed, this._fileRenamed, this);
105
106     this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorSelected, this._editorSelected, this);
107     this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorClosed, this._editorClosed, this);
108
109     this.splitView.mainElement.appendChild(this.debugSidebarResizeWidgetElement);
110
111     this.sidebarPanes = {};
112     this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
113     this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
114     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
115     this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.breakpointManager, this._showSourceLine.bind(this));
116     this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane;
117     this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
118     this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
119
120     if (InspectorFrontendHost.canInspectWorkers() && !WebInspector.WorkerManager.isWorkerFrontend()) {
121         WorkerAgent.enable();
122         this.sidebarPanes.workerList = new WebInspector.WorkersSidebarPane(WebInspector.workerManager);
123     }
124
125     this._debugSidebarContentsElement = document.createElement("div");
126     this._debugSidebarContentsElement.id = "scripts-debug-sidebar-contents";
127     this.sidebarElement.appendChild(this._debugSidebarContentsElement);
128
129     for (var pane in this.sidebarPanes) {
130         if (this.sidebarPanes[pane] === this.sidebarPanes.domBreakpoints)
131             continue;
132         this._debugSidebarContentsElement.appendChild(this.sidebarPanes[pane].element);
133     }
134
135     this.sidebarPanes.callstack.expanded = true;
136
137     this.sidebarPanes.scopechain.expanded = true;
138     this.sidebarPanes.jsBreakpoints.expanded = true;
139
140     this.sidebarPanes.callstack.registerShortcuts(this.registerShortcuts.bind(this));
141     this.registerShortcuts(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.EvaluateSelectionInConsole, this._evaluateSelectionInConsole.bind(this));
142     this.registerShortcuts(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.GoToMember, this._showOutlineDialog.bind(this));
143     this.registerShortcuts(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.ToggleBreakpoint, this._toggleBreakpoint.bind(this));
144
145     var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
146     var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
147     var panelEnablerButton = WebInspector.UIString("Enable Debugging");
148
149     this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
150     this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
151
152     this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
153     this.enableToggleButton.addEventListener("click", this._toggleDebugging, this);
154     if (!Capabilities.debuggerCausesRecompilation)
155         this.enableToggleButton.element.addStyleClass("hidden");
156
157     this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
158     this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this);
159
160     this._toggleFormatSourceButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "scripts-toggle-pretty-print-status-bar-item");
161     this._toggleFormatSourceButton.toggled = false;
162     this._toggleFormatSourceButton.addEventListener("click", this._toggleFormatSource, this);
163
164     this._scriptViewStatusBarItemsContainer = document.createElement("div");
165     this._scriptViewStatusBarItemsContainer.style.display = "inline-block";
166
167     this._installDebuggerSidebarController();
168
169     this._sourceFramesByUISourceCode = new Map();
170     this._updateDebuggerButtons();
171     this._pauseOnExceptionStateChanged();
172     if (WebInspector.debuggerModel.isPaused())
173         this._debuggerPaused();
174
175     WebInspector.settings.pauseOnExceptionStateString.addChangeListener(this._pauseOnExceptionStateChanged, this);
176     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
177     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this);
178     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
179     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
180     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this);
181     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
182     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ExecutionLineChanged, this._executionLineChanged, this);
183     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
184
185     WebInspector.startBatchUpdate();
186     var uiSourceCodes = this._workspace.uiSourceCodes();
187     for (var i = 0; i < uiSourceCodes.length; ++i)
188         this._addUISourceCode(uiSourceCodes[i]);
189     WebInspector.endBatchUpdate();
190
191     this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
192     this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
193     this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.TemporaryUISourceCodeRemoved, this._uiSourceCodeRemoved, this);
194     this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset.bind(this), this);
195
196     WebInspector.advancedSearchController.registerSearchScope(new WebInspector.ScriptsSearchScope(this._workspace));
197 }
198
199 WebInspector.ScriptsPanel.prototype = {
200     get statusBarItems()
201     {
202         return [this.enableToggleButton.element, this._pauseOnExceptionButton.element, this._toggleFormatSourceButton.element, this._scriptViewStatusBarItemsContainer];
203     },
204
205     defaultFocusedElement: function()
206     {
207         return this._navigator.view.defaultFocusedElement();
208     },
209
210     get paused()
211     {
212         return this._paused;
213     },
214
215     wasShown: function()
216     {
217         WebInspector.Panel.prototype.wasShown.call(this);
218         this._debugSidebarContentsElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.xhrBreakpoints.element);
219         this.sidebarPanes.watchExpressions.show();
220
221         this._navigatorController.wasShown();
222     },
223
224     willHide: function()
225     {
226         WebInspector.Panel.prototype.willHide.call(this);
227         WebInspector.closeViewInDrawer();
228     },
229
230     /**
231      * @param {WebInspector.Event} event
232      */
233     _uiSourceCodeAdded: function(event)
234     {
235         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
236         this._addUISourceCode(uiSourceCode);
237     },
238
239     /**
240      * @param {WebInspector.UISourceCode} uiSourceCode
241      */
242     _addUISourceCode: function(uiSourceCode)
243     {
244         if (this._toggleFormatSourceButton.toggled)
245             uiSourceCode.setFormatted(true);
246
247         this._editorContainer.addUISourceCode(uiSourceCode);
248         this._navigator.addUISourceCode(uiSourceCode);
249         // Replace debugger script-based uiSourceCode with a network-based one.
250         if (this._currentUISourceCode && this._currentUISourceCode.isTemporary && this._currentUISourceCode !== uiSourceCode && this._currentUISourceCode.url === uiSourceCode.url) {
251             var currentUISourceCode = this._currentUISourceCode;
252             this._showFile(uiSourceCode);
253             this._editorContainer.removeUISourceCode(currentUISourceCode);
254         }
255     },
256
257     _uiSourceCodeRemoved: function(event)
258     {
259         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
260         this._editorContainer.removeUISourceCode(uiSourceCode);
261         this._navigator.removeUISourceCode(uiSourceCode);
262         this._removeSourceFrame(uiSourceCode);
263     },
264
265     _consoleCommandEvaluatedInSelectedCallFrame: function(event)
266     {
267         this.sidebarPanes.scopechain.update(WebInspector.debuggerModel.selectedCallFrame());
268     },
269
270     _debuggerPaused: function()
271     {
272         var details = WebInspector.debuggerModel.debuggerPausedDetails();
273
274         this._paused = true;
275         this._waitingToPause = false;
276         this._stepping = false;
277
278         this._updateDebuggerButtons();
279
280         WebInspector.inspectorView.setCurrentPanel(this);
281         this.sidebarPanes.callstack.update(details.callFrames);
282
283         if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) {
284             this.sidebarPanes.domBreakpoints.highlightBreakpoint(details.auxData);
285             function didCreateBreakpointHitStatusMessage(element)
286             {
287                 this.sidebarPanes.callstack.setStatus(element);
288             }
289             this.sidebarPanes.domBreakpoints.createBreakpointHitStatusMessage(details.auxData, didCreateBreakpointHitStatusMessage.bind(this));
290         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) {
291             var eventName = details.auxData.eventName;
292             this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName);
293             var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
294             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
295         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) {
296             this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]);
297             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
298         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception)
299             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description));
300         else if (details.reason === WebInspector.DebuggerModel.BreakReason.Assert)
301             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on assertion."));
302         else if (details.reason === WebInspector.DebuggerModel.BreakReason.CSPViolation)
303             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a script blocked due to Content Security Policy directive: \"%s\".", details.auxData["directiveText"]));
304         else {
305             function didGetUILocation(uiLocation)
306             {
307                 var breakpoint = WebInspector.breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber);
308                 if (!breakpoint)
309                     return;
310                 this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint);
311                 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
312             }
313             if (details.callFrames.length) 
314                 details.callFrames[0].createLiveLocation(didGetUILocation.bind(this));
315             else
316                 console.warn("ScriptsPanel paused, but callFrames.length is zero."); // TODO remove this once we understand this case better
317         }
318
319         this._showDebuggerSidebar();
320         this._toggleDebuggerSidebarButton.setEnabled(false);
321         window.focus();
322         InspectorFrontendHost.bringToFront();
323     },
324
325     _debuggerResumed: function()
326     {
327         this._paused = false;
328         this._waitingToPause = false;
329         this._stepping = false;
330
331         this._clearInterface();
332         this._toggleDebuggerSidebarButton.setEnabled(true);
333     },
334
335     _debuggerWasEnabled: function()
336     {
337         this._updateDebuggerButtons();
338     },
339
340     _debuggerWasDisabled: function()
341     {
342         this._reset();
343     },
344
345     _reset: function()
346     {
347         delete this.currentQuery;
348         this.searchCanceled();
349
350         this._debuggerResumed();
351
352         delete this._currentUISourceCode;
353         this._navigator.reset();
354         this._editorContainer.reset();
355         this._updateScriptViewStatusBarItems();
356         this.sidebarPanes.jsBreakpoints.reset();
357         this.sidebarPanes.watchExpressions.reset();
358
359         var uiSourceCodes = this._workspace.uiSourceCodes();
360         for (var i = 0; i < uiSourceCodes.length; ++i)
361             this._removeSourceFrame(uiSourceCodes[i]);
362     },
363
364     get visibleView()
365     {
366         return this._editorContainer.visibleView;
367     },
368
369     _updateScriptViewStatusBarItems: function()
370     {
371         this._scriptViewStatusBarItemsContainer.removeChildren();
372
373         var sourceFrame = this.visibleView;
374         if (sourceFrame) {
375             var statusBarItems = sourceFrame.statusBarItems() || [];
376             for (var i = 0; i < statusBarItems.length; ++i)
377                 this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
378         }
379     },
380
381     canShowAnchorLocation: function(anchor)
382     {
383         if (WebInspector.debuggerModel.debuggerEnabled() && anchor.uiSourceCode)
384             return true;
385         var uiSourceCodes = this._workspace.uiSourceCodes();
386         for (var i = 0; i < uiSourceCodes.length; ++i) {
387             if (uiSourceCodes[i].url === anchor.href) {
388                 anchor.uiSourceCode = uiSourceCodes[i];
389                 return true;
390             }
391         }
392         return false;
393     },
394
395     showAnchorLocation: function(anchor)
396     {
397         this._showSourceLine(anchor.uiSourceCode, anchor.lineNumber);
398     },
399
400     /**
401      * @param {WebInspector.UISourceCode} uiSourceCode
402      * @param {number} lineNumber
403      */
404     showUISourceCode: function(uiSourceCode, lineNumber)
405     {
406         this._showSourceLine(uiSourceCode, lineNumber);
407     },
408
409     /**
410      * @param {WebInspector.UISourceCode} uiSourceCode
411      * @param {number=} lineNumber
412      */
413     _showSourceLine: function(uiSourceCode, lineNumber)
414     {
415         var sourceFrame = this._showFile(uiSourceCode);
416         if (typeof lineNumber === "number")
417             sourceFrame.highlightLine(lineNumber);
418         sourceFrame.focus();
419
420         WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
421             action: WebInspector.UserMetrics.UserActionNames.OpenSourceLink,
422             url: uiSourceCode.url,
423             lineNumber: lineNumber
424         });
425     },
426
427     /**
428      * @param {WebInspector.UISourceCode} uiSourceCode
429      * @return {WebInspector.SourceFrame}
430      */
431     _showFile: function(uiSourceCode)
432     {
433         var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode);
434         if (this._currentUISourceCode === uiSourceCode)
435             return sourceFrame;
436         this._currentUISourceCode = uiSourceCode;
437
438         if (this._navigator.isScriptSourceAdded(uiSourceCode))
439             this._navigator.revealUISourceCode(uiSourceCode);
440         this._editorContainer.showFile(uiSourceCode);
441         this._updateScriptViewStatusBarItems();
442
443         return sourceFrame;
444     },
445
446     /**
447      * @param {WebInspector.UISourceCode} uiSourceCode
448      * @return {WebInspector.SourceFrame}
449      */
450     _createSourceFrame: function(uiSourceCode)
451     {
452         var sourceFrame;
453         switch (uiSourceCode.contentType()) {
454         case WebInspector.resourceTypes.Script:
455             if (uiSourceCode.isSnippet)
456                 sourceFrame = new WebInspector.SnippetJavaScriptSourceFrame(this, uiSourceCode);
457             else
458                 sourceFrame = new WebInspector.JavaScriptSourceFrame(this, uiSourceCode);
459             break;
460         case WebInspector.resourceTypes.Document:
461             sourceFrame = new WebInspector.JavaScriptSourceFrame(this, uiSourceCode);
462             break;
463         case WebInspector.resourceTypes.Stylesheet:
464         default:
465             sourceFrame = new WebInspector.UISourceCodeFrame(uiSourceCode);
466         break;
467         }
468         this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame);
469         return sourceFrame;
470     },
471
472     /**
473      * @param {WebInspector.UISourceCode} uiSourceCode
474      * @return {WebInspector.SourceFrame}
475      */
476     _getOrCreateSourceFrame: function(uiSourceCode)
477     {
478         return this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode);
479     },
480
481     /**
482      * @param {WebInspector.UISourceCode} uiSourceCode
483      * @return {WebInspector.SourceFrame}
484      */
485     viewForFile: function(uiSourceCode)
486     {
487         return this._getOrCreateSourceFrame(uiSourceCode);
488     },
489
490     /**
491      * @param {WebInspector.UISourceCode} uiSourceCode
492      */
493     _removeSourceFrame: function(uiSourceCode)
494     {
495         var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode);
496         if (!sourceFrame)
497             return;
498         this._sourceFramesByUISourceCode.remove(uiSourceCode);
499         sourceFrame.detach();
500     },
501
502     _clearCurrentExecutionLine: function()
503     {
504         if (this._executionSourceFrame)
505             this._executionSourceFrame.clearExecutionLine();
506         delete this._executionSourceFrame;
507     },
508
509     _executionLineChanged: function(event)
510     {
511         var uiLocation = event.data;
512
513         this._clearCurrentExecutionLine();
514         if (!uiLocation)
515             return;
516         var sourceFrame = this._getOrCreateSourceFrame(uiLocation.uiSourceCode);
517         sourceFrame.setExecutionLine(uiLocation.lineNumber);
518         this._executionSourceFrame = sourceFrame;
519     },
520
521     _revealExecutionLine: function(uiLocation)
522     {
523         var uiSourceCode = uiLocation.uiSourceCode;
524         // Some scripts (anonymous and snippets evaluations) are not added to files select by default.
525         if (uiSourceCode.isTemporary) {
526             if (this._currentUISourceCode && this._currentUISourceCode.scriptFile() && this._currentUISourceCode.scriptFile().isDivergingFromVM())
527                 return;
528             this._editorContainer.addUISourceCode(uiSourceCode);
529             if (uiSourceCode.formatted() !== this._toggleFormatSourceButton.toggled)
530                 uiSourceCode.setFormatted(this._toggleFormatSourceButton.toggled);
531         }
532         var sourceFrame = this._showFile(uiSourceCode);
533         sourceFrame.revealLine(uiLocation.lineNumber);
534         sourceFrame.focus();
535     },
536
537     _callFrameSelected: function(event)
538     {
539         var callFrame = event.data;
540
541         if (!callFrame)
542             return;
543
544         this.sidebarPanes.scopechain.update(callFrame);
545         this.sidebarPanes.watchExpressions.refreshExpressions();
546         this.sidebarPanes.callstack.setSelectedCallFrame(callFrame);
547         callFrame.createLiveLocation(this._revealExecutionLine.bind(this));
548     },
549
550     _editorClosed: function(event)
551     {
552         this._navigatorController.hideNavigatorOverlay();
553         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
554
555         if (this._currentUISourceCode === uiSourceCode)
556             delete this._currentUISourceCode;
557
558         // ScriptsNavigator does not need to update on EditorClosed.
559         this._updateScriptViewStatusBarItems();
560         WebInspector.searchController.resetSearch();
561     },
562
563     _editorSelected: function(event)
564     {
565         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
566         var sourceFrame = this._showFile(uiSourceCode);
567         this._navigatorController.hideNavigatorOverlay();
568         sourceFrame.focus();
569         WebInspector.searchController.resetSearch();
570     },
571
572     _scriptSelected: function(event)
573     {
574         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data.uiSourceCode);
575         var sourceFrame = this._showFile(uiSourceCode);
576         this._navigatorController.hideNavigatorOverlay();
577         if (sourceFrame && event.data.focusSource)
578             sourceFrame.focus();
579     },
580
581     _pauseOnExceptionStateChanged: function()
582     {
583         var pauseOnExceptionsState = WebInspector.settings.pauseOnExceptionStateString.get();
584         switch (pauseOnExceptionsState) {
585         case WebInspector.DebuggerModel.PauseOnExceptionsState.DontPauseOnExceptions:
586             this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions.");
587             break;
588         case WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnAllExceptions:
589             this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions.");
590             break;
591         case WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnUncaughtExceptions:
592             this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions.");
593             break;
594         }
595         this._pauseOnExceptionButton.state = pauseOnExceptionsState;
596     },
597
598     _updateDebuggerButtons: function()
599     {
600         if (WebInspector.debuggerModel.debuggerEnabled()) {
601             this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
602             this.enableToggleButton.toggled = true;
603             this._pauseOnExceptionButton.visible = true;
604             this.panelEnablerView.detach();
605         } else {
606             this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
607             this.enableToggleButton.toggled = false;
608             this._pauseOnExceptionButton.visible = false;
609             this.panelEnablerView.show(this.element);
610         }
611
612         if (this._paused) {
613             this._updateButtonTitle(this.pauseButton, WebInspector.UIString("Resume script execution (%s)."))
614             this.pauseButton.addStyleClass("paused");
615
616             this.pauseButton.disabled = false;
617             this.stepOverButton.disabled = false;
618             this.stepIntoButton.disabled = false;
619             this.stepOutButton.disabled = false;
620
621             this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
622         } else {
623             this._updateButtonTitle(this.pauseButton, WebInspector.UIString("Pause script execution (%s)."))
624             this.pauseButton.removeStyleClass("paused");
625
626             this.pauseButton.disabled = this._waitingToPause;
627             this.stepOverButton.disabled = true;
628             this.stepIntoButton.disabled = true;
629             this.stepOutButton.disabled = true;
630
631             if (this._waitingToPause)
632                 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
633             else if (this._stepping)
634                 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
635             else
636                 this.debuggerStatusElement.textContent = "";
637         }
638     },
639
640     _clearInterface: function()
641     {
642         this.sidebarPanes.callstack.update(null);
643         this.sidebarPanes.scopechain.update(null);
644         this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
645         this.sidebarPanes.domBreakpoints.clearBreakpointHighlight();
646         this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
647         this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
648
649         this._clearCurrentExecutionLine();
650         this._updateDebuggerButtons();
651     },
652
653     _enableDebugging: function()
654     {
655         this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
656     },
657
658     _toggleDebugging: function(optionalAlways)
659     {
660         this._paused = false;
661         this._waitingToPause = false;
662         this._stepping = false;
663
664         if (WebInspector.debuggerModel.debuggerEnabled()) {
665             WebInspector.settings.debuggerEnabled.set(false);
666             WebInspector.debuggerModel.disableDebugger();
667         } else {
668             WebInspector.settings.debuggerEnabled.set(!!optionalAlways);
669             WebInspector.debuggerModel.enableDebugger();
670         }
671     },
672
673     _togglePauseOnExceptions: function()
674     {
675         var nextStateMap = {};
676         var stateEnum = WebInspector.DebuggerModel.PauseOnExceptionsState;
677         nextStateMap[stateEnum.DontPauseOnExceptions] = stateEnum.PauseOnAllExceptions;
678         nextStateMap[stateEnum.PauseOnAllExceptions] = stateEnum.PauseOnUncaughtExceptions;
679         nextStateMap[stateEnum.PauseOnUncaughtExceptions] = stateEnum.DontPauseOnExceptions;
680         WebInspector.settings.pauseOnExceptionStateString.set(nextStateMap[this._pauseOnExceptionButton.state]);
681     },
682
683     _togglePause: function()
684     {
685         if (this._paused) {
686             this._paused = false;
687             this._waitingToPause = false;
688             DebuggerAgent.resume();
689         } else {
690             this._stepping = false;
691             this._waitingToPause = true;
692             DebuggerAgent.pause();
693         }
694
695         this._clearInterface();
696     },
697
698     _stepOverClicked: function()
699     {
700         if (!this._paused)
701             return;
702
703         this._paused = false;
704         this._stepping = true;
705
706         this._clearInterface();
707
708         DebuggerAgent.stepOver();
709     },
710
711     _stepIntoClicked: function()
712     {
713         if (!this._paused)
714             return;
715
716         this._paused = false;
717         this._stepping = true;
718
719         this._clearInterface();
720
721         DebuggerAgent.stepInto();
722     },
723
724     _stepOutClicked: function()
725     {
726         if (!this._paused)
727             return;
728
729         this._paused = false;
730         this._stepping = true;
731
732         this._clearInterface();
733
734         DebuggerAgent.stepOut();
735     },
736
737     _toggleBreakpointsClicked: function(event)
738     {
739         WebInspector.debuggerModel.setBreakpointsActive(!WebInspector.debuggerModel.breakpointsActive());
740     },
741
742     _breakpointsActiveStateChanged: function(event)
743     {
744         var active = event.data;
745         this._toggleBreakpointsButton.toggled = active;
746         if (active) {
747             this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate breakpoints.");
748             WebInspector.inspectorView.element.removeStyleClass("breakpoints-deactivated");
749             this.sidebarPanes.jsBreakpoints.listElement.removeStyleClass("breakpoints-list-deactivated");
750         } else {
751             this._toggleBreakpointsButton.title = WebInspector.UIString("Activate breakpoints.");
752             WebInspector.inspectorView.element.addStyleClass("breakpoints-deactivated");
753             this.sidebarPanes.jsBreakpoints.listElement.addStyleClass("breakpoints-list-deactivated");
754         }
755     },
756
757     _evaluateSelectionInConsole: function()
758     {
759         var selection = window.getSelection();
760         if (selection.type === "Range" && !selection.isCollapsed)
761             WebInspector.evaluateInConsole(selection.toString());
762     },
763
764     _createDebugToolbar: function()
765     {
766         var debugToolbar = document.createElement("div");
767         debugToolbar.className = "status-bar";
768         debugToolbar.id = "scripts-debug-toolbar";
769
770         var title, handler;
771         var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
772
773         // Continue.
774         handler = this._togglePause.bind(this);
775         this.pauseButton = this._createButtonAndRegisterShortcuts("scripts-pause", "", handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.PauseContinue);
776         debugToolbar.appendChild(this.pauseButton);
777
778         // Step over.
779         title = WebInspector.UIString("Step over next function call (%s).");
780         handler = this._stepOverClicked.bind(this);
781         this.stepOverButton = this._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepOver);
782         debugToolbar.appendChild(this.stepOverButton);
783
784         // Step into.
785         title = WebInspector.UIString("Step into next function call (%s).");
786         handler = this._stepIntoClicked.bind(this);
787         this.stepIntoButton = this._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepInto);
788         debugToolbar.appendChild(this.stepIntoButton);
789
790         // Step out.
791         title = WebInspector.UIString("Step out of current function (%s).");
792         handler = this._stepOutClicked.bind(this);
793         this.stepOutButton = this._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepOut);
794         debugToolbar.appendChild(this.stepOutButton);
795
796         this._toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate breakpoints."), "toggle-breakpoints");
797         this._toggleBreakpointsButton.toggled = true;
798         this._toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this);
799         debugToolbar.appendChild(this._toggleBreakpointsButton.element);
800
801         this.debuggerStatusElement = document.createElement("div");
802         this.debuggerStatusElement.id = "scripts-debugger-status";
803         debugToolbar.appendChild(this.debuggerStatusElement);
804
805         return debugToolbar;
806     },
807
808     _updateButtonTitle: function(button, buttonTitle)
809     {
810         button.buttonTitle = buttonTitle;
811         var hasShortcuts = button.shortcuts && button.shortcuts.length;
812         if (hasShortcuts)
813             button.title = String.vsprintf(buttonTitle, [button.shortcuts[0].name]);
814         else
815             button.title = buttonTitle;
816     },
817
818     /**
819      * @param {string} buttonId
820      * @param {string} buttonTitle
821      * @param {function(Event)} handler
822      * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts
823      */
824     _createButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts)
825     {
826         var button = document.createElement("button");
827         button.className = "status-bar-item";
828         button.id = buttonId;
829         button.shortcuts = shortcuts;
830         this._updateButtonTitle(button, buttonTitle);
831         button.disabled = true;
832         button.appendChild(document.createElement("img"));
833         button.addEventListener("click", handler, false);
834
835         this.registerShortcuts(shortcuts, handler);
836
837         return button;
838     },
839
840     searchCanceled: function()
841     {
842         if (this._searchView)
843             this._searchView.searchCanceled();
844
845         delete this._searchView;
846         delete this._searchQuery;
847     },
848
849     /**
850      * @param {string} query
851      */
852     performSearch: function(query)
853     {
854         WebInspector.searchController.updateSearchMatchesCount(0, this);
855
856         if (!this.visibleView)
857             return;
858
859         // Call searchCanceled since it will reset everything we need before doing a new search.
860         this.searchCanceled();
861
862         this._searchView = this.visibleView;
863         this._searchQuery = query;
864
865         function finishedCallback(view, searchMatches)
866         {
867             if (!searchMatches)
868                 return;
869
870             WebInspector.searchController.updateSearchMatchesCount(searchMatches, this);
871             view.jumpToNextSearchResult();
872             WebInspector.searchController.updateCurrentMatchIndex(view.currentSearchResultIndex, this);
873         }
874
875         this._searchView.performSearch(query, finishedCallback.bind(this));
876     },
877
878     jumpToNextSearchResult: function()
879     {
880         if (!this._searchView)
881             return;
882
883         if (this._searchView !== this.visibleView) {
884             this.performSearch(this._searchQuery);
885             return;
886         }
887
888         if (this._searchView.showingLastSearchResult())
889             this._searchView.jumpToFirstSearchResult();
890         else
891             this._searchView.jumpToNextSearchResult();
892         WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this);
893         return true;
894     },
895
896     jumpToPreviousSearchResult: function()
897     {
898         if (!this._searchView)
899             return false;
900
901         if (this._searchView !== this.visibleView) {
902             this.performSearch(this._searchQuery);
903             if (this._searchView)
904                 this._searchView.jumpToLastSearchResult();
905             return;
906         }
907
908         if (this._searchView.showingFirstSearchResult())
909             this._searchView.jumpToLastSearchResult();
910         else
911             this._searchView.jumpToPreviousSearchResult();
912         WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this);
913     },
914
915     /**
916      * @return {boolean}
917      */
918     canSearchAndReplace: function()
919     {
920         var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView);
921         return !!view && view.canEditSource();
922     },
923
924     /**
925      * @param {string} text
926      */
927     replaceSelectionWith: function(text)
928     {
929         var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView);
930         view.replaceSearchMatchWith(text);
931     },
932
933     /**
934      * @param {string} query
935      * @param {string} text
936      */
937     replaceAllWith: function(query, text)
938     {
939         var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView);
940         view.replaceAllWith(query, text);
941     },
942
943     _toggleFormatSource: function()
944     {
945         this._toggleFormatSourceButton.toggled = !this._toggleFormatSourceButton.toggled;
946         var uiSourceCodes = this._workspace.uiSourceCodes();
947         for (var i = 0; i < uiSourceCodes.length; ++i)
948             uiSourceCodes[i].setFormatted(this._toggleFormatSourceButton.toggled);
949
950         WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
951             action: WebInspector.UserMetrics.UserActionNames.TogglePrettyPrint,
952             enabled: this._toggleFormatSourceButton.toggled,
953             url: this._editorContainer.currentFile().url
954         });
955     },
956
957     addToWatch: function(expression)
958     {
959         this.sidebarPanes.watchExpressions.addExpression(expression);
960     },
961
962     _toggleBreakpoint: function()
963     {
964         var sourceFrame = this.visibleView;
965         if (!sourceFrame)
966             return;
967
968         if (sourceFrame instanceof WebInspector.JavaScriptSourceFrame) {
969             var javaScriptSourceFrame = /** @type {WebInspector.JavaScriptSourceFrame} */ (sourceFrame);
970             javaScriptSourceFrame.toggleBreakpointOnCurrentLine();
971         }            
972     },
973
974     _showOutlineDialog: function()
975     {
976         var uiSourceCode = this._editorContainer.currentFile();
977         if (!uiSourceCode)
978             return;
979
980         switch (uiSourceCode.contentType()) {
981         case WebInspector.resourceTypes.Document:
982         case WebInspector.resourceTypes.Script:
983             WebInspector.JavaScriptOutlineDialog.show(this.visibleView, uiSourceCode);
984             break;
985         case WebInspector.resourceTypes.Stylesheet:
986             WebInspector.StyleSheetOutlineDialog.show(this.visibleView, uiSourceCode);
987             break;
988         }
989     },
990
991     _installDebuggerSidebarController: function()
992     {
993         this._toggleDebuggerSidebarButton = new WebInspector.StatusBarButton(WebInspector.UIString("Hide debugger"), "scripts-debugger-show-hide-button", 3);
994         this._toggleDebuggerSidebarButton.state = "shown";
995         this._toggleDebuggerSidebarButton.addEventListener("click", clickHandler, this);
996
997         function clickHandler()
998         {
999             if (this._toggleDebuggerSidebarButton.state === "shown")
1000                 this._hideDebuggerSidebar();
1001             else
1002                 this._showDebuggerSidebar();
1003         }
1004         this.editorView.element.appendChild(this._toggleDebuggerSidebarButton.element);
1005
1006         if (WebInspector.settings.debuggerSidebarHidden.get())
1007             this._hideDebuggerSidebar();
1008
1009     },
1010
1011     _showDebuggerSidebar: function()
1012     {
1013         if (this._toggleDebuggerSidebarButton.state === "shown")
1014             return;
1015         this._toggleDebuggerSidebarButton.state = "shown";
1016         this._toggleDebuggerSidebarButton.title = WebInspector.UIString("Hide debugger");
1017         this.splitView.showSidebarElement();
1018         this.debugSidebarResizeWidgetElement.removeStyleClass("hidden");
1019         WebInspector.settings.debuggerSidebarHidden.set(false);
1020     },
1021
1022     _hideDebuggerSidebar: function()
1023     {
1024         if (this._toggleDebuggerSidebarButton.state === "hidden")
1025             return;
1026         this._toggleDebuggerSidebarButton.state = "hidden";
1027         this._toggleDebuggerSidebarButton.title = WebInspector.UIString("Show debugger");
1028         this.splitView.hideSidebarElement();
1029         this.debugSidebarResizeWidgetElement.addStyleClass("hidden");
1030         WebInspector.settings.debuggerSidebarHidden.set(true);
1031     },
1032
1033     _fileRenamed: function(event)
1034     {
1035         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data.uiSourceCode);
1036         var name = /** @type {string} */ (event.data.name);
1037         if (!uiSourceCode.isSnippet)
1038             return;
1039         WebInspector.scriptSnippetModel.renameScriptSnippet(uiSourceCode, name);
1040     },
1041         
1042     /**
1043      * @param {WebInspector.Event} event
1044      */
1045     _snippetCreationRequested: function(event)
1046     {
1047         var uiSourceCode = WebInspector.scriptSnippetModel.createScriptSnippet();
1048         this._showSourceLine(uiSourceCode);
1049         
1050         var shouldHideNavigator = !this._navigatorController.isNavigatorPinned();
1051         if (this._navigatorController.isNavigatorHidden())
1052             this._navigatorController.showNavigatorOverlay();
1053         this._navigator.rename(uiSourceCode, callback.bind(this));
1054     
1055         /**
1056          * @param {boolean} committed
1057          */
1058         function callback(committed)
1059         {
1060             if (shouldHideNavigator)
1061                 this._navigatorController.hideNavigatorOverlay();
1062
1063             if (!committed) {
1064                 WebInspector.scriptSnippetModel.deleteScriptSnippet(uiSourceCode);
1065                 return;
1066             }
1067
1068             this._showSourceLine(uiSourceCode);
1069         }
1070     },
1071
1072     /**
1073      * @param {WebInspector.Event} event
1074      */
1075     _itemRenamingRequested: function(event)
1076     {
1077         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
1078         
1079         var shouldHideNavigator = !this._navigatorController.isNavigatorPinned();
1080         if (this._navigatorController.isNavigatorHidden())
1081             this._navigatorController.showNavigatorOverlay();
1082         this._navigator.rename(uiSourceCode, callback.bind(this));
1083     
1084         /**
1085          * @param {boolean} committed
1086          */
1087         function callback(committed)
1088         {
1089             if (shouldHideNavigator && committed) {
1090                 this._navigatorController.hideNavigatorOverlay();
1091                 this._showSourceLine(uiSourceCode);
1092             }
1093         }
1094     },
1095
1096     /**
1097      * @param {WebInspector.UISourceCode} uiSourceCode
1098      */
1099     _showLocalHistory: function(uiSourceCode)
1100     {
1101         WebInspector.RevisionHistoryView.showHistory(uiSourceCode);
1102     },
1103
1104     /** 
1105      * @param {WebInspector.ContextMenu} contextMenu
1106      * @param {Object} target
1107      */
1108     appendApplicableItems: function(event, contextMenu, target)
1109     {
1110         this._appendUISourceCodeItems(contextMenu, target);
1111         this._appendFunctionItems(contextMenu, target);
1112     },
1113
1114     /** 
1115      * @param {WebInspector.ContextMenu} contextMenu
1116      * @param {Object} target
1117      */
1118     _appendUISourceCodeItems: function(contextMenu, target)
1119     {
1120         if (!(target instanceof WebInspector.UISourceCode))
1121             return;
1122
1123         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (target);
1124         contextMenu.appendItem(WebInspector.UIString("Local modifications..."), this._showLocalHistory.bind(this, uiSourceCode));
1125         var resource = WebInspector.resourceForURL(uiSourceCode.url);
1126         if (resource && resource.request)
1127             contextMenu.appendApplicableItems(resource.request);
1128     },
1129
1130     /** 
1131      * @param {WebInspector.ContextMenu} contextMenu
1132      * @param {Object} target
1133      */
1134     _appendFunctionItems: function(contextMenu, target)
1135     {
1136         if (!(target instanceof WebInspector.RemoteObject))
1137             return;
1138         var remoteObject = /** @type {WebInspector.RemoteObject} */ (target);
1139         if (remoteObject.type !== "function")
1140             return;
1141
1142         function didGetDetails(error, response)
1143         {
1144             if (error) {
1145                 console.error(error);
1146                 return;
1147             }
1148             WebInspector.inspectorView.showPanelForAnchorNavigation(this);
1149             var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(response.location);
1150             this._showSourceLine(uiLocation.uiSourceCode, uiLocation.lineNumber);
1151         }
1152
1153         function revealFunction()
1154         {
1155             DebuggerAgent.getFunctionDetails(remoteObject.objectId, didGetDetails.bind(this));
1156         }
1157
1158         contextMenu.appendItem(WebInspector.UIString("Show function definition"), revealFunction.bind(this));
1159     },
1160
1161     showGoToSourceDialog: function()
1162     {
1163         WebInspector.OpenResourceDialog.show(this, this._workspace, this.editorView.mainElement);
1164     },
1165
1166     __proto__: WebInspector.Panel.prototype
1167 }