Chromium Code Reviews| 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 |