OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | |
25 /** | 26 /** |
26 * @implements {UI.ContextFlavorListener} | 27 * @implements {UI.ContextFlavorListener} |
28 * @implements {UI.ListDelegate<!Sources.CallStackSidebarPane.Item>} | |
27 * @unrestricted | 29 * @unrestricted |
28 */ | 30 */ |
29 Sources.CallStackSidebarPane = class extends UI.SimpleView { | 31 Sources.CallStackSidebarPane = class extends UI.SimpleView { |
30 constructor() { | 32 constructor() { |
31 super(Common.UIString('Call Stack')); | 33 super(Common.UIString('Call Stack'), true); |
32 this.callFrameList = new Sources.UIList(); | 34 this.registerRequiredCSS('sources/callStackSidebarPane.css'); |
33 this.callFrameList.show(this.element); | 35 |
34 this._linkifier = new Components.Linkifier(); | 36 this._blackboxedMessageElement = this._createBlackboxedMessageElement(); |
35 Common.moduleSetting('enableAsyncStackTraces').addChangeListener(this._async StackTracesStateChanged, this); | 37 this.contentElement.appendChild(this._blackboxedMessageElement); |
36 Common.moduleSetting('skipStackFramesPattern').addChangeListener(this._updat e, this); | 38 |
37 /** @type {!Array<!Sources.CallStackSidebarPane.CallFrame>} */ | 39 this._notPausedMessageElement = this.contentElement.createChild('div', 'gray -info-message'); |
38 this.callFrames = []; | 40 this._notPausedMessageElement.textContent = Common.UIString('Not Paused'); |
41 | |
42 /** @type {!UI.ListControl<!Sources.CallStackSidebarPane.Item>} */ | |
43 this._list = new UI.ListControl(this, UI.ListMode.Grow); | |
44 this._list.setHandleInput(true); | |
45 this.contentElement.appendChild(this._list.element); | |
46 | |
47 Common.moduleSetting('enableAsyncStackTraces').addChangeListener(this._updat e.bind(this, false)); | |
48 Common.moduleSetting('skipStackFramesPattern').addChangeListener(this._updat e.bind(this, false)); | |
39 this._locationPool = new Bindings.LiveLocationPool(); | 49 this._locationPool = new Bindings.LiveLocationPool(); |
40 this._update(); | 50 |
51 this._update(false); | |
41 } | 52 } |
42 | 53 |
43 /** | 54 /** |
44 * @override | 55 * @override |
45 * @param {?Object} object | 56 * @param {?Object} object |
46 */ | 57 */ |
47 flavorChanged(object) { | 58 flavorChanged(object) { |
48 this._update(); | 59 this._update(false); |
49 } | 60 } |
50 | 61 |
51 _update() { | 62 /** |
52 var details = UI.context.flavor(SDK.DebuggerPausedDetails); | 63 * @param {boolean} showBlackboxed |
53 | 64 */ |
54 this.callFrameList.detach(); | 65 _update(showBlackboxed) { |
55 this.callFrameList.clear(); | |
56 this._linkifier.reset(); | |
57 this.element.removeChildren(); | |
58 this._locationPool.disposeAll(); | 66 this._locationPool.disposeAll(); |
59 | 67 |
60 this.callFrameList.show(this.element); | 68 var details = UI.context.flavor(SDK.DebuggerPausedDetails); |
61 delete this._hiddenCallFramesMessageElement; | |
62 this.callFrames = []; | |
63 this._hiddenCallFrames = 0; | |
64 | |
65 if (!details) { | 69 if (!details) { |
66 var infoElement = this.element.createChild('div', 'gray-info-message'); | 70 this._notPausedMessageElement.classList.remove('hidden'); |
67 infoElement.textContent = Common.UIString('Not Paused'); | 71 this._blackboxedMessageElement.classList.add('hidden'); |
72 this._list.replaceAllItems([]); | |
73 this._debuggerModel = null; | |
68 UI.context.setFlavor(SDK.DebuggerModel.CallFrame, null); | 74 UI.context.setFlavor(SDK.DebuggerModel.CallFrame, null); |
69 return; | 75 return; |
70 } | 76 } |
77 | |
71 this._debuggerModel = details.debuggerModel; | 78 this._debuggerModel = details.debuggerModel; |
79 this._notPausedMessageElement.classList.add('hidden'); | |
80 | |
81 if (!showBlackboxed) { | |
caseq
2016/12/30 01:54:43
showBlackboxed = showBlackboxed || details.callFra
dgozman
2017/01/18 23:14:24
Done.
| |
82 var topFrameHidden = true; | |
83 for (var i = 0; i < details.callFrames.length; i++) { | |
84 if (!Bindings.blackboxManager.isBlackboxedRawLocation(details.callFrames [i].location())) { | |
85 topFrameHidden = false; | |
86 break; | |
87 } | |
88 } | |
89 if (topFrameHidden) | |
90 showBlackboxed = true; | |
91 } | |
92 | |
93 var hiddenCallFramesCount = 0; | |
94 var items = []; | |
95 | |
96 for (var i = 0; i < details.callFrames.length; i++) { | |
caseq
2016/12/30 01:54:43
var items = details.callFrames.map(frame => ({debu
dgozman
2017/01/18 23:14:25
Done.
| |
97 var item = {debuggerCallFrame: details.callFrames[i]}; | |
98 var location = this._itemLocation(item); | |
99 if (!showBlackboxed && location && Bindings.blackboxManager.isBlackboxedRa wLocation(location)) { | |
100 hiddenCallFramesCount++; | |
101 continue; | |
102 } | |
103 items.push(item); | |
104 } | |
105 | |
72 var asyncStackTrace = details.asyncStackTrace; | 106 var asyncStackTrace = details.asyncStackTrace; |
73 | |
74 this._appendSidebarCallFrames(this._callFramesFromDebugger(details.callFrame s)); | |
75 var topStackHidden = (this._hiddenCallFrames === this.callFrames.length); | |
76 | |
77 var peviousStackTrace = details.callFrames; | 107 var peviousStackTrace = details.callFrames; |
78 while (asyncStackTrace) { | 108 while (asyncStackTrace) { |
79 var title = ''; | 109 var title = ''; |
80 if (asyncStackTrace.description === 'async function') { | 110 if (asyncStackTrace.description === 'async function') { |
81 var lastPreviousFrame = peviousStackTrace[peviousStackTrace.length - 1]; | 111 var lastPreviousFrame = peviousStackTrace[peviousStackTrace.length - 1]; |
82 var topFrame = asyncStackTrace.callFrames[0]; | 112 var topFrame = asyncStackTrace.callFrames[0]; |
83 var lastPreviousFrameName = UI.beautifyFunctionName(lastPreviousFrame.fu nctionName); | 113 var lastPreviousFrameName = UI.beautifyFunctionName(lastPreviousFrame.fu nctionName); |
84 var topFrameName = UI.beautifyFunctionName(topFrame.functionName); | 114 var topFrameName = UI.beautifyFunctionName(topFrame.functionName); |
85 title = topFrameName + ' awaits ' + lastPreviousFrameName; | 115 title = topFrameName + ' awaits ' + lastPreviousFrameName; |
86 } else { | 116 } else { |
87 title = UI.asyncStackTraceLabel(asyncStackTrace.description); | 117 title = UI.asyncStackTraceLabel(asyncStackTrace.description); |
88 } | 118 } |
89 var asyncCallFrame = new Sources.UIList.Item(title, '', true); | 119 |
90 asyncCallFrame.setHoverable(false); | 120 var asyncItems = []; |
91 asyncCallFrame.element.addEventListener( | 121 for (var i = 0; i < asyncStackTrace.callFrames.length; i++) { |
92 'contextmenu', this._asyncCallFrameContextMenu.bind(this, this.callFra mes.length), true); | 122 var item = {runtimeCallFrame: asyncStackTrace.callFrames[i]}; |
93 this._appendSidebarCallFrames( | 123 var location = this._itemLocation(item); |
94 this._callFramesFromRuntime(asyncStackTrace.callFrames, asyncCallFrame ), asyncCallFrame); | 124 if (!showBlackboxed && location && Bindings.blackboxManager.isBlackboxed RawLocation(location)) { |
125 hiddenCallFramesCount++; | |
126 continue; | |
127 } | |
128 asyncItems.push(item); | |
129 } | |
130 | |
131 if (asyncItems.length) { | |
132 items.push({asyncStackHeader: title}); | |
133 for (var i = 0; i < asyncItems.length; i++) | |
134 items.push(asyncItems[i]); | |
135 } | |
136 | |
95 peviousStackTrace = asyncStackTrace.callFrames; | 137 peviousStackTrace = asyncStackTrace.callFrames; |
96 asyncStackTrace = asyncStackTrace.parent; | 138 asyncStackTrace = asyncStackTrace.parent; |
97 } | 139 } |
98 | 140 |
99 if (topStackHidden) | 141 if (!hiddenCallFramesCount) { |
100 this._revealHiddenCallFrames(); | 142 this._blackboxedMessageElement.classList.add('hidden'); |
101 if (this._hiddenCallFrames) { | 143 } else { |
102 var element = createElementWithClass('div', 'hidden-callframes-message'); | 144 if (hiddenCallFramesCount === 1) { |
103 if (this._hiddenCallFrames === 1) | 145 this._blackboxedMessageElement.firstChild.textContent = |
104 element.textContent = Common.UIString('1 stack frame is hidden (black-bo xed).'); | 146 Common.UIString('1 stack frame is hidden (black-boxed).'); |
105 else | 147 } else { |
106 element.textContent = Common.UIString('%d stack frames are hidden (black -boxed).', this._hiddenCallFrames); | 148 this._blackboxedMessageElement.firstChild.textContent = |
107 element.createTextChild(' '); | 149 Common.UIString('%d stack frames are hidden (black-boxed).', hiddenC allFramesCount); |
108 var showAllLink = element.createChild('span', 'link'); | 150 } |
109 showAllLink.textContent = Common.UIString('Show'); | 151 this._blackboxedMessageElement.classList.remove('hidden'); |
110 showAllLink.addEventListener('click', this._revealHiddenCallFrames.bind(th is), false); | |
111 this.element.insertBefore(element, this.element.firstChild); | |
112 this._hiddenCallFramesMessageElement = element; | |
113 } | 152 } |
114 this._selectNextVisibleCallFrame(0); | 153 |
154 this._list.replaceAllItems(items); | |
155 this._list.selectNextItem(true, true); | |
115 } | 156 } |
116 | 157 |
117 /** | 158 /** |
118 * @param {!Array.<!SDK.DebuggerModel.CallFrame>} callFrames | 159 * @override |
119 * @return {!Array<!Sources.CallStackSidebarPane.CallFrame>} | 160 * @param {!Sources.CallStackSidebarPane.Item} item |
161 * @return {!Element} | |
120 */ | 162 */ |
121 _callFramesFromDebugger(callFrames) { | 163 createElementForItem(item) { |
122 var callFrameItems = []; | 164 var element = createElementWithClass('div', 'call-frame-item'); |
123 for (var i = 0, n = callFrames.length; i < n; ++i) { | 165 element.addEventListener('contextmenu', this._onContextMenu.bind(this, item) , true); |
caseq
2016/12/30 01:54:43
can we have just one event listener for the entire
dgozman
2017/01/18 23:14:25
Done.
| |
124 var callFrame = callFrames[i]; | 166 element.createChild('div', 'call-frame-item-title').textContent = this._item Title(item); |
125 var callFrameItem = new Sources.CallStackSidebarPane.CallFrame( | 167 if (item.asyncStackHeader) |
126 callFrame.functionName, callFrame.location(), this._linkifier, callFra me, this._locationPool); | 168 element.classList.add('async-header'); |
127 callFrameItem.element.addEventListener('click', this._callFrameSelected.bi nd(this, callFrameItem), false); | 169 |
128 callFrameItems.push(callFrameItem); | 170 var location = this._itemLocation(item); |
171 if (location) { | |
172 if (item.runtimeCallFrame) { | |
173 element.addEventListener('click', event => { | |
caseq
2016/12/30 01:54:43
ditto.
dgozman
2017/01/18 23:14:25
Done.
| |
174 Common.Revealer.reveal(Bindings.debuggerWorkspaceBinding.rawLocationTo UILocation( | |
175 /** @type {!SDK.DebuggerModel.Location} */ (location))); | |
176 }, false); | |
177 } | |
178 | |
179 if (Bindings.blackboxManager.isBlackboxedRawLocation(location)) | |
180 element.classList.add('blackboxed-call-frame'); | |
181 | |
182 var linkElement = element.createChild('div', 'call-frame-location'); | |
183 Bindings.debuggerWorkspaceBinding.createCallFrameLiveLocation(location, li veLocation => { | |
caseq
2016/12/30 01:54:43
nit: extract a named function
dgozman
2017/01/18 23:14:25
Done.
| |
184 var uiLocation = liveLocation.uiLocation(); | |
185 if (!uiLocation) | |
186 return; | |
187 var text = uiLocation.linkText(); | |
188 linkElement.textContent = text.trimMiddle(30); | |
189 linkElement.title = text; | |
190 }, this._locationPool); | |
129 } | 191 } |
130 return callFrameItems; | 192 |
193 return element; | |
131 } | 194 } |
132 | 195 |
133 /** | 196 /** |
134 * @param {!Array<!Protocol.Runtime.CallFrame>} callFrames | 197 * @override |
135 * @param {!Sources.UIList.Item} asyncCallFrameItem | 198 * @param {!Sources.CallStackSidebarPane.Item} item |
136 * @return {!Array<!Sources.CallStackSidebarPane.CallFrame>} | 199 * @return {number} |
137 */ | 200 */ |
138 _callFramesFromRuntime(callFrames, asyncCallFrameItem) { | 201 heightForItem(item) { |
139 var callFrameItems = []; | 202 return 0; |
caseq
2016/12/30 01:54:43
throw 'Not implemented'?
dgozman
2017/01/18 23:14:25
Done.
| |
140 for (var i = 0, n = callFrames.length; i < n; ++i) { | |
141 var callFrame = callFrames[i]; | |
142 var location = new SDK.DebuggerModel.Location( | |
143 this._debuggerModel, callFrame.scriptId, callFrame.lineNumber, callFra me.columnNumber); | |
144 var callFrameItem = new Sources.CallStackSidebarPane.CallFrame( | |
145 callFrame.functionName, location, this._linkifier, null, this._locatio nPool, asyncCallFrameItem); | |
146 callFrameItem.element.addEventListener('click', this._asyncCallFrameClicke d.bind(this, callFrameItem), false); | |
147 callFrameItems.push(callFrameItem); | |
148 } | |
149 return callFrameItems; | |
150 } | 203 } |
151 | 204 |
152 /** | 205 /** |
153 * @param {!Array.<!Sources.CallStackSidebarPane.CallFrame>} callFrames | 206 * @override |
154 * @param {!Sources.UIList.Item=} asyncCallFrameItem | 207 * @param {!Sources.CallStackSidebarPane.Item} item |
208 * @return {boolean} | |
155 */ | 209 */ |
156 _appendSidebarCallFrames(callFrames, asyncCallFrameItem) { | 210 isItemSelectable(item) { |
157 if (asyncCallFrameItem) | 211 return !!item.debuggerCallFrame; |
158 this.callFrameList.addItem(asyncCallFrameItem); | |
159 | |
160 var allCallFramesHidden = true; | |
161 for (var i = 0, n = callFrames.length; i < n; ++i) { | |
162 var callFrameItem = callFrames[i]; | |
163 callFrameItem.element.addEventListener('contextmenu', this._callFrameConte xtMenu.bind(this, callFrameItem), true); | |
164 this.callFrames.push(callFrameItem); | |
165 | |
166 if (Bindings.blackboxManager.isBlackboxedRawLocation(callFrameItem._locati on)) { | |
167 callFrameItem.setHidden(true); | |
168 callFrameItem.setDimmed(true); | |
169 ++this._hiddenCallFrames; | |
170 } else { | |
171 this.callFrameList.addItem(callFrameItem); | |
172 allCallFramesHidden = false; | |
173 } | |
174 } | |
175 if (allCallFramesHidden && asyncCallFrameItem) { | |
176 asyncCallFrameItem.setHidden(true); | |
177 asyncCallFrameItem.element.remove(); | |
178 } | |
179 } | |
180 | |
181 _revealHiddenCallFrames() { | |
182 if (!this._hiddenCallFrames) | |
183 return; | |
184 this._hiddenCallFrames = 0; | |
185 this.callFrameList.clear(); | |
186 for (var i = 0; i < this.callFrames.length; ++i) { | |
187 var callFrame = this.callFrames[i]; | |
188 if (callFrame._asyncCallFrame) { | |
189 callFrame._asyncCallFrame.setHidden(false); | |
190 if (i && callFrame._asyncCallFrame !== this.callFrames[i - 1]._asyncCall Frame) | |
191 this.callFrameList.addItem(callFrame._asyncCallFrame); | |
192 } | |
193 callFrame.setHidden(false); | |
194 this.callFrameList.addItem(callFrame); | |
195 } | |
196 if (this._hiddenCallFramesMessageElement) { | |
197 this._hiddenCallFramesMessageElement.remove(); | |
198 delete this._hiddenCallFramesMessageElement; | |
199 } | |
200 } | 212 } |
201 | 213 |
202 /** | 214 /** |
203 * @param {!Sources.CallStackSidebarPane.CallFrame} callFrame | 215 * @override |
216 * @param {?Sources.CallStackSidebarPane.Item} from | |
217 * @param {?Sources.CallStackSidebarPane.Item} to | |
218 * @param {?Element} fromElement | |
219 * @param {?Element} toElement | |
220 */ | |
221 selectedItemChanged(from, to, fromElement, toElement) { | |
222 if (fromElement) | |
223 fromElement.removeChild(fromElement.lastElementChild); | |
caseq
2016/12/30 01:54:43
can we toggle a class instead?
dgozman
2017/01/18 23:14:25
Done.
| |
224 if (toElement) | |
225 toElement.appendChild(UI.Icon.create('smallicon-thick-right-arrow', 'selec ted-call-frame-icon')); | |
226 | |
227 if (!to) | |
228 return; | |
229 | |
230 var oldCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame); | |
231 if (oldCallFrame === to.debuggerCallFrame) { | |
232 var uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation (oldCallFrame.location()); | |
233 Common.Revealer.reveal(uiLocation); | |
234 return; | |
235 } | |
236 | |
237 UI.context.setFlavor(SDK.DebuggerModel.CallFrame, to.debuggerCallFrame); | |
238 this._debuggerModel.setSelectedCallFrame(to.debuggerCallFrame); | |
239 } | |
240 | |
241 /** | |
242 * @param {!Sources.CallStackSidebarPane.Item} item | |
243 * @return {string} | |
244 */ | |
245 _itemTitle(item) { | |
246 if (item.debuggerCallFrame) | |
247 return UI.beautifyFunctionName(item.debuggerCallFrame.functionName); | |
248 if (item.runtimeCallFrame) | |
249 return UI.beautifyFunctionName(item.runtimeCallFrame.functionName); | |
250 return item.asyncStackHeader || ''; | |
251 } | |
252 | |
253 /** | |
254 * @param {!Sources.CallStackSidebarPane.Item} item | |
255 * @return {?SDK.DebuggerModel.Location} | |
256 */ | |
257 _itemLocation(item) { | |
258 if (item.debuggerCallFrame) | |
259 return item.debuggerCallFrame.location(); | |
260 if (item.runtimeCallFrame) { | |
261 return new SDK.DebuggerModel.Location( | |
262 this._debuggerModel, item.runtimeCallFrame.scriptId, item.runtimeCallF rame.lineNumber, | |
263 item.runtimeCallFrame.columnNumber); | |
264 } | |
265 return null; | |
266 } | |
267 | |
268 /** | |
269 * @return {!Element} | |
270 */ | |
271 _createBlackboxedMessageElement() { | |
272 var element = createElementWithClass('div', 'blackboxed-message'); | |
273 element.createTextChild(''); | |
274 element.createTextChild(' '); | |
caseq
2016/12/30 01:54:43
Let's not have multiple adjacent text nodes.
dgozman
2017/01/18 23:14:25
Done.
| |
275 var showAllLink = element.createChild('span', 'link'); | |
276 showAllLink.textContent = Common.UIString('Show'); | |
277 showAllLink.addEventListener('click', this._update.bind(this, true), false); | |
278 return element; | |
279 } | |
280 | |
281 /** | |
282 * @param {!Sources.CallStackSidebarPane.Item} item | |
204 * @param {!Event} event | 283 * @param {!Event} event |
205 */ | 284 */ |
206 _callFrameContextMenu(callFrame, event) { | 285 _onContextMenu(item, event) { |
207 var contextMenu = new UI.ContextMenu(event); | 286 var contextMenu = new UI.ContextMenu(event); |
208 var debuggerCallFrame = callFrame._debuggerCallFrame; | 287 if (item.debuggerCallFrame) |
209 if (debuggerCallFrame) { | 288 contextMenu.appendItem(Common.UIString.capitalize('Restart ^frame'), () => item.debuggerCallFrame.restart()); |
210 contextMenu.appendItem( | 289 contextMenu.appendItem(Common.UIString.capitalize('Copy ^stack ^trace'), thi s._copyStackTrace.bind(this)); |
211 Common.UIString.capitalize('Restart ^frame'), debuggerCallFrame.restar t.bind(debuggerCallFrame)); | 290 var location = this._itemLocation(item); |
291 if (location) { | |
292 var uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation (location); | |
293 this.appendBlackboxURLContextMenuItems(contextMenu, uiLocation.uiSourceCod e); | |
212 } | 294 } |
213 | |
214 contextMenu.appendItem(Common.UIString.capitalize('Copy ^stack ^trace'), thi s._copyStackTrace.bind(this)); | |
215 | |
216 var uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(c allFrame._location); | |
217 this.appendBlackboxURLContextMenuItems(contextMenu, uiLocation.uiSourceCode) ; | |
218 | |
219 contextMenu.show(); | 295 contextMenu.show(); |
220 } | 296 } |
221 | 297 |
222 /** | 298 /** |
223 * @param {number} index | |
224 * @param {!Event} event | |
225 */ | |
226 _asyncCallFrameContextMenu(index, event) { | |
227 for (; index < this.callFrames.length; ++index) { | |
228 var callFrame = this.callFrames[index]; | |
229 if (!callFrame.isHidden()) { | |
230 this._callFrameContextMenu(callFrame, event); | |
231 break; | |
232 } | |
233 } | |
234 } | |
235 | |
236 /** | |
237 * @param {!UI.ContextMenu} contextMenu | 299 * @param {!UI.ContextMenu} contextMenu |
238 * @param {!Workspace.UISourceCode} uiSourceCode | 300 * @param {!Workspace.UISourceCode} uiSourceCode |
239 */ | 301 */ |
240 appendBlackboxURLContextMenuItems(contextMenu, uiSourceCode) { | 302 appendBlackboxURLContextMenuItems(contextMenu, uiSourceCode) { |
241 var binding = Persistence.persistence.binding(uiSourceCode); | 303 var binding = Persistence.persistence.binding(uiSourceCode); |
242 if (binding) | 304 if (binding) |
243 uiSourceCode = binding.network; | 305 uiSourceCode = binding.network; |
244 if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) | 306 if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) |
245 return; | 307 return; |
246 var canBlackbox = Bindings.blackboxManager.canBlackboxUISourceCode(uiSourceC ode); | 308 var canBlackbox = Bindings.blackboxManager.canBlackboxUISourceCode(uiSourceC ode); |
(...skipping 17 matching lines...) Expand all Loading... | |
264 Common.UIString.capitalize('Stop blackboxing ^all ^content ^scripts' ), | 326 Common.UIString.capitalize('Stop blackboxing ^all ^content ^scripts' ), |
265 manager.blackboxContentScripts.bind(manager)); | 327 manager.blackboxContentScripts.bind(manager)); |
266 } else { | 328 } else { |
267 contextMenu.appendItem( | 329 contextMenu.appendItem( |
268 Common.UIString.capitalize('Blackbox ^all ^content ^scripts'), | 330 Common.UIString.capitalize('Blackbox ^all ^content ^scripts'), |
269 manager.unblackboxContentScripts.bind(manager)); | 331 manager.unblackboxContentScripts.bind(manager)); |
270 } | 332 } |
271 } | 333 } |
272 } | 334 } |
273 | 335 |
274 _asyncStackTracesStateChanged() { | |
275 var enabled = Common.moduleSetting('enableAsyncStackTraces').get(); | |
276 if (!enabled && this.callFrames) | |
277 this._removeAsyncCallFrames(); | |
278 } | |
279 | |
280 _removeAsyncCallFrames() { | |
281 var shouldSelectTopFrame = false; | |
282 var lastSyncCallFrameIndex = -1; | |
283 for (var i = 0; i < this.callFrames.length; ++i) { | |
284 var callFrame = this.callFrames[i]; | |
285 if (callFrame._asyncCallFrame) { | |
286 if (callFrame.isSelected()) | |
287 shouldSelectTopFrame = true; | |
288 callFrame._asyncCallFrame.element.remove(); | |
289 callFrame.element.remove(); | |
290 } else { | |
291 lastSyncCallFrameIndex = i; | |
292 } | |
293 } | |
294 this.callFrames.length = lastSyncCallFrameIndex + 1; | |
295 if (shouldSelectTopFrame) | |
296 this._selectNextVisibleCallFrame(0); | |
297 } | |
298 | |
299 /** | 336 /** |
300 * @return {boolean} | 337 * @return {boolean} |
301 */ | 338 */ |
302 _selectNextCallFrameOnStack() { | 339 _selectNextCallFrameOnStack() { |
303 var index = this._selectedCallFrameIndex(); | 340 return this._list.selectNextItem(false, true); |
304 if (index === -1) | |
305 return false; | |
306 return this._selectNextVisibleCallFrame(index + 1); | |
307 } | 341 } |
308 | 342 |
309 /** | 343 /** |
310 * @return {boolean} | 344 * @return {boolean} |
311 */ | 345 */ |
312 _selectPreviousCallFrameOnStack() { | 346 _selectPreviousCallFrameOnStack() { |
313 var index = this._selectedCallFrameIndex(); | 347 return this._list.selectPreviousItem(false, true); |
314 if (index === -1) | 348 } |
315 return false; | 349 |
316 return this._selectNextVisibleCallFrame(index - 1, true); | 350 _copyStackTrace() { |
351 var text = []; | |
352 for (var i = 0; i < this._list.length(); i++) { | |
353 var item = this._list.itemAtIndex(i); | |
354 var itemText = this._itemTitle(item); | |
355 var location = this._itemLocation(item); | |
356 if (location) { | |
357 var uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocati on(location); | |
358 itemText += ' (' + uiLocation.linkText() + ')'; | |
359 } | |
360 text.push(itemText); | |
361 } | |
362 InspectorFrontendHost.copyText(text.join('\n')); | |
317 } | 363 } |
318 | 364 |
319 /** | 365 /** |
320 * @param {number} index | |
321 * @param {boolean=} backward | |
322 * @return {boolean} | |
323 */ | |
324 _selectNextVisibleCallFrame(index, backward) { | |
325 while (0 <= index && index < this.callFrames.length) { | |
326 var callFrame = this.callFrames[index]; | |
327 if (!callFrame.isHidden() && !callFrame.isLabel() && !callFrame._asyncCall Frame) { | |
328 this._callFrameSelected(callFrame); | |
329 return true; | |
330 } | |
331 index += backward ? -1 : 1; | |
332 } | |
333 return false; | |
334 } | |
335 | |
336 /** | |
337 * @return {number} | |
338 */ | |
339 _selectedCallFrameIndex() { | |
340 if (!this._debuggerModel) | |
341 return -1; | |
342 var selectedCallFrame = this._debuggerModel.selectedCallFrame(); | |
343 if (!selectedCallFrame) | |
344 return -1; | |
345 for (var i = 0; i < this.callFrames.length; ++i) { | |
346 if (this.callFrames[i]._debuggerCallFrame === selectedCallFrame) | |
347 return i; | |
348 } | |
349 return -1; | |
350 } | |
351 | |
352 /** | |
353 * @param {!Sources.CallStackSidebarPane.CallFrame} callFrameItem | |
354 */ | |
355 _asyncCallFrameClicked(callFrameItem) { | |
356 var uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(c allFrameItem._location); | |
357 Common.Revealer.reveal(uiLocation); | |
358 } | |
359 | |
360 /** | |
361 * @param {!Sources.CallStackSidebarPane.CallFrame} selectedCallFrame | |
362 */ | |
363 _callFrameSelected(selectedCallFrame) { | |
364 selectedCallFrame.element.scrollIntoViewIfNeeded(); | |
365 var callFrame = selectedCallFrame._debuggerCallFrame; | |
366 | |
367 for (var i = 0; i < this.callFrames.length; ++i) { | |
368 var callFrameItem = this.callFrames[i]; | |
369 callFrameItem.setSelected(callFrameItem === selectedCallFrame); | |
370 if (callFrameItem.isSelected() && callFrameItem.isHidden()) | |
371 this._revealHiddenCallFrames(); | |
372 } | |
373 | |
374 var oldCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame); | |
375 if (oldCallFrame === callFrame) { | |
376 var uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation (callFrame.location()); | |
377 Common.Revealer.reveal(uiLocation); | |
378 return; | |
379 } | |
380 | |
381 UI.context.setFlavor(SDK.DebuggerModel.CallFrame, callFrame); | |
382 callFrame.debuggerModel.setSelectedCallFrame(callFrame); | |
383 } | |
384 | |
385 _copyStackTrace() { | |
386 var text = ''; | |
387 var lastCallFrame = null; | |
388 for (var i = 0; i < this.callFrames.length; ++i) { | |
389 var callFrame = this.callFrames[i]; | |
390 if (callFrame.isHidden()) | |
391 continue; | |
392 if (lastCallFrame && callFrame._asyncCallFrame !== lastCallFrame._asyncCal lFrame) | |
393 text += callFrame._asyncCallFrame.title() + '\n'; | |
394 text += callFrame.title() + ' (' + callFrame.subtitle() + ')\n'; | |
395 lastCallFrame = callFrame; | |
396 } | |
397 InspectorFrontendHost.copyText(text); | |
398 } | |
399 | |
400 /** | |
401 * @param {function(!Array.<!UI.KeyboardShortcut.Descriptor>, function(!Event= ):boolean)} registerShortcutDelegate | 366 * @param {function(!Array.<!UI.KeyboardShortcut.Descriptor>, function(!Event= ):boolean)} registerShortcutDelegate |
402 */ | 367 */ |
403 registerShortcuts(registerShortcutDelegate) { | 368 registerShortcuts(registerShortcutDelegate) { |
404 registerShortcutDelegate( | 369 registerShortcutDelegate( |
405 Components.ShortcutsScreen.SourcesPanelShortcuts.NextCallFrame, this._se lectNextCallFrameOnStack.bind(this)); | 370 Components.ShortcutsScreen.SourcesPanelShortcuts.NextCallFrame, this._se lectNextCallFrameOnStack.bind(this)); |
406 registerShortcutDelegate( | 371 registerShortcutDelegate( |
407 Components.ShortcutsScreen.SourcesPanelShortcuts.PrevCallFrame, | 372 Components.ShortcutsScreen.SourcesPanelShortcuts.PrevCallFrame, |
408 this._selectPreviousCallFrameOnStack.bind(this)); | 373 this._selectPreviousCallFrameOnStack.bind(this)); |
409 } | 374 } |
410 }; | 375 }; |
411 | 376 |
412 /** | 377 /** |
413 * @unrestricted | 378 * @typedef {{ |
379 * debuggerCallFrame: (SDK.DebuggerModel.CallFrame|undefined), | |
380 * asyncStackHeader: (string|undefined), | |
381 * runtimeCallFrame: (Protocol.Runtime.CallFrame|undefined) | |
382 * }} | |
414 */ | 383 */ |
415 Sources.CallStackSidebarPane.CallFrame = class extends Sources.UIList.Item { | 384 Sources.CallStackSidebarPane.Item; |
416 /** | |
417 * @param {string} functionName | |
418 * @param {!SDK.DebuggerModel.Location} location | |
419 * @param {!Components.Linkifier} linkifier | |
420 * @param {?SDK.DebuggerModel.CallFrame} debuggerCallFrame | |
421 * @param {!Bindings.LiveLocationPool} locationPool | |
422 * @param {!Sources.UIList.Item=} asyncCallFrame | |
423 */ | |
424 constructor(functionName, location, linkifier, debuggerCallFrame, locationPool , asyncCallFrame) { | |
425 super(UI.beautifyFunctionName(functionName), ''); | |
426 this._location = location; | |
427 this._debuggerCallFrame = debuggerCallFrame; | |
428 this._asyncCallFrame = asyncCallFrame; | |
429 Bindings.debuggerWorkspaceBinding.createCallFrameLiveLocation(location, this ._update.bind(this), locationPool); | |
430 } | |
431 | |
432 /** | |
433 * @param {!Bindings.LiveLocation} liveLocation | |
434 */ | |
435 _update(liveLocation) { | |
436 var uiLocation = liveLocation.uiLocation(); | |
437 if (!uiLocation) | |
438 return; | |
439 var text = uiLocation.linkText(); | |
440 this.setSubtitle(text.trimMiddle(30)); | |
441 this.subtitleElement.title = text; | |
442 } | |
443 }; | |
OLD | NEW |