CallStackSidebarPane.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. * @constructor
  27. * @extends {WebInspector.SidebarPane}
  28. */
  29. WebInspector.CallStackSidebarPane = function()
  30. {
  31. WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
  32. this._model = WebInspector.debuggerModel;
  33. this.bodyElement.addEventListener("keydown", this._keyDown.bind(this), true);
  34. this.bodyElement.tabIndex = 0;
  35. }
  36. WebInspector.CallStackSidebarPane.Events = {
  37. CallFrameSelected: "CallFrameSelected"
  38. }
  39. WebInspector.CallStackSidebarPane.prototype = {
  40. update: function(callFrames)
  41. {
  42. this.bodyElement.removeChildren();
  43. delete this._statusMessageElement;
  44. this.placards = [];
  45. if (!callFrames) {
  46. var infoElement = document.createElement("div");
  47. infoElement.className = "info";
  48. infoElement.textContent = WebInspector.UIString("Not Paused");
  49. this.bodyElement.appendChild(infoElement);
  50. return;
  51. }
  52. for (var i = 0; i < callFrames.length; ++i) {
  53. var callFrame = callFrames[i];
  54. var placard = new WebInspector.CallStackSidebarPane.Placard(callFrame, this);
  55. placard.element.addEventListener("click", this._placardSelected.bind(this, placard), false);
  56. this.placards.push(placard);
  57. this.bodyElement.appendChild(placard.element);
  58. }
  59. },
  60. setSelectedCallFrame: function(x)
  61. {
  62. for (var i = 0; i < this.placards.length; ++i) {
  63. var placard = this.placards[i];
  64. placard.selected = (placard._callFrame === x);
  65. }
  66. },
  67. /**
  68. * @param {Event=} event
  69. * @return {boolean}
  70. */
  71. _selectNextCallFrameOnStack: function(event)
  72. {
  73. var index = this._selectedCallFrameIndex();
  74. if (index == -1)
  75. return true;
  76. this._selectedPlacardByIndex(index + 1);
  77. return true;
  78. },
  79. /**
  80. * @param {Event=} event
  81. * @return {boolean}
  82. */
  83. _selectPreviousCallFrameOnStack: function(event)
  84. {
  85. var index = this._selectedCallFrameIndex();
  86. if (index == -1)
  87. return true;
  88. this._selectedPlacardByIndex(index - 1);
  89. return true;
  90. },
  91. /**
  92. * @param {number} index
  93. */
  94. _selectedPlacardByIndex: function(index)
  95. {
  96. if (index < 0 || index >= this.placards.length)
  97. return;
  98. this._placardSelected(this.placards[index])
  99. },
  100. /**
  101. * @return {number}
  102. */
  103. _selectedCallFrameIndex: function()
  104. {
  105. if (!this._model.selectedCallFrame())
  106. return -1;
  107. for (var i = 0; i < this.placards.length; ++i) {
  108. var placard = this.placards[i];
  109. if (placard._callFrame === this._model.selectedCallFrame())
  110. return i;
  111. }
  112. return -1;
  113. },
  114. _placardSelected: function(placard)
  115. {
  116. this.dispatchEventToListeners(WebInspector.CallStackSidebarPane.Events.CallFrameSelected, placard._callFrame);
  117. },
  118. _copyStackTrace: function()
  119. {
  120. var text = "";
  121. for (var i = 0; i < this.placards.length; ++i)
  122. text += this.placards[i].title + " (" + this.placards[i].subtitle + ")\n";
  123. InspectorFrontendHost.copyText(text);
  124. },
  125. /**
  126. * @param {function(!Array.<!WebInspector.KeyboardShortcut.Descriptor>, function(Event=):boolean)} registerShortcutDelegate
  127. */
  128. registerShortcuts: function(registerShortcutDelegate)
  129. {
  130. registerShortcutDelegate(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.NextCallFrame, this._selectNextCallFrameOnStack.bind(this));
  131. registerShortcutDelegate(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.PrevCallFrame, this._selectPreviousCallFrameOnStack.bind(this));
  132. },
  133. setStatus: function(status)
  134. {
  135. if (!this._statusMessageElement) {
  136. this._statusMessageElement = document.createElement("div");
  137. this._statusMessageElement.className = "info";
  138. this.bodyElement.appendChild(this._statusMessageElement);
  139. }
  140. if (typeof status === "string")
  141. this._statusMessageElement.textContent = status;
  142. else {
  143. this._statusMessageElement.removeChildren();
  144. this._statusMessageElement.appendChild(status);
  145. }
  146. },
  147. _keyDown: function(event)
  148. {
  149. if (event.altKey || event.shiftKey || event.metaKey || event.ctrlKey)
  150. return;
  151. if (event.keyIdentifier === "Up") {
  152. this._selectPreviousCallFrameOnStack();
  153. event.consume();
  154. } else if (event.keyIdentifier === "Down") {
  155. this._selectNextCallFrameOnStack();
  156. event.consume();
  157. }
  158. },
  159. __proto__: WebInspector.SidebarPane.prototype
  160. }
  161. /**
  162. * @constructor
  163. * @extends {WebInspector.Placard}
  164. * @param {WebInspector.DebuggerModel.CallFrame} callFrame
  165. * @param {WebInspector.CallStackSidebarPane} pane
  166. */
  167. WebInspector.CallStackSidebarPane.Placard = function(callFrame, pane)
  168. {
  169. WebInspector.Placard.call(this, callFrame.functionName || WebInspector.UIString("(anonymous function)"), "");
  170. callFrame.createLiveLocation(this._update.bind(this));
  171. this.element.addEventListener("contextmenu", this._placardContextMenu.bind(this), true);
  172. this._callFrame = callFrame;
  173. this._pane = pane;
  174. }
  175. WebInspector.CallStackSidebarPane.Placard.prototype = {
  176. _update: function(uiLocation)
  177. {
  178. this.subtitle = uiLocation.linkText().trimMiddle(100);
  179. },
  180. _placardContextMenu: function(event)
  181. {
  182. var contextMenu = new WebInspector.ContextMenu(event);
  183. if (WebInspector.debuggerModel.canSetScriptSource()) {
  184. contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Restart frame" : "Restart Frame"), this._restartFrame.bind(this));
  185. contextMenu.appendSeparator();
  186. }
  187. contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy stack trace" : "Copy Stack Trace"), this._pane._copyStackTrace.bind(this._pane));
  188. contextMenu.show();
  189. },
  190. _restartFrame: function()
  191. {
  192. this._callFrame.restart(undefined);
  193. },
  194. __proto__: WebInspector.Placard.prototype
  195. }