home *** CD-ROM | disk | FTP | other *** search
/ Computer Active Guide 2009 July / CAG7.ISO / Internetas / SafariSetup.exe / AppleApplicationSupport.msi / WebKit.resources_inspector_ScriptsPanel.js < prev    next >
Encoding:
Text File  |  2010-06-03  |  37.5 KB  |  1,013 lines

  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.     this.backButton.addEventListener("click", this._goBack.bind(this), false);
  44.     this.topStatusBar.appendChild(this.backButton);
  45.  
  46.     this.forwardButton = document.createElement("button");
  47.     this.forwardButton.className = "status-bar-item";
  48.     this.forwardButton.id = "scripts-forward";
  49.     this.forwardButton.title = WebInspector.UIString("Show the next script resource.");
  50.     this.forwardButton.disabled = true;
  51.     this.forwardButton.appendChild(document.createElement("img"));
  52.     this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
  53.     this.topStatusBar.appendChild(this.forwardButton);
  54.  
  55.     this.filesSelectElement = document.createElement("select");
  56.     this.filesSelectElement.className = "status-bar-item";
  57.     this.filesSelectElement.id = "scripts-files";
  58.     this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
  59.     this.topStatusBar.appendChild(this.filesSelectElement);
  60.  
  61.     this.functionsSelectElement = document.createElement("select");
  62.     this.functionsSelectElement.className = "status-bar-item";
  63.     this.functionsSelectElement.id = "scripts-functions";
  64.  
  65.     // FIXME: append the functions select element to the top status bar when it is implemented.
  66.     // this.topStatusBar.appendChild(this.functionsSelectElement);
  67.  
  68.     this.sidebarButtonsElement = document.createElement("div");
  69.     this.sidebarButtonsElement.id = "scripts-sidebar-buttons";
  70.     this.topStatusBar.appendChild(this.sidebarButtonsElement);
  71.  
  72.     this.pauseButton = document.createElement("button");
  73.     this.pauseButton.className = "status-bar-item";
  74.     this.pauseButton.id = "scripts-pause";
  75.     this.pauseButton.title = WebInspector.UIString("Pause script execution.");
  76.     this.pauseButton.disabled = true;
  77.     this.pauseButton.appendChild(document.createElement("img"));
  78.     this.pauseButton.addEventListener("click", this._togglePause.bind(this), false);
  79.     this.sidebarButtonsElement.appendChild(this.pauseButton);
  80.  
  81.     this.stepOverButton = document.createElement("button");
  82.     this.stepOverButton.className = "status-bar-item";
  83.     this.stepOverButton.id = "scripts-step-over";
  84.     this.stepOverButton.title = WebInspector.UIString("Step over next function call.");
  85.     this.stepOverButton.disabled = true;
  86.     this.stepOverButton.addEventListener("click", this._stepOverClicked.bind(this), false);
  87.     this.stepOverButton.appendChild(document.createElement("img"));
  88.     this.sidebarButtonsElement.appendChild(this.stepOverButton);
  89.  
  90.     this.stepIntoButton = document.createElement("button");
  91.     this.stepIntoButton.className = "status-bar-item";
  92.     this.stepIntoButton.id = "scripts-step-into";
  93.     this.stepIntoButton.title = WebInspector.UIString("Step into next function call.");
  94.     this.stepIntoButton.disabled = true;
  95.     this.stepIntoButton.addEventListener("click", this._stepIntoClicked.bind(this), false);
  96.     this.stepIntoButton.appendChild(document.createElement("img"));
  97.     this.sidebarButtonsElement.appendChild(this.stepIntoButton);
  98.  
  99.     this.stepOutButton = document.createElement("button");
  100.     this.stepOutButton.className = "status-bar-item";
  101.     this.stepOutButton.id = "scripts-step-out";
  102.     this.stepOutButton.title = WebInspector.UIString("Step out of current function.");
  103.     this.stepOutButton.disabled = true;
  104.     this.stepOutButton.addEventListener("click", this._stepOutClicked.bind(this), false);
  105.     this.stepOutButton.appendChild(document.createElement("img"));
  106.     this.sidebarButtonsElement.appendChild(this.stepOutButton);
  107.  
  108.     this.toggleBreakpointsButton = new WebInspector.StatusBarButton("", "toggle-breakpoints");
  109.     this.toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked.bind(this), false);
  110.     this.sidebarButtonsElement.appendChild(this.toggleBreakpointsButton.element);
  111.     // Breakpoints should be activated by default, so emulate a click to toggle on.
  112.     this._toggleBreakpointsClicked();
  113.  
  114.     this.debuggerStatusElement = document.createElement("div");
  115.     this.debuggerStatusElement.id = "scripts-debugger-status";
  116.     this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);
  117.  
  118.     this.viewsContainerElement = document.createElement("div");
  119.     this.viewsContainerElement.id = "script-resource-views";
  120.  
  121.     this.sidebarElement = document.createElement("div");
  122.     this.sidebarElement.id = "scripts-sidebar";
  123.  
  124.     this.sidebarResizeElement = document.createElement("div");
  125.     this.sidebarResizeElement.className = "sidebar-resizer-vertical";
  126.     this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
  127.  
  128.     this.sidebarResizeWidgetElement = document.createElement("div");
  129.     this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
  130.     this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
  131.     this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
  132.  
  133.     this.sidebarPanes = {};
  134.     this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
  135.     this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
  136.     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
  137.     this.sidebarPanes.breakpoints = new WebInspector.BreakpointsSidebarPane();
  138.  
  139.     for (var pane in this.sidebarPanes)
  140.         this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
  141.  
  142.     this.sidebarPanes.callstack.expanded = true;
  143.     this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
  144.  
  145.     this.sidebarPanes.scopechain.expanded = true;
  146.     this.sidebarPanes.breakpoints.expanded = true;
  147.  
  148.     var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
  149.     var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
  150.     var panelEnablerButton = WebInspector.UIString("Enable Debugging");
  151.  
  152.     this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
  153.     this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
  154.  
  155.     this.element.appendChild(this.panelEnablerView.element);
  156.     this.element.appendChild(this.viewsContainerElement);
  157.     this.element.appendChild(this.sidebarElement);
  158.     this.element.appendChild(this.sidebarResizeElement);
  159.  
  160.     this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
  161.     this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
  162.  
  163.     this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
  164.     this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
  165.     this._pauseOnExceptionButton.state = WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions;
  166.  
  167.     this._shortcuts = {};
  168.     var handler, shortcut;
  169.     var platformSpecificModifier = WebInspector.isMac() ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl;
  170.  
  171.     // Continue.
  172.     handler = this.pauseButton.click.bind(this.pauseButton);
  173.     shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F8);
  174.     this._shortcuts[shortcut] = handler;
  175.     shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Slash, platformSpecificModifier);
  176.     this._shortcuts[shortcut] = handler;
  177.  
  178.     // Step over.
  179.     handler = this.stepOverButton.click.bind(this.stepOverButton);
  180.     shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F10);
  181.     this._shortcuts[shortcut] = handler;
  182.     shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.SingleQuote, platformSpecificModifier);
  183.     this._shortcuts[shortcut] = handler;
  184.  
  185.     // Step into.
  186.     handler = this.stepIntoButton.click.bind(this.stepIntoButton);
  187.     shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11);
  188.     this._shortcuts[shortcut] = handler;
  189.     shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, platformSpecificModifier);
  190.     this._shortcuts[shortcut] = handler;
  191.  
  192.     // Step out.
  193.     handler = this.stepOutButton.click.bind(this.stepOutButton);
  194.     shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11, WebInspector.KeyboardShortcut.Modifiers.Shift);
  195.     this._shortcuts[shortcut] = handler;
  196.     shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier);
  197.     this._shortcuts[shortcut] = handler;
  198.  
  199.     this._debuggerEnabled = Preferences.debuggerAlwaysEnabled;
  200.     if (Preferences.debuggerAlwaysEnabled)
  201.         this._attachDebuggerWhenShown = true;
  202.     this.reset();
  203. }
  204.  
  205. // Keep these in sync with WebCore::ScriptDebugServer
  206. WebInspector.ScriptsPanel.PauseOnExceptionsState = {
  207.     DontPauseOnExceptions : 0,
  208.     PauseOnAllExceptions : 1,
  209.     PauseOnUncaughtExceptions: 2
  210. };
  211.  
  212. WebInspector.ScriptsPanel.prototype = {
  213.     toolbarItemClass: "scripts",
  214.  
  215.     get toolbarItemLabel()
  216.     {
  217.         return WebInspector.UIString("Scripts");
  218.     },
  219.  
  220.     get statusBarItems()
  221.     {
  222.         return [this.enableToggleButton.element, this._pauseOnExceptionButton.element];
  223.     },
  224.  
  225.     get defaultFocusedElement()
  226.     {
  227.         return this.filesSelectElement;
  228.     },
  229.  
  230.     get paused()
  231.     {
  232.         return this._paused;
  233.     },
  234.  
  235.     show: function()
  236.     {
  237.         WebInspector.Panel.prototype.show.call(this);
  238.         this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
  239.  
  240.         if (this.visibleView) {
  241.             if (this.visibleView instanceof WebInspector.ResourceView)
  242.                 this.visibleView.headersVisible = false;
  243.             this.visibleView.show(this.viewsContainerElement);
  244.         }
  245.         if (this._attachDebuggerWhenShown) {
  246.             InspectorBackend.enableDebugger(false);
  247.             delete this._attachDebuggerWhenShown;
  248.         }
  249.     },
  250.     
  251.     hide: function()
  252.     {
  253.         WebInspector.Panel.prototype.hide.call(this);
  254.         if (this.visibleView)
  255.             this.visibleView.hide();
  256.     },
  257.  
  258.     get searchableViews()
  259.     {
  260.         return [ this.visibleView ];
  261.     },
  262.  
  263.     get breakpointsActivated()
  264.     {
  265.         return this.toggleBreakpointsButton.toggled;
  266.     },
  267.  
  268.     addScript: function(sourceID, sourceURL, source, startingLine, errorLine, errorMessage)
  269.     {
  270.         var script = new WebInspector.Script(sourceID, sourceURL, source, startingLine, errorLine, errorMessage);
  271.         this._sourceIDMap[sourceID] = script;
  272.  
  273.         var resource = WebInspector.resourceURLMap[sourceURL];
  274.         if (resource) {
  275.             if (resource.finished) {
  276.                 // Resource is finished, bind the script right away.
  277.                 resource.addScript(script);
  278.                 this._sourceIDMap[sourceID] = resource;
  279.             } else {
  280.                 // Resource is not finished, bind the script later.
  281.                 if (!resource._scriptsPendingResourceLoad) {
  282.                     resource._scriptsPendingResourceLoad = [];
  283.                     resource.addEventListener("finished", this._resourceLoadingFinished, this);
  284.                 }
  285.                 resource._scriptsPendingResourceLoad.push(script);
  286.             }
  287.         }
  288.         this._addScriptToFilesMenu(script);
  289.     },
  290.  
  291.     _resourceLoadingFinished: function(e)
  292.     {
  293.         var resource = e.target;
  294.         for (var i = 0; i < resource._scriptsPendingResourceLoad.length; ++i) {
  295.             // Bind script to resource.
  296.             var script = resource._scriptsPendingResourceLoad[i];
  297.             resource.addScript(script);
  298.             this._sourceIDMap[script.sourceID] = resource;
  299.  
  300.             // Remove script from the files list.
  301.             script.filesSelectOption.parentElement.removeChild(script.filesSelectOption);
  302.             
  303.             // Move breakpoints to the resource's frame.
  304.             if (script._scriptView) {
  305.                 var sourceFrame = script._scriptView.sourceFrame;
  306.                 var resourceFrame = this._sourceFrameForScriptOrResource(resource);
  307.                 for (var j = 0; j < sourceFrame.breakpoints; ++j)
  308.                     resourceFrame.addBreakpoint(sourceFrame.breakpoints[j]);
  309.             }
  310.         }
  311.         // Adding first script will add resource.
  312.         this._addScriptToFilesMenu(resource._scriptsPendingResourceLoad[0]);
  313.         delete resource._scriptsPendingResourceLoad;
  314.     },
  315.  
  316.     addBreakpoint: function(breakpoint)
  317.     {
  318.         if (!this.breakpointsActivated)
  319.             this._toggleBreakpointsClicked();
  320.  
  321.         this.sidebarPanes.breakpoints.addBreakpoint(breakpoint);
  322.  
  323.         var sourceFrame;
  324.         if (breakpoint.url) {
  325.             var resource = WebInspector.resourceURLMap[breakpoint.url];
  326.             if (resource && resource.finished)
  327.                 sourceFrame = this._sourceFrameForScriptOrResource(resource);
  328.         }
  329.  
  330.         if (breakpoint.sourceID && !sourceFrame) {
  331.             var object = this._sourceIDMap[breakpoint.sourceID]
  332.             sourceFrame = this._sourceFrameForScriptOrResource(object);
  333.         }
  334.  
  335.         if (sourceFrame)
  336.             sourceFrame.addBreakpoint(breakpoint);
  337.     },
  338.  
  339.     removeBreakpoint: function(breakpoint)
  340.     {
  341.         this.sidebarPanes.breakpoints.removeBreakpoint(breakpoint);
  342.  
  343.         var sourceFrame;
  344.         if (breakpoint.url) {
  345.             var resource = WebInspector.resourceURLMap[breakpoint.url];
  346.             if (resource && resource.finished)
  347.                 sourceFrame = this._sourceFrameForScriptOrResource(resource);
  348.         }
  349.  
  350.         if (breakpoint.sourceID && !sourceFrame) {
  351.             var object = this._sourceIDMap[breakpoint.sourceID]
  352.             sourceFrame = this._sourceFrameForScriptOrResource(object);
  353.         }
  354.  
  355.         if (sourceFrame)
  356.             sourceFrame.removeBreakpoint(breakpoint);
  357.     },
  358.  
  359.     canEditScripts: function()
  360.     {
  361.         return !!InspectorBackend.editScriptSource;
  362.     },
  363.  
  364.     editScriptSource: function(sourceID, newContent, line, linesCountToShift, callback)
  365.     {
  366.         if (!this.canEditScripts())
  367.             return;
  368.  
  369.         // Need to clear breakpoints and re-create them later when editing source.
  370.         var breakpointsPanel = this.sidebarPanes.breakpoints;
  371.         var newBreakpoints = [];
  372.         for (var id in breakpointsPanel.breakpoints) {
  373.             var breakpoint = breakpointsPanel.breakpoints[id];
  374.             breakpointsPanel.removeBreakpoint(breakpoint);
  375.             newBreakpoints.push(breakpoint);
  376.         }
  377.  
  378.         function mycallback(newBody)
  379.         {
  380.             callback(newBody);
  381.             for (var i = 0; i < newBreakpoints.length; ++i) {
  382.                 var breakpoint = newBreakpoints[i];
  383.                 if (breakpoint.line >= line)
  384.                     breakpoint.line += linesCountToShift;
  385.                 this.addBreakpoint(breakpoint);
  386.             }
  387.         };
  388.         var callbackId = WebInspector.Callback.wrap(mycallback.bind(this))
  389.         InspectorBackend.editScriptSource(callbackId, sourceID, newContent);
  390.     },
  391.  
  392.     selectedCallFrameId: function()
  393.     {
  394.         var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
  395.         if (!selectedCallFrame)
  396.             return null;
  397.         return selectedCallFrame.id;
  398.     },
  399.  
  400.     evaluateInSelectedCallFrame: function(code, updateInterface, objectGroup, callback)
  401.     {
  402.         var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
  403.         if (!this._paused || !selectedCallFrame)
  404.             return;
  405.  
  406.         if (typeof updateInterface === "undefined")
  407.             updateInterface = true;
  408.  
  409.         var self = this;
  410.         function updatingCallbackWrapper(result, exception)
  411.         {
  412.             callback(result, exception);
  413.             if (updateInterface)
  414.                 self.sidebarPanes.scopechain.update(selectedCallFrame);
  415.         }
  416.         this.doEvalInCallFrame(selectedCallFrame, code, objectGroup, updatingCallbackWrapper);
  417.     },
  418.  
  419.     doEvalInCallFrame: function(callFrame, code, objectGroup, callback)
  420.     {
  421.         function evalCallback(result)
  422.         {
  423.             if (result)
  424.                 callback(result.value, result.isException);
  425.         }
  426.         InjectedScriptAccess.get(callFrame.injectedScriptId).evaluateInCallFrame(callFrame.id, code, objectGroup, evalCallback);
  427.     },
  428.  
  429.     debuggerPaused: function(callFrames)
  430.     {
  431.         this._paused = true;
  432.         this._waitingToPause = false;
  433.         this._stepping = false;
  434.  
  435.         this._updateDebuggerButtons();
  436.  
  437.         this.sidebarPanes.callstack.update(callFrames, this._sourceIDMap);
  438.         this.sidebarPanes.callstack.selectedCallFrame = callFrames[0];
  439.  
  440.         WebInspector.currentPanel = this;
  441.         window.focus();
  442.     },
  443.  
  444.     debuggerResumed: function()
  445.     {
  446.         this._paused = false;
  447.         this._waitingToPause = false;
  448.         this._stepping = false;
  449.  
  450.         this._clearInterface();
  451.     },
  452.  
  453.     attachDebuggerWhenShown: function()
  454.     {
  455.         if (this.element.parentElement) {
  456.             InspectorBackend.enableDebugger(false);
  457.         } else {
  458.             this._attachDebuggerWhenShown = true;
  459.         }
  460.     },
  461.  
  462.     debuggerWasEnabled: function()
  463.     {
  464.         if (this._debuggerEnabled)
  465.             return;
  466.  
  467.         this._debuggerEnabled = true;
  468.         this.reset(true);
  469.     },
  470.  
  471.     debuggerWasDisabled: function()
  472.     {
  473.         if (!this._debuggerEnabled)
  474.             return;
  475.  
  476.         this._debuggerEnabled = false;
  477.         this.reset(true);
  478.     },
  479.  
  480.     reset: function(preserveItems)
  481.     {
  482.         this.visibleView = null;
  483.  
  484.         delete this.currentQuery;
  485.         this.searchCanceled();
  486.  
  487.         if (!this._debuggerEnabled) {
  488.             this._paused = false;
  489.             this._waitingToPause = false;
  490.             this._stepping = false;
  491.         }
  492.  
  493.         this._clearInterface();
  494.  
  495.         this._backForwardList = [];
  496.         this._currentBackForwardIndex = -1;
  497.         this._updateBackAndForwardButtons();
  498.  
  499.         this._resourceForURLInFilesSelect = {};
  500.         this.filesSelectElement.removeChildren();
  501.         this.functionsSelectElement.removeChildren();
  502.         this.viewsContainerElement.removeChildren();
  503.  
  504.         if (this._sourceIDMap) {
  505.             for (var sourceID in this._sourceIDMap) {
  506.                 var object = this._sourceIDMap[sourceID];
  507.                 if (object instanceof WebInspector.Resource)
  508.                     object.removeAllScripts();
  509.             }
  510.         }
  511.  
  512.         this._sourceIDMap = {};
  513.  
  514.         this.sidebarPanes.watchExpressions.refreshExpressions();
  515.         if (!preserveItems) {
  516.             this.sidebarPanes.breakpoints.reset();
  517.             if (this.sidebarPanes.workers)
  518.                 this.sidebarPanes.workers.reset();
  519.         }
  520.     },
  521.  
  522.     get visibleView()
  523.     {
  524.         return this._visibleView;
  525.     },
  526.  
  527.     set visibleView(x)
  528.     {
  529.         if (this._visibleView === x)
  530.             return;
  531.  
  532.         if (this._visibleView)
  533.             this._visibleView.hide();
  534.  
  535.         this._visibleView = x;
  536.  
  537.         if (x)
  538.             x.show(this.viewsContainerElement);
  539.     },
  540.  
  541.     viewRecreated: function(oldView, newView)
  542.     {
  543.         if (this._visibleView === oldView)
  544.             this._visibleView = newView;
  545.     },
  546.  
  547.     canShowSourceLine: function(url, line)
  548.     {
  549.         if (!this._debuggerEnabled)
  550.             return false;
  551.         return !!this._scriptOrResourceForURLAndLine(url, line);
  552.     },
  553.  
  554.     showSourceLine: function(url, line)
  555.     {
  556.         var scriptOrResource = this._scriptOrResourceForURLAndLine(url, line);
  557.         this._showScriptOrResource(scriptOrResource, {line: line, shouldHighlightLine: true});
  558.     },
  559.  
  560.     _scriptOrResourceForURLAndLine: function(url, line) 
  561.     {
  562.         var scriptWithMatchingUrl = null;
  563.         for (var sourceID in this._sourceIDMap) {
  564.             var scriptOrResource = this._sourceIDMap[sourceID];
  565.             if (scriptOrResource instanceof WebInspector.Script) {
  566.                 if (scriptOrResource.sourceURL !== url)
  567.                     continue;
  568.                 scriptWithMatchingUrl = scriptOrResource;
  569.                 if (scriptWithMatchingUrl.startingLine <= line && scriptWithMatchingUrl.startingLine + scriptWithMatchingUrl.linesCount > line)
  570.                     return scriptWithMatchingUrl;
  571.             } else {
  572.                 var resource = scriptOrResource;
  573.                 if (resource.url === url)
  574.                     return resource;
  575.             }
  576.         }
  577.         return scriptWithMatchingUrl;
  578.     },
  579.  
  580.     showView: function(view)
  581.     {
  582.         if (!view)
  583.             return;
  584.         this._showScriptOrResource(view.resource || view.script);
  585.     },
  586.  
  587.     handleShortcut: function(event)
  588.     {
  589.         var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
  590.         var handler = this._shortcuts[shortcut];
  591.         if (handler) {
  592.             handler(event);
  593.             event.handled = true;
  594.         } else
  595.             this.sidebarPanes.callstack.handleShortcut(event);
  596.     },
  597.  
  598.     scriptViewForScript: function(script)
  599.     {
  600.         if (!script)
  601.             return null;
  602.         if (!script._scriptView)
  603.             script._scriptView = new WebInspector.ScriptView(script);
  604.         return script._scriptView;
  605.     },
  606.  
  607.     sourceFrameForScript: function(script)
  608.     {
  609.         var view = this.scriptViewForScript(script);
  610.         if (!view)
  611.             return null;
  612.  
  613.         // Setting up the source frame requires that we be attached.
  614.         if (!this.element.parentNode)
  615.             this.attach();
  616.  
  617.         view.setupSourceFrameIfNeeded();
  618.         return view.sourceFrame;
  619.     },
  620.  
  621.     _sourceFrameForScriptOrResource: function(scriptOrResource)
  622.     {
  623.         if (scriptOrResource instanceof WebInspector.Resource)
  624.             return WebInspector.panels.resources.sourceFrameForResource(scriptOrResource);
  625.         if (scriptOrResource instanceof WebInspector.Script)
  626.             return this.sourceFrameForScript(scriptOrResource);
  627.     },
  628.  
  629.     _showScriptOrResource: function(scriptOrResource, options)
  630.     {
  631.         // options = {line:, shouldHighlightLine:, fromBackForwardAction:, initialLoad:}
  632.         if (!options) 
  633.             options = {};
  634.  
  635.         if (!scriptOrResource)
  636.             return;
  637.  
  638.         var view;
  639.         if (scriptOrResource instanceof WebInspector.Resource) {
  640.             if (!WebInspector.panels.resources)
  641.                 return null;
  642.             view = WebInspector.panels.resources.resourceViewForResource(scriptOrResource);
  643.             view.headersVisible = false;
  644.             var breakpoints = this.sidebarPanes.breakpoints.breakpoints;
  645.             for (var breakpointId in breakpoints) {
  646.                 var breakpoint = breakpoints[breakpointId];
  647.                 if (breakpoint.url === scriptOrResource.url) {
  648.                     var sourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
  649.                     sourceFrame.addBreakpoint(breakpoint);
  650.                 }
  651.             }
  652.         } else if (scriptOrResource instanceof WebInspector.Script)
  653.             view = this.scriptViewForScript(scriptOrResource);
  654.  
  655.         if (!view)
  656.             return;
  657.  
  658.         var url = scriptOrResource.url || scriptOrResource.sourceURL;
  659.         if (url && !options.initialLoad)
  660.             WebInspector.settings.lastViewedScriptFile = url;
  661.  
  662.         if (!options.fromBackForwardAction) {
  663.             var oldIndex = this._currentBackForwardIndex;
  664.             if (oldIndex >= 0)
  665.                 this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
  666.  
  667.             // Check for a previous entry of the same object in _backForwardList.
  668.             // If one is found, remove it and update _currentBackForwardIndex to match.
  669.             var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource);
  670.             if (previousEntryIndex !== -1) {
  671.                 this._backForwardList.splice(previousEntryIndex, 1);
  672.                 --this._currentBackForwardIndex;
  673.             }
  674.  
  675.             this._backForwardList.push(scriptOrResource);
  676.             ++this._currentBackForwardIndex;
  677.  
  678.             this._updateBackAndForwardButtons();
  679.         }
  680.  
  681.         this.visibleView = view;
  682.  
  683.         if (options.line) {
  684.             if (view.revealLine)
  685.                 view.revealLine(options.line);
  686.             if (view.highlightLine && options.shouldHighlightLine)
  687.                 view.highlightLine(options.line);
  688.         }
  689.  
  690.         var option;
  691.         if (scriptOrResource instanceof WebInspector.Script) {
  692.             option = scriptOrResource.filesSelectOption;
  693.  
  694.             // hasn't been added yet - happens for stepping in evals,
  695.             // so use the force option to force the script into the menu.
  696.             if (!option) {
  697.                 this._addScriptToFilesMenu(scriptOrResource, true);
  698.                 option = scriptOrResource.filesSelectOption;
  699.             }
  700.  
  701.             console.assert(option);
  702.         } else
  703.             option = scriptOrResource.filesSelectOption;
  704.  
  705.         if (option)
  706.             this.filesSelectElement.selectedIndex = option.index;
  707.     },
  708.  
  709.     _addScriptToFilesMenu: function(script, force)
  710.     {
  711.         if (!script.sourceURL && !force)
  712.             return;
  713.  
  714.         if (script.resource) {
  715.             if (this._resourceForURLInFilesSelect[script.resource.url])
  716.                 return;
  717.             this._resourceForURLInFilesSelect[script.resource.url] = script.resource;
  718.         }
  719.  
  720.         var displayName = script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)");
  721.  
  722.         var select = this.filesSelectElement;
  723.         var option = document.createElement("option");
  724.         option.representedObject = script.resource || script;
  725.         option.url = displayName;
  726.         option.startingLine = script.startingLine;
  727.         option.text = script.resource || script.startingLine === 1 ? displayName : String.sprintf("%s:%d", displayName, script.startingLine);
  728.  
  729.         function optionCompare(a, b)
  730.         {
  731.             if (a.url < b.url)
  732.                 return -1;
  733.             else if (a.url > b.url)
  734.                 return 1;
  735.  
  736.             if (typeof a.startingLine !== "number")
  737.                 return -1;
  738.             if (typeof b.startingLine !== "number")
  739.                 return -1;
  740.             return a.startingLine - b.startingLine;
  741.         }
  742.  
  743.         var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
  744.         if (insertionIndex < 0)
  745.             select.appendChild(option);
  746.         else
  747.             select.insertBefore(option, select.childNodes.item(insertionIndex));
  748.  
  749.         if (script.resource)
  750.             script.resource.filesSelectOption = option;
  751.         else
  752.             script.filesSelectOption = option;
  753.  
  754.         // Call _showScriptOrResource if the option we just appended ended up being selected.
  755.         // This will happen for the first item added to the menu.
  756.         if (select.options[select.selectedIndex] === option)
  757.             this._showScriptOrResource(option.representedObject, {initialLoad: true});
  758.         else {
  759.             // if not first item, check to see if this was the last viewed
  760.             var url = option.representedObject.url || option.representedObject.sourceURL;
  761.             var lastURL = WebInspector.settings.lastViewedScriptFile;
  762.             if (url && url === lastURL)
  763.                 this._showScriptOrResource(option.representedObject, {initialLoad: true});
  764.         }
  765.     },
  766.  
  767.     _clearCurrentExecutionLine: function()
  768.     {
  769.         if (this._executionSourceFrame)
  770.             this._executionSourceFrame.executionLine = 0;
  771.         delete this._executionSourceFrame;
  772.     },
  773.  
  774.     _callFrameSelected: function()
  775.     {
  776.         this._clearCurrentExecutionLine();
  777.  
  778.         var callStackPane = this.sidebarPanes.callstack;
  779.         var currentFrame = callStackPane.selectedCallFrame;
  780.         if (!currentFrame)
  781.             return;
  782.  
  783.         this.sidebarPanes.scopechain.update(currentFrame);
  784.         this.sidebarPanes.watchExpressions.refreshExpressions();
  785.  
  786.         var scriptOrResource = this._sourceIDMap[currentFrame.sourceID];
  787.         this._showScriptOrResource(scriptOrResource, {line: currentFrame.line});
  788.  
  789.         this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
  790.         if (this._executionSourceFrame)
  791.             this._executionSourceFrame.executionLine = currentFrame.line;
  792.     },
  793.  
  794.     _changeVisibleFile: function(event)
  795.     {
  796.         var select = this.filesSelectElement;
  797.         this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
  798.     },
  799.  
  800.     _startSidebarResizeDrag: function(event)
  801.     {
  802.         WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "col-resize");
  803.  
  804.         if (event.target === this.sidebarResizeWidgetElement)
  805.             this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft));
  806.         else
  807.             this._dragOffset = 0;
  808.     },
  809.  
  810.     _endSidebarResizeDrag: function(event)
  811.     {
  812.         WebInspector.elementDragEnd(event);
  813.  
  814.         delete this._dragOffset;
  815.     },
  816.  
  817.     _sidebarResizeDrag: function(event)
  818.     {
  819.         var x = event.pageX + this._dragOffset;
  820.         var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
  821.  
  822.         this.sidebarElement.style.width = newWidth + "px";
  823.         this.sidebarButtonsElement.style.width = newWidth + "px";
  824.         this.viewsContainerElement.style.right = newWidth + "px";
  825.         this.sidebarResizeWidgetElement.style.right = newWidth + "px";
  826.         this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
  827.  
  828.         this.resize();
  829.         event.preventDefault();
  830.     },
  831.     
  832.     updatePauseOnExceptionsState: function(pauseOnExceptionsState)
  833.     {
  834.         if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions)
  835.             this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions.");
  836.         else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnAllExceptions)
  837.             this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions.");
  838.         else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnUncaughtExceptions)
  839.             this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions.");
  840.  
  841.         this._pauseOnExceptionButton.state = pauseOnExceptionsState;
  842.     },
  843.  
  844.     _updateDebuggerButtons: function()
  845.     {
  846.         if (this._debuggerEnabled) {
  847.             this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
  848.             this.enableToggleButton.toggled = true;
  849.             this._pauseOnExceptionButton.visible = true;
  850.             this.panelEnablerView.visible = false;
  851.         } else {
  852.             this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
  853.             this.enableToggleButton.toggled = false;
  854.             this._pauseOnExceptionButton.visible = false;
  855.             this.panelEnablerView.visible = true;
  856.         }
  857.  
  858.         if (this._paused) {
  859.             this.pauseButton.addStyleClass("paused");
  860.  
  861.             this.pauseButton.disabled = false;
  862.             this.stepOverButton.disabled = false;
  863.             this.stepIntoButton.disabled = false;
  864.             this.stepOutButton.disabled = false;
  865.  
  866.             this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
  867.         } else {
  868.             this.pauseButton.removeStyleClass("paused");
  869.  
  870.             this.pauseButton.disabled = this._waitingToPause;
  871.             this.stepOverButton.disabled = true;
  872.             this.stepIntoButton.disabled = true;
  873.             this.stepOutButton.disabled = true;
  874.  
  875.             if (this._waitingToPause)
  876.                 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
  877.             else if (this._stepping)
  878.                 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
  879.             else
  880.                 this.debuggerStatusElement.textContent = "";
  881.         }
  882.     },
  883.  
  884.     _updateBackAndForwardButtons: function()
  885.     {
  886.         this.backButton.disabled = this._currentBackForwardIndex <= 0;
  887.         this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1);
  888.     },
  889.  
  890.     _clearInterface: function()
  891.     {
  892.         this.sidebarPanes.callstack.update(null);
  893.         this.sidebarPanes.scopechain.update(null);
  894.  
  895.         this._clearCurrentExecutionLine();
  896.         this._updateDebuggerButtons();
  897.     },
  898.  
  899.     _goBack: function()
  900.     {
  901.         if (this._currentBackForwardIndex <= 0) {
  902.             console.error("Can't go back from index " + this._currentBackForwardIndex);
  903.             return;
  904.         }
  905.  
  906.         this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], {fromBackForwardAction: true});
  907.         this._updateBackAndForwardButtons();
  908.     },
  909.  
  910.     _goForward: function()
  911.     {
  912.         if (this._currentBackForwardIndex >= this._backForwardList.length - 1) {
  913.             console.error("Can't go forward from index " + this._currentBackForwardIndex);
  914.             return;
  915.         }
  916.  
  917.         this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], {fromBackForwardAction: true});
  918.         this._updateBackAndForwardButtons();
  919.     },
  920.  
  921.     _enableDebugging: function()
  922.     {
  923.         if (this._debuggerEnabled)
  924.             return;
  925.         this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
  926.     },
  927.  
  928.     _toggleDebugging: function(optionalAlways)
  929.     {
  930.         this._paused = false;
  931.         this._waitingToPause = false;
  932.         this._stepping = false;
  933.  
  934.         if (this._debuggerEnabled)
  935.             InspectorBackend.disableDebugger(true);
  936.         else
  937.             InspectorBackend.enableDebugger(!!optionalAlways);
  938.     },
  939.  
  940.     _togglePauseOnExceptions: function()
  941.     {
  942.         InspectorBackend.setPauseOnExceptionsState((this._pauseOnExceptionButton.state + 1) % this._pauseOnExceptionButton.states);
  943.     },
  944.  
  945.     _togglePause: function()
  946.     {
  947.         if (this._paused) {
  948.             this._paused = false;
  949.             this._waitingToPause = false;
  950.             InspectorBackend.resumeDebugger();
  951.         } else {
  952.             this._stepping = false;
  953.             this._waitingToPause = true;
  954.             InspectorBackend.pauseInDebugger();
  955.         }
  956.  
  957.         this._clearInterface();
  958.     },
  959.  
  960.     _stepOverClicked: function()
  961.     {
  962.         this._paused = false;
  963.         this._stepping = true;
  964.  
  965.         this._clearInterface();
  966.  
  967.         InspectorBackend.stepOverStatementInDebugger();
  968.     },
  969.  
  970.     _stepIntoClicked: function()
  971.     {
  972.         this._paused = false;
  973.         this._stepping = true;
  974.  
  975.         this._clearInterface();
  976.  
  977.         InspectorBackend.stepIntoStatementInDebugger();
  978.     },
  979.  
  980.     _stepOutClicked: function()
  981.     {
  982.         this._paused = false;
  983.         this._stepping = true;
  984.  
  985.         this._clearInterface();
  986.  
  987.         InspectorBackend.stepOutOfFunctionInDebugger();
  988.     },
  989.  
  990.     _toggleBreakpointsClicked: function()
  991.     {
  992.         this.toggleBreakpointsButton.toggled = !this.toggleBreakpointsButton.toggled;
  993.         if (this.toggleBreakpointsButton.toggled) {
  994.             InspectorBackend.activateBreakpoints();
  995.             this.toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
  996.             document.getElementById("main-panels").removeStyleClass("breakpoints-deactivated");
  997.         } else {
  998.             InspectorBackend.deactivateBreakpoints();
  999.             this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
  1000.             document.getElementById("main-panels").addStyleClass("breakpoints-deactivated");
  1001.         }
  1002.     },
  1003.  
  1004.     elementsToRestoreScrollPositionsFor: function()
  1005.     {
  1006.         return [ this.sidebarElement ];
  1007.     }
  1008. }
  1009.  
  1010. WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
  1011.  
  1012. WebInspector.didEditScriptSource = WebInspector.Callback.processCallback;
  1013.