ScriptsPanel.js 57 KB

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