home *** CD-ROM | disk | FTP | other *** search
/ Computer Active 2010 July / CA07.iso / Multimedija / QuickTimeInstaller.exe / AppleApplicationSupport.msi / WebKit.resources_inspector_ScriptsPanel.js < prev    next >
Encoding:
Text File  |  2010-03-15  |  33.2 KB  |  921 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.debuggerStatusElement = document.createElement("div");
  109.     this.debuggerStatusElement.id = "scripts-debugger-status";
  110.     this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);
  111.  
  112.     this.viewsContainerElement = document.createElement("div");
  113.     this.viewsContainerElement.id = "script-resource-views";
  114.  
  115.     this.sidebarElement = document.createElement("div");
  116.     this.sidebarElement.id = "scripts-sidebar";
  117.  
  118.     this.sidebarResizeElement = document.createElement("div");
  119.     this.sidebarResizeElement.className = "sidebar-resizer-vertical";
  120.     this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
  121.  
  122.     this.sidebarResizeWidgetElement = document.createElement("div");
  123.     this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
  124.     this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
  125.     this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
  126.  
  127.     this.sidebarPanes = {};
  128.     this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
  129.     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
  130.     this.sidebarPanes.breakpoints = new WebInspector.BreakpointsSidebarPane();
  131.  
  132.     for (var pane in this.sidebarPanes)
  133.         this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
  134.  
  135.     // FIXME: remove the following line of code when the Breakpoints pane has content.
  136.     this.sidebarElement.removeChild(this.sidebarPanes.breakpoints.element);
  137.  
  138.     this.sidebarPanes.callstack.expanded = true;
  139.     this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
  140.  
  141.     this.sidebarPanes.scopechain.expanded = true;
  142.  
  143.     var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
  144.     var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
  145.     var panelEnablerButton = WebInspector.UIString("Enable Debugging");
  146.  
  147.     this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
  148.     this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
  149.  
  150.     this.element.appendChild(this.panelEnablerView.element);
  151.     this.element.appendChild(this.viewsContainerElement);
  152.     this.element.appendChild(this.sidebarElement);
  153.     this.element.appendChild(this.sidebarResizeElement);
  154.  
  155.     this.enableToggleButton = document.createElement("button");
  156.     this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
  157.     this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
  158.  
  159.     this.pauseOnExceptionButton = document.createElement("button");
  160.     this.pauseOnExceptionButton.id = "scripts-pause-on-exceptions-status-bar-item";
  161.     this.pauseOnExceptionButton.className = "status-bar-item";
  162.     this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
  163.  
  164.     this._breakpointsURLMap = {};
  165.  
  166.     this._shortcuts = {};
  167.  
  168.     var isMac = InspectorController.platform().indexOf("mac-") === 0;
  169.     var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl;
  170.  
  171.     // Continue.
  172.     var handler = this.pauseButton.click.bind(this.pauseButton);
  173.     var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F8);
  174.     this._shortcuts[shortcut] = handler;
  175.     var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Slash, platformSpecificModifier);
  176.     this._shortcuts[shortcut] = handler;
  177.  
  178.     // Step over.
  179.     var handler = this.stepOverButton.click.bind(this.stepOverButton);
  180.     var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F10);
  181.     this._shortcuts[shortcut] = handler;
  182.     var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.SingleQuote, platformSpecificModifier);
  183.     this._shortcuts[shortcut] = handler;
  184.  
  185.     // Step into.
  186.     var handler = this.stepIntoButton.click.bind(this.stepIntoButton);
  187.     var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11);
  188.     this._shortcuts[shortcut] = handler;
  189.     var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, platformSpecificModifier);
  190.     this._shortcuts[shortcut] = handler;
  191.  
  192.     // Step out.
  193.     var handler = this.stepOutButton.click.bind(this.stepOutButton);
  194.     var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11, WebInspector.KeyboardShortcut.Modifiers.Shift);
  195.     this._shortcuts[shortcut] = handler;
  196.     var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier);
  197.     this._shortcuts[shortcut] = handler;
  198.  
  199.     this.reset();
  200. }
  201.  
  202. WebInspector.ScriptsPanel.prototype = {
  203.     toolbarItemClass: "scripts",
  204.  
  205.     get toolbarItemLabel()
  206.     {
  207.         return WebInspector.UIString("Scripts");
  208.     },
  209.  
  210.     get statusBarItems()
  211.     {
  212.         return [this.enableToggleButton, this.pauseOnExceptionButton];
  213.     },
  214.  
  215.     get paused()
  216.     {
  217.         return this._paused;
  218.     },
  219.  
  220.     show: function()
  221.     {
  222.         WebInspector.Panel.prototype.show.call(this);
  223.         this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
  224.  
  225.         if (this.visibleView) {
  226.             if (this.visibleView instanceof WebInspector.ResourceView)
  227.                 this.visibleView.headersVisible = false;
  228.             this.visibleView.show(this.viewsContainerElement);
  229.         }
  230.  
  231.         // Hide any views that are visible that are not this panel's current visible view.
  232.         // This can happen when a ResourceView is visible in the Resources panel then switched
  233.         // to the this panel.
  234.         for (var sourceID in this._sourceIDMap) {
  235.             var scriptOrResource = this._sourceIDMap[sourceID];
  236.             var view = this._sourceViewForScriptOrResource(scriptOrResource);
  237.             if (!view || view === this.visibleView)
  238.                 continue;
  239.             view.visible = false;
  240.         }
  241.         if (this._attachDebuggerWhenShown) {
  242.             InspectorController.enableDebuggerFromFrontend(false);
  243.             delete this._attachDebuggerWhenShown;
  244.         }
  245.     },
  246.  
  247.     get searchableViews()
  248.     {
  249.         var views = [];
  250.  
  251.         const visibleView = this.visibleView;
  252.         if (visibleView && visibleView.performSearch) {
  253.             visibleView.alreadySearching = true;
  254.             views.push(visibleView);
  255.         }
  256.  
  257.         for (var sourceID in this._sourceIDMap) {
  258.             var scriptOrResource = this._sourceIDMap[sourceID];
  259.             var view = this._sourceViewForScriptOrResource(scriptOrResource);
  260.             if (!view || !view.performSearch || view.alreadySearching)
  261.                 continue;
  262.  
  263.             view.alreadySearching = true;
  264.             views.push(view);
  265.         }
  266.  
  267.         for (var i = 0; i < views.length; ++i)
  268.             delete views[i].alreadySearching;
  269.  
  270.         return views;
  271.     },
  272.  
  273.     addScript: function(sourceID, sourceURL, source, startingLine, errorLine, errorMessage)
  274.     {
  275.         var script = new WebInspector.Script(sourceID, sourceURL, source, startingLine, errorLine, errorMessage);
  276.  
  277.         if (sourceURL in WebInspector.resourceURLMap) {
  278.             var resource = WebInspector.resourceURLMap[sourceURL];
  279.             resource.addScript(script);
  280.         }
  281.  
  282.         if (sourceURL in this._breakpointsURLMap && sourceID) {
  283.             var breakpoints = this._breakpointsURLMap[sourceURL];
  284.             var breakpointsLength = breakpoints.length;
  285.             for (var i = 0; i < breakpointsLength; ++i) {
  286.                 var breakpoint = breakpoints[i];
  287.                 if (startingLine <= breakpoint.line) {
  288.                     breakpoint.sourceID = sourceID;
  289.                     if (breakpoint.enabled)
  290.                         InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
  291.                 }
  292.             }
  293.         }
  294.  
  295.         if (sourceID)
  296.             this._sourceIDMap[sourceID] = (resource || script);
  297.  
  298.         this._addScriptToFilesMenu(script);
  299.     },
  300.  
  301.     addBreakpoint: function(breakpoint)
  302.     {
  303.         this.sidebarPanes.breakpoints.addBreakpoint(breakpoint);
  304.  
  305.         var sourceFrame;
  306.         if (breakpoint.url) {
  307.             if (!(breakpoint.url in this._breakpointsURLMap))
  308.                 this._breakpointsURLMap[breakpoint.url] = [];
  309.             this._breakpointsURLMap[breakpoint.url].unshift(breakpoint);
  310.  
  311.             if (breakpoint.url in WebInspector.resourceURLMap) {
  312.                 var resource = WebInspector.resourceURLMap[breakpoint.url];
  313.                 sourceFrame = this._sourceFrameForScriptOrResource(resource);
  314.             }
  315.         }
  316.  
  317.         if (breakpoint.sourceID && !sourceFrame) {
  318.             var object = this._sourceIDMap[breakpoint.sourceID]
  319.             sourceFrame = this._sourceFrameForScriptOrResource(object);
  320.         }
  321.  
  322.         if (sourceFrame)
  323.             sourceFrame.addBreakpoint(breakpoint);
  324.     },
  325.  
  326.     removeBreakpoint: function(breakpoint)
  327.     {
  328.         this.sidebarPanes.breakpoints.removeBreakpoint(breakpoint);
  329.  
  330.         var sourceFrame;
  331.         if (breakpoint.url && breakpoint.url in this._breakpointsURLMap) {
  332.             var breakpoints = this._breakpointsURLMap[breakpoint.url];
  333.             breakpoints.remove(breakpoint);
  334.             if (!breakpoints.length)
  335.                 delete this._breakpointsURLMap[breakpoint.url];
  336.  
  337.             if (breakpoint.url in WebInspector.resourceURLMap) {
  338.                 var resource = WebInspector.resourceURLMap[breakpoint.url];
  339.                 sourceFrame = this._sourceFrameForScriptOrResource(resource);
  340.             }
  341.         }
  342.  
  343.         if (breakpoint.sourceID && !sourceFrame) {
  344.             var object = this._sourceIDMap[breakpoint.sourceID]
  345.             sourceFrame = this._sourceFrameForScriptOrResource(object);
  346.         }
  347.  
  348.         if (sourceFrame)
  349.             sourceFrame.removeBreakpoint(breakpoint);
  350.     },
  351.  
  352.     evaluateInSelectedCallFrame: function(code, updateInterface, callback)
  353.     {
  354.         var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
  355.         if (!this._paused || !selectedCallFrame)
  356.             return;
  357.  
  358.         if (typeof updateInterface === "undefined")
  359.             updateInterface = true;
  360.  
  361.         var self = this;
  362.         function updatingCallbackWrapper(result)
  363.         {
  364.             callback(result);
  365.             if (updateInterface)
  366.                 self.sidebarPanes.scopechain.update(selectedCallFrame);
  367.         }        
  368.         this.doEvalInCallFrame(selectedCallFrame, code, updatingCallbackWrapper);
  369.     },
  370.  
  371.     doEvalInCallFrame: function(callFrame, code, callback)
  372.     {
  373.         var panel = this;
  374.         function delayedEvaluation()
  375.         {
  376.             if (!code) {
  377.                 // Evaluate into properties in scope of the selected call frame.
  378.                 callback(panel._variablesInScope(callFrame));
  379.                 return;
  380.             }
  381.             try {
  382.                 callback(callFrame.evaluate(code));
  383.             } catch (e) {
  384.                 callback(e, true);
  385.             }
  386.         }
  387.         setTimeout(delayedEvaluation, 0);
  388.     },
  389.  
  390.     _variablesInScope: function(callFrame)
  391.     {
  392.         var result = {};
  393.         var scopeChain = callFrame.scopeChain;
  394.         for (var i = 0; i < scopeChain.length; ++i) {
  395.             var scopeObject = scopeChain[i];
  396.             for (var property in scopeObject)
  397.                 result[property] = true;
  398.         }
  399.         return result;
  400.     },
  401.  
  402.     debuggerPaused: function()
  403.     {
  404.         this._paused = true;
  405.         this._waitingToPause = false;
  406.         this._stepping = false;
  407.  
  408.         this._updateDebuggerButtons();
  409.  
  410.         var callStackPane = this.sidebarPanes.callstack;
  411.         var currentFrame = InspectorController.currentCallFrame();
  412.         callStackPane.update(currentFrame, this._sourceIDMap);
  413.         callStackPane.selectedCallFrame = currentFrame;
  414.  
  415.         WebInspector.currentPanel = this;
  416.         window.focus();
  417.     },
  418.  
  419.     debuggerResumed: function()
  420.     {
  421.         this._paused = false;
  422.         this._waitingToPause = false;
  423.         this._stepping = false;
  424.  
  425.         this._clearInterface();
  426.     },
  427.  
  428.     attachDebuggerWhenShown: function()
  429.     {
  430.         if (this.element.parentElement) {
  431.             InspectorController.enableDebuggerFromFrontend(false);
  432.         } else {
  433.             this._attachDebuggerWhenShown = true;
  434.         }
  435.     },
  436.  
  437.     debuggerWasEnabled: function()
  438.     {
  439.         this.reset();
  440.     },
  441.  
  442.     debuggerWasDisabled: function()
  443.     {
  444.         this.reset();
  445.     },
  446.  
  447.     reset: function()
  448.     {
  449.         this.visibleView = null;
  450.  
  451.         delete this.currentQuery;
  452.         this.searchCanceled();
  453.  
  454.         if (!InspectorController.debuggerEnabled()) {
  455.             this._paused = false;
  456.             this._waitingToPause = false;
  457.             this._stepping = false;
  458.         }
  459.  
  460.         this._clearInterface();
  461.  
  462.         this._backForwardList = [];
  463.         this._currentBackForwardIndex = -1;
  464.         this._updateBackAndForwardButtons();
  465.  
  466.         this._scriptsForURLsInFilesSelect = {};
  467.         this.filesSelectElement.removeChildren();
  468.         this.functionsSelectElement.removeChildren();
  469.         this.viewsContainerElement.removeChildren();
  470.  
  471.         if (this._sourceIDMap) {
  472.             for (var sourceID in this._sourceIDMap) {
  473.                 var object = this._sourceIDMap[sourceID];
  474.                 if (object instanceof WebInspector.Resource)
  475.                     object.removeAllScripts();
  476.             }
  477.         }
  478.  
  479.         this._sourceIDMap = {};
  480.     },
  481.  
  482.     get visibleView()
  483.     {
  484.         return this._visibleView;
  485.     },
  486.  
  487.     set visibleView(x)
  488.     {
  489.         if (this._visibleView === x)
  490.             return;
  491.  
  492.         if (this._visibleView)
  493.             this._visibleView.hide();
  494.  
  495.         this._visibleView = x;
  496.  
  497.         if (x)
  498.             x.show(this.viewsContainerElement);
  499.     },
  500.  
  501.     canShowResource: function(resource)
  502.     {
  503.         return resource && resource.scripts.length && InspectorController.debuggerEnabled();
  504.     },
  505.  
  506.     showScript: function(script, line)
  507.     {
  508.         this._showScriptOrResource(script, line, true);
  509.     },
  510.  
  511.     showResource: function(resource, line)
  512.     {
  513.         this._showScriptOrResource(resource, line, true);
  514.     },
  515.  
  516.     showView: function(view)
  517.     {
  518.         if (!view)
  519.             return;
  520.         this._showScriptOrResource((view.resource || view.script));
  521.     },
  522.  
  523.     handleKeyEvent: function(event)
  524.     {
  525.         var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
  526.         var handler = this._shortcuts[shortcut];
  527.         if (handler) {
  528.             handler(event);
  529.             event.preventDefault();
  530.             event.handled = true;
  531.         } else {
  532.             this.sidebarPanes.callstack.handleKeyEvent(event);
  533.         }
  534.     },
  535.  
  536.     scriptViewForScript: function(script)
  537.     {
  538.         if (!script)
  539.             return null;
  540.         if (!script._scriptView)
  541.             script._scriptView = new WebInspector.ScriptView(script);
  542.         return script._scriptView;
  543.     },
  544.  
  545.     sourceFrameForScript: function(script)
  546.     {
  547.         var view = this.scriptViewForScript(script);
  548.         if (!view)
  549.             return null;
  550.  
  551.         // Setting up the source frame requires that we be attached.
  552.         if (!this.element.parentNode)
  553.             this.attach();
  554.  
  555.         view.setupSourceFrameIfNeeded();
  556.         return view.sourceFrame;
  557.     },
  558.  
  559.     _sourceViewForScriptOrResource: function(scriptOrResource)
  560.     {
  561.         if (scriptOrResource instanceof WebInspector.Resource) {
  562.             if (!WebInspector.panels.resources)
  563.                 return null;
  564.             return WebInspector.panels.resources.resourceViewForResource(scriptOrResource);
  565.         }
  566.         if (scriptOrResource instanceof WebInspector.Script)
  567.             return this.scriptViewForScript(scriptOrResource);
  568.     },
  569.  
  570.     _sourceFrameForScriptOrResource: function(scriptOrResource)
  571.     {
  572.         if (scriptOrResource instanceof WebInspector.Resource) {
  573.             if (!WebInspector.panels.resources)
  574.                 return null;
  575.             return WebInspector.panels.resources.sourceFrameForResource(scriptOrResource);
  576.         }
  577.         if (scriptOrResource instanceof WebInspector.Script)
  578.             return this.sourceFrameForScript(scriptOrResource);
  579.     },
  580.  
  581.     _showScriptOrResource: function(scriptOrResource, line, shouldHighlightLine, fromBackForwardAction)
  582.     {
  583.         if (!scriptOrResource)
  584.             return;
  585.  
  586.         var view;
  587.         if (scriptOrResource instanceof WebInspector.Resource) {
  588.             if (!WebInspector.panels.resources)
  589.                 return null;
  590.             view = WebInspector.panels.resources.resourceViewForResource(scriptOrResource);
  591.             view.headersVisible = false;
  592.  
  593.             if (scriptOrResource.url in this._breakpointsURLMap) {
  594.                 var sourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
  595.                 if (sourceFrame && !sourceFrame.breakpoints.length) {
  596.                     var breakpoints = this._breakpointsURLMap[scriptOrResource.url];
  597.                     var breakpointsLength = breakpoints.length;
  598.                     for (var i = 0; i < breakpointsLength; ++i)
  599.                         sourceFrame.addBreakpoint(breakpoints[i]);
  600.                 }
  601.             }
  602.         } else if (scriptOrResource instanceof WebInspector.Script)
  603.             view = this.scriptViewForScript(scriptOrResource);
  604.  
  605.         if (!view)
  606.             return;
  607.  
  608.         if (!fromBackForwardAction) {
  609.             var oldIndex = this._currentBackForwardIndex;
  610.             if (oldIndex >= 0)
  611.                 this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
  612.  
  613.             // Check for a previous entry of the same object in _backForwardList.
  614.             // If one is found, remove it and update _currentBackForwardIndex to match.
  615.             var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource);
  616.             if (previousEntryIndex !== -1) {
  617.                 this._backForwardList.splice(previousEntryIndex, 1);
  618.                 --this._currentBackForwardIndex;
  619.             }
  620.  
  621.             this._backForwardList.push(scriptOrResource);
  622.             ++this._currentBackForwardIndex;
  623.  
  624.             this._updateBackAndForwardButtons();
  625.         }
  626.  
  627.         this.visibleView = view;
  628.  
  629.         if (line) {
  630.             if (view.revealLine)
  631.                 view.revealLine(line);
  632.             if (view.highlightLine && shouldHighlightLine)
  633.                 view.highlightLine(line);
  634.         }
  635.  
  636.         var option;
  637.         if (scriptOrResource instanceof WebInspector.Script) {
  638.             option = scriptOrResource.filesSelectOption;
  639.             console.assert(option);
  640.         } else {
  641.             var url = scriptOrResource.url;
  642.             var script = this._scriptsForURLsInFilesSelect[url];
  643.             if (script)
  644.                option = script.filesSelectOption;
  645.         }
  646.  
  647.         if (option)
  648.             this.filesSelectElement.selectedIndex = option.index;
  649.     },
  650.  
  651.     _addScriptToFilesMenu: function(script)
  652.     {
  653.         if (script.resource && this._scriptsForURLsInFilesSelect[script.sourceURL])
  654.             return;
  655.  
  656.         this._scriptsForURLsInFilesSelect[script.sourceURL] = script;
  657.  
  658.         var select = this.filesSelectElement;
  659.  
  660.         var option = document.createElement("option");
  661.         option.representedObject = (script.resource || script);
  662.         option.text = (script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)"));
  663.  
  664.         function optionCompare(a, b)
  665.         {
  666.             var aTitle = a.text.toLowerCase();
  667.             var bTitle = b.text.toLowerCase();
  668.             if (aTitle < bTitle)
  669.                 return -1;
  670.             else if (aTitle > bTitle)
  671.                 return 1;
  672.  
  673.             var aSourceID = a.representedObject.sourceID;
  674.             var bSourceID = b.representedObject.sourceID;
  675.             if (aSourceID < bSourceID)
  676.                 return -1;
  677.             else if (aSourceID > bSourceID)
  678.                 return 1;
  679.             return 0;
  680.         }
  681.  
  682.         var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
  683.         if (insertionIndex < 0)
  684.             select.appendChild(option);
  685.         else
  686.             select.insertBefore(option, select.childNodes.item(insertionIndex));
  687.  
  688.         script.filesSelectOption = option;
  689.  
  690.         // Call _showScriptOrResource if the option we just appended ended up being selected.
  691.         // This will happen for the first item added to the menu.
  692.         if (select.options[select.selectedIndex] === option)
  693.             this._showScriptOrResource(option.representedObject);
  694.     },
  695.  
  696.     _clearCurrentExecutionLine: function()
  697.     {
  698.         if (this._executionSourceFrame)
  699.             this._executionSourceFrame.executionLine = 0;
  700.         delete this._executionSourceFrame;
  701.     },
  702.  
  703.     _callFrameSelected: function()
  704.     {
  705.         this._clearCurrentExecutionLine();
  706.  
  707.         var callStackPane = this.sidebarPanes.callstack;
  708.         var currentFrame = callStackPane.selectedCallFrame;
  709.         if (!currentFrame)
  710.             return;
  711.  
  712.         this.sidebarPanes.scopechain.update(currentFrame);
  713.  
  714.         var scriptOrResource = this._sourceIDMap[currentFrame.sourceID];
  715.         this._showScriptOrResource(scriptOrResource, currentFrame.line);
  716.  
  717.         this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
  718.         if (this._executionSourceFrame)
  719.             this._executionSourceFrame.executionLine = currentFrame.line;
  720.     },
  721.  
  722.     _changeVisibleFile: function(event)
  723.     {
  724.         var select = this.filesSelectElement;
  725.         this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
  726.     },
  727.  
  728.     _startSidebarResizeDrag: function(event)
  729.     {
  730.         WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "col-resize");
  731.  
  732.         if (event.target === this.sidebarResizeWidgetElement)
  733.             this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft));
  734.         else
  735.             this._dragOffset = 0;
  736.     },
  737.  
  738.     _endSidebarResizeDrag: function(event)
  739.     {
  740.         WebInspector.elementDragEnd(event);
  741.  
  742.         delete this._dragOffset;
  743.     },
  744.  
  745.     _sidebarResizeDrag: function(event)
  746.     {
  747.         var x = event.pageX + this._dragOffset;
  748.         var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
  749.  
  750.         this.sidebarElement.style.width = newWidth + "px";
  751.         this.sidebarButtonsElement.style.width = newWidth + "px";
  752.         this.viewsContainerElement.style.right = newWidth + "px";
  753.         this.sidebarResizeWidgetElement.style.right = newWidth + "px";
  754.         this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
  755.  
  756.         event.preventDefault();
  757.     },
  758.  
  759.     _updatePauseOnExceptionsButton: function()
  760.     {
  761.         if (InspectorController.pauseOnExceptions()) {
  762.             this.pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.");
  763.             this.pauseOnExceptionButton.addStyleClass("toggled-on");
  764.         } else {
  765.             this.pauseOnExceptionButton.title = WebInspector.UIString("Pause on exceptions.");
  766.             this.pauseOnExceptionButton.removeStyleClass("toggled-on");
  767.         }
  768.     },
  769.  
  770.     _updateDebuggerButtons: function()
  771.     {
  772.         if (InspectorController.debuggerEnabled()) {
  773.             this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
  774.             this.enableToggleButton.addStyleClass("toggled-on");
  775.             this.pauseOnExceptionButton.removeStyleClass("hidden");
  776.             this.panelEnablerView.visible = false;
  777.         } else {
  778.             this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
  779.             this.enableToggleButton.removeStyleClass("toggled-on");
  780.             this.pauseOnExceptionButton.addStyleClass("hidden");
  781.             this.panelEnablerView.visible = true;
  782.         }
  783.  
  784.         this._updatePauseOnExceptionsButton();
  785.  
  786.         if (this._paused) {
  787.             this.pauseButton.addStyleClass("paused");
  788.  
  789.             this.pauseButton.disabled = false;
  790.             this.stepOverButton.disabled = false;
  791.             this.stepIntoButton.disabled = false;
  792.             this.stepOutButton.disabled = false;
  793.  
  794.             this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
  795.         } else {
  796.             this.pauseButton.removeStyleClass("paused");
  797.  
  798.             this.pauseButton.disabled = this._waitingToPause;
  799.             this.stepOverButton.disabled = true;
  800.             this.stepIntoButton.disabled = true;
  801.             this.stepOutButton.disabled = true;
  802.  
  803.             if (this._waitingToPause)
  804.                 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
  805.             else if (this._stepping)
  806.                 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
  807.             else
  808.                 this.debuggerStatusElement.textContent = "";
  809.         }
  810.     },
  811.  
  812.     _updateBackAndForwardButtons: function()
  813.     {
  814.         this.backButton.disabled = this._currentBackForwardIndex <= 0;
  815.         this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1);
  816.     },
  817.  
  818.     _clearInterface: function()
  819.     {
  820.         this.sidebarPanes.callstack.update(null);
  821.         this.sidebarPanes.scopechain.update(null);
  822.  
  823.         this._clearCurrentExecutionLine();
  824.         this._updateDebuggerButtons();
  825.     },
  826.  
  827.     _goBack: function()
  828.     {
  829.         if (this._currentBackForwardIndex <= 0) {
  830.             console.error("Can't go back from index " + this._currentBackForwardIndex);
  831.             return;
  832.         }
  833.  
  834.         this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], null, false, true);
  835.         this._updateBackAndForwardButtons();
  836.     },
  837.  
  838.     _goForward: function()
  839.     {
  840.         if (this._currentBackForwardIndex >= this._backForwardList.length - 1) {
  841.             console.error("Can't go forward from index " + this._currentBackForwardIndex);
  842.             return;
  843.         }
  844.  
  845.         this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], null, false, true);
  846.         this._updateBackAndForwardButtons();
  847.     },
  848.  
  849.     _enableDebugging: function()
  850.     {
  851.         if (InspectorController.debuggerEnabled())
  852.             return;
  853.         this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
  854.     },
  855.  
  856.     _toggleDebugging: function(optionalAlways)
  857.     {
  858.         this._paused = false;
  859.         this._waitingToPause = false;
  860.         this._stepping = false;
  861.  
  862.         if (InspectorController.debuggerEnabled())
  863.             InspectorController.disableDebugger(true);
  864.         else
  865.             InspectorController.enableDebuggerFromFrontend(!!optionalAlways);
  866.     },
  867.  
  868.     _togglePauseOnExceptions: function()
  869.     {
  870.         InspectorController.setPauseOnExceptions(!InspectorController.pauseOnExceptions());
  871.         this._updatePauseOnExceptionsButton();
  872.     },
  873.  
  874.     _togglePause: function()
  875.     {
  876.         if (this._paused) {
  877.             this._paused = false;
  878.             this._waitingToPause = false;
  879.             InspectorController.resumeDebugger();
  880.         } else {
  881.             this._stepping = false;
  882.             this._waitingToPause = true;
  883.             InspectorController.pauseInDebugger();
  884.         }
  885.  
  886.         this._clearInterface();
  887.     },
  888.  
  889.     _stepOverClicked: function()
  890.     {
  891.         this._paused = false;
  892.         this._stepping = true;
  893.  
  894.         this._clearInterface();
  895.  
  896.         InspectorController.stepOverStatementInDebugger();
  897.     },
  898.  
  899.     _stepIntoClicked: function()
  900.     {
  901.         this._paused = false;
  902.         this._stepping = true;
  903.  
  904.         this._clearInterface();
  905.  
  906.         InspectorController.stepIntoStatementInDebugger();
  907.     },
  908.  
  909.     _stepOutClicked: function()
  910.     {
  911.         this._paused = false;
  912.         this._stepping = true;
  913.  
  914.         this._clearInterface();
  915.  
  916.         InspectorController.stepOutOfFunctionInDebugger();
  917.     }
  918. }
  919.  
  920. WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
  921.