2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 WebInspector.ScriptsPanel = function()
28 WebInspector.Panel.call(this, "scripts");
30 this.topStatusBar = document.createElement("div");
31 this.topStatusBar.className = "status-bar";
32 this.topStatusBar.id = "scripts-status-bar";
33 this.element.appendChild(this.topStatusBar);
35 this.backButton = document.createElement("button");
36 this.backButton.className = "status-bar-item";
37 this.backButton.id = "scripts-back";
38 this.backButton.title = WebInspector.UIString("Show the previous script resource.");
39 this.backButton.disabled = true;
40 this.backButton.appendChild(document.createElement("img"));
41 this.backButton.addEventListener("click", this._goBack.bind(this), false);
42 this.topStatusBar.appendChild(this.backButton);
44 this.forwardButton = document.createElement("button");
45 this.forwardButton.className = "status-bar-item";
46 this.forwardButton.id = "scripts-forward";
47 this.forwardButton.title = WebInspector.UIString("Show the next script resource.");
48 this.forwardButton.disabled = true;
49 this.forwardButton.appendChild(document.createElement("img"));
50 this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
51 this.topStatusBar.appendChild(this.forwardButton);
53 this.filesSelectElement = document.createElement("select");
54 this.filesSelectElement.className = "status-bar-item";
55 this.filesSelectElement.id = "scripts-files";
56 this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
57 this.topStatusBar.appendChild(this.filesSelectElement);
59 this.functionsSelectElement = document.createElement("select");
60 this.functionsSelectElement.className = "status-bar-item";
61 this.functionsSelectElement.id = "scripts-functions";
63 // FIXME: append the functions select element to the top status bar when it is implemented.
64 // this.topStatusBar.appendChild(this.functionsSelectElement);
66 this.formatButton = document.createElement("button");
67 this.formatButton.className = "status-bar-item";
68 this.formatButton.id = "format-script";
69 this.formatButton.title = WebInspector.UIString("Format script.");
70 this.formatButton.appendChild(document.createElement("img"));
71 this.formatButton.addEventListener("click", this._formatScript.bind(this), false);
72 if (Preferences.debugMode)
73 this.topStatusBar.appendChild(this.formatButton);
75 this.sidebarButtonsElement = document.createElement("div");
76 this.sidebarButtonsElement.id = "scripts-sidebar-buttons";
77 this.topStatusBar.appendChild(this.sidebarButtonsElement);
79 this.pauseButton = document.createElement("button");
80 this.pauseButton.className = "status-bar-item";
81 this.pauseButton.id = "scripts-pause";
82 this.pauseButton.title = WebInspector.UIString("Pause script execution.");
83 this.pauseButton.disabled = true;
84 this.pauseButton.appendChild(document.createElement("img"));
85 this.pauseButton.addEventListener("click", this._togglePause.bind(this), false);
86 this.sidebarButtonsElement.appendChild(this.pauseButton);
88 this.stepOverButton = document.createElement("button");
89 this.stepOverButton.className = "status-bar-item";
90 this.stepOverButton.id = "scripts-step-over";
91 this.stepOverButton.title = WebInspector.UIString("Step over next function call.");
92 this.stepOverButton.disabled = true;
93 this.stepOverButton.addEventListener("click", this._stepOverClicked.bind(this), false);
94 this.stepOverButton.appendChild(document.createElement("img"));
95 this.sidebarButtonsElement.appendChild(this.stepOverButton);
97 this.stepIntoButton = document.createElement("button");
98 this.stepIntoButton.className = "status-bar-item";
99 this.stepIntoButton.id = "scripts-step-into";
100 this.stepIntoButton.title = WebInspector.UIString("Step into next function call.");
101 this.stepIntoButton.disabled = true;
102 this.stepIntoButton.addEventListener("click", this._stepIntoClicked.bind(this), false);
103 this.stepIntoButton.appendChild(document.createElement("img"));
104 this.sidebarButtonsElement.appendChild(this.stepIntoButton);
106 this.stepOutButton = document.createElement("button");
107 this.stepOutButton.className = "status-bar-item";
108 this.stepOutButton.id = "scripts-step-out";
109 this.stepOutButton.title = WebInspector.UIString("Step out of current function.");
110 this.stepOutButton.disabled = true;
111 this.stepOutButton.addEventListener("click", this._stepOutClicked.bind(this), false);
112 this.stepOutButton.appendChild(document.createElement("img"));
113 this.sidebarButtonsElement.appendChild(this.stepOutButton);
115 this.toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate all breakpoints."), "toggle-breakpoints");
116 this.toggleBreakpointsButton.toggled = true;
117 this.toggleBreakpointsButton.addEventListener("click", this.toggleBreakpointsClicked.bind(this), false);
118 this.sidebarButtonsElement.appendChild(this.toggleBreakpointsButton.element);
120 this.debuggerStatusElement = document.createElement("div");
121 this.debuggerStatusElement.id = "scripts-debugger-status";
122 this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);
124 this.viewsContainerElement = document.createElement("div");
125 this.viewsContainerElement.id = "script-resource-views";
127 this.sidebarElement = document.createElement("div");
128 this.sidebarElement.id = "scripts-sidebar";
130 this.sidebarResizeElement = document.createElement("div");
131 this.sidebarResizeElement.className = "sidebar-resizer-vertical";
132 this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
134 this.sidebarResizeWidgetElement = document.createElement("div");
135 this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
136 this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
137 this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
139 this.sidebarPanes = {};
140 this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
141 this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
142 this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
143 this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane();
144 if (Preferences.nativeInstrumentationEnabled) {
145 this.sidebarPanes.domBreakpoints = WebInspector.createDOMBreakpointsSidebarPane();
146 this.sidebarPanes.xhrBreakpoints = WebInspector.createXHRBreakpointsSidebarPane();
147 this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
150 this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane();
152 for (var pane in this.sidebarPanes)
153 this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
155 this.sidebarPanes.callstack.expanded = true;
156 this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
158 this.sidebarPanes.scopechain.expanded = true;
159 this.sidebarPanes.jsBreakpoints.expanded = true;
161 var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
162 var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
163 var panelEnablerButton = WebInspector.UIString("Enable Debugging");
165 this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
166 this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
168 this.element.appendChild(this.panelEnablerView.element);
169 this.element.appendChild(this.viewsContainerElement);
170 this.element.appendChild(this.sidebarElement);
171 this.element.appendChild(this.sidebarResizeElement);
173 this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
174 this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
175 if (Preferences.debuggerAlwaysEnabled)
176 this.enableToggleButton.element.addStyleClass("hidden");
178 this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
179 this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
181 this._registerShortcuts();
183 this._debuggerEnabled = Preferences.debuggerAlwaysEnabled;
187 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
188 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._failedToParseScriptSource, this);
189 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ScriptSourceChanged, this._scriptSourceChanged, this);
190 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
191 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
194 // Keep these in sync with WebCore::ScriptDebugServer
195 WebInspector.ScriptsPanel.PauseOnExceptionsState = {
196 DontPauseOnExceptions : 0,
197 PauseOnAllExceptions : 1,
198 PauseOnUncaughtExceptions: 2
201 WebInspector.ScriptsPanel.prototype = {
202 get toolbarItemLabel()
204 return WebInspector.UIString("Scripts");
209 return [this.enableToggleButton.element, this._pauseOnExceptionButton.element];
212 get defaultFocusedElement()
214 return this.filesSelectElement;
224 WebInspector.Panel.prototype.show.call(this);
225 this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
227 if (this.visibleView)
228 this.visibleView.show(this.viewsContainerElement);
233 if (this.visibleView)
234 this.visibleView.hide();
235 WebInspector.Panel.prototype.hide.call(this);
238 get breakpointsActivated()
240 return this.toggleBreakpointsButton.toggled;
243 _parsedScriptSource: function(event)
245 this._addScript(event.data);
248 _failedToParseScriptSource: function(event)
250 this._addScript(event.data);
253 _scriptSourceChanged: function(event)
255 var sourceID = event.data.sourceID;
256 var oldSource = event.data.oldSource;
258 var oldView, newView;
259 var script = WebInspector.debuggerModel.scriptForSourceID(sourceID);
260 if (script.resource) {
261 oldView = this._urlToSourceFrame[script.resource.url];
262 delete this._urlToSourceFrame[script.resource.url];
263 newView = this._sourceFrameForResource(script.resource);
264 var revertHandle = WebInspector.debuggerModel.editScriptSource.bind(WebInspector.debuggerModel, sourceID, oldSource);
265 script.resource.setContent(script.source, revertHandle);
267 var oldView = script._sourceFrame;
268 delete script._sourceFrame;
269 newView = this._sourceFrameForScript(script);
271 newView.scrollTop = oldView.scrollTop;
273 if (this.visibleView === oldView)
274 this.visibleView = newView;
276 var callFrames = WebInspector.debuggerModel.callFrames;
277 if (callFrames.length)
278 this._debuggerPaused({ data: { callFrames: callFrames } });
281 _addScript: function(script)
283 var resource = WebInspector.networkManager.inflightResourceForURL(script.sourceURL) || WebInspector.resourceForURL(script.sourceURL);
285 if (resource.finished) {
286 // Resource is finished, bind the script right away.
287 script.resource = resource;
289 // Resource is not finished, bind the script later.
290 if (!resource._scriptsPendingResourceLoad) {
291 resource._scriptsPendingResourceLoad = [];
292 resource.addEventListener("finished", this._resourceLoadingFinished, this);
294 resource._scriptsPendingResourceLoad.push(script);
297 this._addScriptToFilesMenu(script);
300 _resourceLoadingFinished: function(e)
302 var resource = e.target;
305 var select = this.filesSelectElement;
306 for (var i = 0; i < resource._scriptsPendingResourceLoad.length; ++i) {
307 // Bind script to resource.
308 var script = resource._scriptsPendingResourceLoad[i];
309 script.resource = resource;
311 if (select.options[select.selectedIndex] === script.filesSelectOption)
314 // Remove script from the files list.
315 script.filesSelectOption.parentElement.removeChild(script.filesSelectOption);
317 // Adding first script will add resource.
318 this._addScriptToFilesMenu(resource._scriptsPendingResourceLoad[0]);
319 delete resource._scriptsPendingResourceLoad;
322 this._showScriptOrResource(resource, { initialLoad: true });
325 addConsoleMessage: function(message)
327 this._messages.push(message);
328 var sourceFrame = this._urlToSourceFrame[message.url];
330 sourceFrame.addMessage(message);
333 clearConsoleMessages: function()
336 for (var url in this._urlToSourceFrame)
337 this._urlToSourceFrame[url].clearMessages();
340 selectedCallFrameId: function()
342 var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
343 if (!selectedCallFrame)
345 return selectedCallFrame.id;
348 evaluateInSelectedCallFrame: function(code, updateInterface, objectGroup, includeCommandLineAPI, callback)
350 var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
351 if (!this._paused || !selectedCallFrame)
354 if (typeof updateInterface === "undefined")
355 updateInterface = true;
357 function updatingCallbackWrapper(result)
360 callback(WebInspector.RemoteObject.fromPayload(result));
362 this.sidebarPanes.scopechain.update(selectedCallFrame);
365 InspectorBackend.evaluateOnCallFrame(selectedCallFrame.id, code, objectGroup, includeCommandLineAPI, updatingCallbackWrapper.bind(this));
368 _debuggerPaused: function(event)
370 var callFrames = event.data.callFrames;
373 this._waitingToPause = false;
374 this._stepping = false;
376 this._updateDebuggerButtons();
378 WebInspector.currentPanel = this;
380 this.sidebarPanes.callstack.update(callFrames, event.data.eventType, event.data.eventData);
381 this.sidebarPanes.callstack.selectedCallFrame = callFrames[0];
384 InspectorFrontendHost.bringToFront();
387 _debuggerResumed: function()
389 this._paused = false;
390 this._waitingToPause = false;
391 this._stepping = false;
393 this._clearInterface();
396 debuggerWasEnabled: function()
398 this._setPauseOnExceptions(WebInspector.settings.pauseOnExceptionState);
400 if (this._debuggerEnabled)
402 this._debuggerEnabled = true;
406 debuggerWasDisabled: function()
408 if (!this._debuggerEnabled)
411 this._debuggerEnabled = false;
415 reset: function(preserveItems)
417 this.visibleView = null;
419 delete this.currentQuery;
420 this.searchCanceled();
422 this._debuggerResumed();
424 this._backForwardList = [];
425 this._currentBackForwardIndex = -1;
426 this._updateBackAndForwardButtons();
428 this._urlToSourceFrame = {};
430 this._resourceForURLInFilesSelect = {};
431 this.filesSelectElement.removeChildren();
432 this.functionsSelectElement.removeChildren();
433 this.viewsContainerElement.removeChildren();
435 this.sidebarPanes.watchExpressions.refreshExpressions();
437 this.sidebarPanes.workers.reset();
442 return this._visibleView;
447 if (this._visibleView === x)
450 if (this._visibleView)
451 this._visibleView.hide();
453 this._visibleView = x;
456 x.show(this.viewsContainerElement);
459 canShowSourceLine: function(url, line)
461 if (!this._debuggerEnabled)
463 return !!this._scriptOrResourceForURLAndLine(url, line);
466 showSourceLine: function(url, line)
468 var scriptOrResource = this._scriptOrResourceForURLAndLine(url, line);
469 this._showScriptOrResource(scriptOrResource, {line: line, shouldHighlightLine: true});
472 _scriptOrResourceForURLAndLine: function(url, line)
474 var scripts = WebInspector.debuggerModel.scriptsForURL(url);
475 for (var i = 0; i < scripts.length; ++i) {
476 var script = scripts[i];
478 return script.resource;
479 if (script.startingLine <= line && script.startingLine + script.linesCount > line)
485 showView: function(view)
489 this._showScriptOrResource(view.resource || view.script);
492 handleShortcut: function(event)
494 var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
495 var handler = this._shortcuts[shortcut];
498 event.handled = true;
500 this.sidebarPanes.callstack.handleShortcut(event);
503 _sourceFrameForScriptOrResource: function(scriptOrResource)
505 if (scriptOrResource instanceof WebInspector.Resource)
506 return this._sourceFrameForResource(scriptOrResource);
507 return this._sourceFrameForScript(scriptOrResource);
510 _sourceFrameForResource: function(resource)
512 var sourceFrame = this._urlToSourceFrame[resource.url];
515 var contentProvider = new WebInspector.SourceFrameContentProviderForResource(resource);
516 var isScript = resource.type === WebInspector.Resource.Type.Script;
517 sourceFrame = new WebInspector.SourceFrame(contentProvider, resource.url, isScript);
518 for (var i = 0; i < this._messages.length; ++i) {
519 var message = this._messages[i];
520 if (this._messages[i].url === resource.url)
521 sourceFrame.addMessage(message);
523 this._urlToSourceFrame[resource.url] = sourceFrame;
527 _sourceFrameForScript: function(script)
529 if (script._sourceFrame)
530 return script._sourceFrame;
531 var contentProvider = new WebInspector.SourceFrameContentProviderForScript(script);
532 script._sourceFrame = new WebInspector.SourceFrame(contentProvider, script.sourceURL, true);
533 return script._sourceFrame;
536 _showScriptOrResource: function(scriptOrResource, options)
538 // options = {line:, shouldHighlightLine:, fromBackForwardAction:, initialLoad:}
539 options = options || {};
541 if (!scriptOrResource)
544 var view = this._sourceFrameForScriptOrResource(scriptOrResource);
548 var url = scriptOrResource.url || scriptOrResource.sourceURL;
549 if (url && !options.initialLoad)
550 WebInspector.settings.lastViewedScriptFile = url;
552 if (!options.fromBackForwardAction) {
553 var oldIndex = this._currentBackForwardIndex;
555 this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
557 // Check for a previous entry of the same object in _backForwardList.
558 // If one is found, remove it and update _currentBackForwardIndex to match.
559 var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource);
560 if (previousEntryIndex !== -1) {
561 this._backForwardList.splice(previousEntryIndex, 1);
562 --this._currentBackForwardIndex;
565 this._backForwardList.push(scriptOrResource);
566 ++this._currentBackForwardIndex;
568 this._updateBackAndForwardButtons();
571 this.visibleView = view;
575 view.revealLine(options.line);
576 if (view.highlightLine && options.shouldHighlightLine)
577 view.highlightLine(options.line);
581 if (scriptOrResource instanceof WebInspector.Script) {
582 option = scriptOrResource.filesSelectOption;
584 // hasn't been added yet - happens for stepping in evals,
585 // so use the force option to force the script into the menu.
587 this._addScriptToFilesMenu(scriptOrResource, true);
588 option = scriptOrResource.filesSelectOption;
591 console.assert(option);
593 option = scriptOrResource.filesSelectOption;
596 this.filesSelectElement.selectedIndex = option.index;
599 _addScriptToFilesMenu: function(script, force)
601 if (!script.sourceURL && !force)
604 if (script.resource) {
605 if (this._resourceForURLInFilesSelect[script.resource.url])
607 this._resourceForURLInFilesSelect[script.resource.url] = script.resource;
610 var displayName = script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)");
612 var select = this.filesSelectElement;
613 var option = document.createElement("option");
614 option.representedObject = script.resource || script;
615 option.url = displayName;
616 option.startingLine = script.startingLine;
617 option.text = script.resource || script.startingLine === 1 ? displayName : String.sprintf("%s:%d", displayName, script.startingLine);
619 function optionCompare(a, b)
623 else if (a.url > b.url)
626 if (typeof a.startingLine !== "number")
628 if (typeof b.startingLine !== "number")
630 return a.startingLine - b.startingLine;
633 var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
634 if (insertionIndex < 0)
635 select.appendChild(option);
637 select.insertBefore(option, select.childNodes.item(insertionIndex));
640 script.resource.filesSelectOption = option;
642 script.filesSelectOption = option;
644 if (select.options[select.selectedIndex] === option) {
645 // Call _showScriptOrResource if the option we just appended ended up being selected.
646 // This will happen for the first item added to the menu.
647 this._showScriptOrResource(option.representedObject, {initialLoad: true});
649 // If not first item, check to see if this was the last viewed
650 var url = option.representedObject.url || option.representedObject.sourceURL;
651 var lastURL = WebInspector.settings.lastViewedScriptFile;
652 if (url && url === lastURL) {
653 // For resources containing multiple <script> tags, we first report them separately and
654 // then glue them all together. They all share url and there is no need to show them all one
656 var isResource = !!option.representedObject.url;
657 if (isResource || !this.visibleView || !this.visibleView.script || this.visibleView.script.sourceURL !== url)
658 this._showScriptOrResource(option.representedObject, {initialLoad: true});
662 if (script.worldType === WebInspector.Script.WorldType.EXTENSIONS_WORLD)
663 script.filesSelectOption.addStyleClass("extension-script");
666 _clearCurrentExecutionLine: function()
668 if (this._executionSourceFrame)
669 this._executionSourceFrame.clearExecutionLine();
670 delete this._executionSourceFrame;
673 _callFrameSelected: function()
675 this._clearCurrentExecutionLine();
677 var callStackPane = this.sidebarPanes.callstack;
678 var currentFrame = callStackPane.selectedCallFrame;
682 this.sidebarPanes.scopechain.update(currentFrame);
683 this.sidebarPanes.watchExpressions.refreshExpressions();
685 var script = WebInspector.debuggerModel.scriptForSourceID(currentFrame.sourceID);
686 var scriptOrResource = script.resource || script;
687 this._showScriptOrResource(scriptOrResource, {line: currentFrame.line});
689 this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
690 if (this._executionSourceFrame)
691 this._executionSourceFrame.setExecutionLine(currentFrame.line);
694 _changeVisibleFile: function(event)
696 var select = this.filesSelectElement;
697 this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
700 _startSidebarResizeDrag: function(event)
702 WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "col-resize");
704 if (event.target === this.sidebarResizeWidgetElement)
705 this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft));
707 this._dragOffset = 0;
710 _endSidebarResizeDrag: function(event)
712 WebInspector.elementDragEnd(event);
713 delete this._dragOffset;
714 this.saveSidebarWidth();
717 _sidebarResizeDrag: function(event)
719 var x = event.pageX + this._dragOffset;
720 var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
721 this.setSidebarWidth(newWidth);
722 event.preventDefault();
725 setSidebarWidth: function(newWidth)
727 this.sidebarElement.style.width = newWidth + "px";
728 this.sidebarButtonsElement.style.width = newWidth + "px";
729 this.viewsContainerElement.style.right = newWidth + "px";
730 this.sidebarResizeWidgetElement.style.right = newWidth + "px";
731 this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
736 _setPauseOnExceptions: function(pauseOnExceptionsState)
738 function callback(pauseOnExceptionsState)
740 if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions)
741 this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions.");
742 else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnAllExceptions)
743 this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions.");
744 else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnUncaughtExceptions)
745 this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions.");
747 this._pauseOnExceptionButton.state = pauseOnExceptionsState;
748 WebInspector.settings.pauseOnExceptionState = pauseOnExceptionsState;
750 InspectorBackend.setPauseOnExceptionsState(pauseOnExceptionsState, callback.bind(this));
753 _updateDebuggerButtons: function()
755 if (this._debuggerEnabled) {
756 this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
757 this.enableToggleButton.toggled = true;
758 this._pauseOnExceptionButton.visible = true;
759 this.panelEnablerView.visible = false;
761 this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
762 this.enableToggleButton.toggled = false;
763 this._pauseOnExceptionButton.visible = false;
764 this.panelEnablerView.visible = true;
768 this.pauseButton.addStyleClass("paused");
770 this.pauseButton.disabled = false;
771 this.stepOverButton.disabled = false;
772 this.stepIntoButton.disabled = false;
773 this.stepOutButton.disabled = false;
775 this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
777 this.pauseButton.removeStyleClass("paused");
779 this.pauseButton.disabled = this._waitingToPause;
780 this.stepOverButton.disabled = true;
781 this.stepIntoButton.disabled = true;
782 this.stepOutButton.disabled = true;
784 if (this._waitingToPause)
785 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
786 else if (this._stepping)
787 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
789 this.debuggerStatusElement.textContent = "";
793 _updateBackAndForwardButtons: function()
795 this.backButton.disabled = this._currentBackForwardIndex <= 0;
796 this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1);
799 _clearInterface: function()
801 this.sidebarPanes.callstack.update(null);
802 this.sidebarPanes.scopechain.update(null);
804 this._clearCurrentExecutionLine();
805 this._updateDebuggerButtons();
810 if (this._currentBackForwardIndex <= 0) {
811 console.error("Can't go back from index " + this._currentBackForwardIndex);
815 this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], {fromBackForwardAction: true});
816 this._updateBackAndForwardButtons();
819 _goForward: function()
821 if (this._currentBackForwardIndex >= this._backForwardList.length - 1) {
822 console.error("Can't go forward from index " + this._currentBackForwardIndex);
826 this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], {fromBackForwardAction: true});
827 this._updateBackAndForwardButtons();
830 _formatScript: function()
832 if (this.visibleView)
833 this.visibleView.formatSource();
836 _enableDebugging: function()
838 if (this._debuggerEnabled)
840 this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
843 _toggleDebugging: function(optionalAlways)
845 this._paused = false;
846 this._waitingToPause = false;
847 this._stepping = false;
849 if (this._debuggerEnabled) {
850 WebInspector.settings.debuggerEnabled = false;
851 WebInspector.debuggerModel.disableDebugger();
853 WebInspector.settings.debuggerEnabled = !!optionalAlways;
854 WebInspector.debuggerModel.enableDebugger();
858 _togglePauseOnExceptions: function()
860 this._setPauseOnExceptions((this._pauseOnExceptionButton.state + 1) % this._pauseOnExceptionButton.states);
863 _togglePause: function()
866 this._paused = false;
867 this._waitingToPause = false;
868 InspectorBackend.resume();
870 this._stepping = false;
871 this._waitingToPause = true;
872 InspectorBackend.pause();
875 this._clearInterface();
878 _stepOverClicked: function()
880 this._paused = false;
881 this._stepping = true;
883 this._clearInterface();
885 InspectorBackend.stepOver();
888 _stepIntoClicked: function()
890 this._paused = false;
891 this._stepping = true;
893 this._clearInterface();
895 InspectorBackend.stepInto();
898 _stepOutClicked: function()
900 this._paused = false;
901 this._stepping = true;
903 this._clearInterface();
905 InspectorBackend.stepOut();
908 toggleBreakpointsClicked: function()
910 this.toggleBreakpointsButton.toggled = !this.toggleBreakpointsButton.toggled;
911 if (this.toggleBreakpointsButton.toggled) {
912 InspectorBackend.activateBreakpoints();
913 this.toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
914 document.getElementById("main-panels").removeStyleClass("breakpoints-deactivated");
916 InspectorBackend.deactivateBreakpoints();
917 this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
918 document.getElementById("main-panels").addStyleClass("breakpoints-deactivated");
922 elementsToRestoreScrollPositionsFor: function()
924 return [ this.sidebarElement ];
927 _registerShortcuts: function()
929 var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Scripts Panel"));
930 var handler, shortcut1, shortcut2;
931 var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
933 this._shortcuts = {};
936 handler = this.pauseButton.click.bind(this.pauseButton);
937 shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F8);
938 this._shortcuts[shortcut1.key] = handler;
939 shortcut2 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Slash, platformSpecificModifier);
940 this._shortcuts[shortcut2.key] = handler;
941 section.addAlternateKeys([ shortcut1.name, shortcut2.name ], WebInspector.UIString("Continue"));
944 handler = this.stepOverButton.click.bind(this.stepOverButton);
945 shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F10);
946 this._shortcuts[shortcut1.key] = handler;
947 shortcut2 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.SingleQuote, platformSpecificModifier);
948 this._shortcuts[shortcut2.key] = handler;
949 section.addAlternateKeys([ shortcut1.name, shortcut2.name ], WebInspector.UIString("Step over"));
952 handler = this.stepIntoButton.click.bind(this.stepIntoButton);
953 shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11);
954 this._shortcuts[shortcut1.key] = handler;
955 shortcut2 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, platformSpecificModifier);
956 this._shortcuts[shortcut2.key] = handler;
957 section.addAlternateKeys([ shortcut1.name, shortcut2.name ], WebInspector.UIString("Step into"));
960 handler = this.stepOutButton.click.bind(this.stepOutButton);
961 shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11, WebInspector.KeyboardShortcut.Modifiers.Shift);
962 this._shortcuts[shortcut1.key] = handler;
963 shortcut2 = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier);
964 this._shortcuts[shortcut2.key] = handler;
965 section.addAlternateKeys([ shortcut1.name, shortcut2.name ], WebInspector.UIString("Step out"));
967 var isMac = WebInspector.isMac();
969 shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Meta);
971 shortcut1 = WebInspector.KeyboardShortcut.makeDescriptor("g", WebInspector.KeyboardShortcut.Modifiers.Ctrl);
972 this._shortcuts[shortcut1.key] = this.showGoToLineDialog.bind(this);
973 section.addAlternateKeys([ shortcut1.name ], WebInspector.UIString("Go to Line"));
974 this.sidebarPanes.callstack.registerShortcuts(section);
977 searchCanceled: function()
979 WebInspector.updateSearchMatchesCount(0, this);
981 if (this._searchView)
982 this._searchView.searchCanceled();
984 delete this._searchView;
985 delete this._searchQuery;
988 performSearch: function(query)
990 if (!this.visibleView)
993 // Call searchCanceled since it will reset everything we need before doing a new search.
994 this.searchCanceled();
996 this._searchView = this.visibleView;
997 this._searchQuery = query;
999 function finishedCallback(view, searchMatches)
1004 WebInspector.updateSearchMatchesCount(searchMatches, this);
1005 view.jumpToFirstSearchResult();
1008 this._searchView.performSearch(query, finishedCallback.bind(this));
1011 jumpToNextSearchResult: function()
1013 if (!this._searchView)
1016 if (this._searchView !== this.visibleView) {
1017 this.performSearch(this._searchQuery);
1021 if (this._searchView.showingLastSearchResult())
1022 this._searchView.jumpToFirstSearchResult();
1024 this._searchView.jumpToNextSearchResult();
1027 jumpToPreviousSearchResult: function()
1029 if (!this._searchView)
1032 if (this._searchView !== this.visibleView) {
1033 this.performSearch(this._searchQuery);
1034 if (this._searchView)
1035 this._searchView.jumpToLastSearchResult();
1039 if (this._searchView.showingFirstSearchResult())
1040 this._searchView.jumpToLastSearchResult();
1042 this._searchView.jumpToPreviousSearchResult();
1045 showGoToLineDialog: function(e)
1047 var view = this.visibleView;
1049 WebInspector.GoToLineDialog.show(view);
1053 WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
1056 WebInspector.SourceFrameContentProviderForScript = function(script)
1058 WebInspector.SourceFrameContentProvider.call(this);
1059 this._script = script;
1062 WebInspector.SourceFrameContentProviderForScript.prototype = {
1063 requestContent: function(callback)
1065 if (this._script.source) {
1066 callback("text/javascript", this._script.source);
1070 function didRequestSource(content)
1075 for (var i = 0; i < this._script.startingLine - 1; ++i)
1077 source = prefix + content;
1079 source = WebInspector.UIString("<source is not available>");
1080 callback("text/javascript", source);
1082 this._script.requestSource(didRequestSource.bind(this));
1087 return [this._script];
1091 WebInspector.SourceFrameContentProviderForScript.prototype.__proto__ = WebInspector.SourceFrameContentProvider.prototype;