1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * @extends {WebInspector.BreakpointsSidebarPaneBase}
8 * @implements {WebInspector.TargetManager.Observer}
10 WebInspector
.AsyncOperationsSidebarPane = function()
12 WebInspector
.BreakpointsSidebarPaneBase
.call(this, WebInspector
.UIString("Async Operation Breakpoints"));
13 this.element
.classList
.add("async-operations");
14 this._updateEmptyElement();
16 var refreshButton
= new WebInspector
.ToolbarButton(WebInspector
.UIString("Refresh"), "refresh-toolbar-item");
17 refreshButton
.addEventListener("click", this._refreshButtonClicked
.bind(this));
18 this.toolbar().appendToolbarItem(refreshButton
);
20 /** @type {!Map.<!WebInspector.Target, !Map.<number, !DebuggerAgent.AsyncOperation>>} */
21 this._asyncOperationsByTarget
= new Map();
22 /** @type {!Map.<number, !Element>} */
23 this._operationIdToElement
= new Map();
25 this._revealBlackboxedCallFrames
= false;
26 this._linkifier
= new WebInspector
.Linkifier(new WebInspector
.Linkifier
.DefaultFormatter(30));
28 this._popoverHelper
= new WebInspector
.PopoverHelper(this.element
, this._getPopoverAnchor
.bind(this), this._showPopover
.bind(this));
29 this._popoverHelper
.setTimeout(250, 250);
30 this.element
.addEventListener("click", this._hidePopover
.bind(this), true);
32 WebInspector
.targetManager
.addModelListener(WebInspector
.DebuggerModel
, WebInspector
.DebuggerModel
.Events
.AsyncOperationStarted
, this._onAsyncOperationStarted
, this);
33 WebInspector
.targetManager
.addModelListener(WebInspector
.DebuggerModel
, WebInspector
.DebuggerModel
.Events
.AsyncOperationCompleted
, this._onAsyncOperationCompleted
, this);
34 WebInspector
.targetManager
.addModelListener(WebInspector
.DebuggerModel
, WebInspector
.DebuggerModel
.Events
.DebuggerResumed
, this._debuggerResumed
, this);
35 WebInspector
.targetManager
.addModelListener(WebInspector
.DebuggerModel
, WebInspector
.DebuggerModel
.Events
.GlobalObjectCleared
, this._debuggerReset
, this);
36 WebInspector
.context
.addFlavorChangeListener(WebInspector
.Target
, this._targetChanged
, this);
38 WebInspector
.moduleSetting("skipStackFramesPattern").addChangeListener(this._refresh
, this);
39 WebInspector
.moduleSetting("enableAsyncStackTraces").addChangeListener(this._asyncStackTracesStateChanged
, this);
41 WebInspector
.targetManager
.observeTargets(this);
44 WebInspector
.AsyncOperationsSidebarPane
.prototype = {
45 _operationIdSymbol
: Symbol("operationId"),
46 _checkedSymbol
: Symbol("checked"),
50 * @param {!WebInspector.Target} target
52 targetAdded: function(target
)
58 * @param {!WebInspector.Target} target
60 targetRemoved: function(target
)
62 this._asyncOperationsByTarget
.delete(target
);
63 if (this._target
=== target
) {
70 * @param {!WebInspector.Event} event
72 _targetChanged: function(event
)
74 var target
= /** @type {!WebInspector.Target} */ (event
.data
);
75 if (this._target
=== target
)
77 this._target
= target
;
82 * @param {?WebInspector.Target} target
83 * @param {number} operationId
84 * @return {?DebuggerAgent.AsyncOperation}
86 operationById: function(target
, operationId
)
90 var operationsMap
= this._asyncOperationsByTarget
.get(target
);
93 return operationsMap
.get(operationId
) || null;
96 _asyncStackTracesStateChanged: function()
98 var enabled
= WebInspector
.moduleSetting("enableAsyncStackTraces").get();
100 this._target
= WebInspector
.context
.flavor(WebInspector
.Target
);
101 } else if (this._target
) {
102 this._asyncOperationsByTarget
.delete(this._target
);
105 this._updateEmptyElement();
109 _updateEmptyElement: function()
111 var enabled
= WebInspector
.moduleSetting("enableAsyncStackTraces").get();
113 this.emptyElement
.textContent
= WebInspector
.UIString("No Async Operations");
115 this.emptyElement
.textContent
= WebInspector
.UIString("Async stack traces are disabled.");
116 this.emptyElement
.createTextChild(" ");
117 var enableLink
= this.emptyElement
.createChild("span", "link");
118 enableLink
.textContent
= WebInspector
.UIString("Enable");
119 enableLink
.addEventListener("click", enableAsyncStackTraces
, true);
122 function enableAsyncStackTraces()
124 WebInspector
.moduleSetting("enableAsyncStackTraces").set(true);
131 if (!this._target
&& WebInspector
.moduleSetting("enableAsyncStackTraces").get()) {
132 this._target
= WebInspector
.context
.flavor(WebInspector
.Target
);
150 * @param {!WebInspector.Target} target
152 revealHiddenCallFrames: function(target
)
154 if (this._target
!== target
|| this._revealBlackboxedCallFrames
)
156 this._revealBlackboxedCallFrames
= true;
161 * @param {number} operationId
163 highlightBreakpoint: function(operationId
)
165 this._breakpointHitId
= operationId
;
166 var element
= this._operationIdToElement
.get(operationId
);
170 element
.classList
.add("breakpoint-hit");
173 clearBreakpointHighlight: function()
175 if (!this._breakpointHitId
)
177 var element
= this._operationIdToElement
.get(this._breakpointHitId
);
179 element
.classList
.remove("breakpoint-hit");
180 delete this._breakpointHitId
;
184 * @param {!WebInspector.Event} event
186 _debuggerResumed: function(event
)
188 var target
= /** @type {!WebInspector.Target} */ (event
.target
.target());
189 if (this._target
!== target
|| !this._revealBlackboxedCallFrames
)
191 this._revealBlackboxedCallFrames
= false;
196 * @param {!WebInspector.Event} event
198 _debuggerReset: function(event
)
200 var target
= /** @type {!WebInspector.Target} */ (event
.target
.target());
201 this._asyncOperationsByTarget
.delete(target
);
202 if (this._target
=== target
)
207 * @param {!WebInspector.Event} event
209 _refreshButtonClicked: function(event
)
213 var debuggerModel
= WebInspector
.DebuggerModel
.fromTarget(this._target
);
215 debuggerModel
.flushAsyncOperationEvents();
219 * @param {!WebInspector.Event} event
221 _onAsyncOperationStarted: function(event
)
223 var target
= /** @type {!WebInspector.Target} */ (event
.target
.target());
224 var operation
= /** @type {!DebuggerAgent.AsyncOperation} */ (event
.data
);
226 var operationsMap
= this._asyncOperationsByTarget
.get(target
);
227 if (!operationsMap
) {
228 operationsMap
= new Map();
229 this._asyncOperationsByTarget
.set(target
, operationsMap
)
231 operationsMap
.set(operation
.id
, operation
);
233 if (this._target
=== target
)
234 this._createAsyncOperationItem(operation
);
238 * @param {!WebInspector.Event} event
240 _onAsyncOperationCompleted: function(event
)
242 var target
= /** @type {!WebInspector.Target} */ (event
.target
.target());
243 var operationId
= /** @type {number} */ (event
.data
);
245 var operationsMap
= this._asyncOperationsByTarget
.get(target
);
247 operationsMap
.delete(operationId
);
249 if (this._target
=== target
) {
250 var element
= this._operationIdToElement
.get(operationId
);
252 this.removeListElement(element
);
253 this._operationIdToElement
.delete(operationId
);
254 if (!this._operationIdToElement
.size
)
264 var operationsMap
= this._asyncOperationsByTarget
.get(this._target
);
265 if (!operationsMap
|| !operationsMap
.size
)
268 // The for..of loop iterates in insertion order.
269 for (var pair
of operationsMap
) {
270 var operation
= /** @type {!DebuggerAgent.AsyncOperation} */ (pair
[1]);
271 this._createAsyncOperationItem(operation
);
276 * @param {!DebuggerAgent.AsyncOperation} operation
278 _createAsyncOperationItem: function(operation
)
280 var element
= createElementWithClass("li", "async-operation");
282 var title
= operation
.description
|| WebInspector
.UIString("Async Operation");
283 var label
= createCheckboxLabel(title
, operation
[this._checkedSymbol
]);
284 label
.checkboxElement
.addEventListener("click", this._checkboxClicked
.bind(this, operation
.id
), false);
285 element
.appendChild(label
);
286 var debuggerModel
= WebInspector
.DebuggerModel
.fromTarget(this._target
);
287 var callFrame
= WebInspector
.DebuggerPresentationUtils
.callFrameAnchorFromStackTrace(debuggerModel
, operation
.stackTrace
, operation
.asyncStackTrace
, this._revealBlackboxedCallFrames
);
289 element
.createChild("div").appendChild(this._linkifier
.linkifyConsoleCallFrame(this._target
, callFrame
));
291 element
[this._operationIdSymbol
] = operation
.id
;
292 this._operationIdToElement
.set(operation
.id
, element
);
293 this.addListElement(element
, this.listElement
.firstChild
);
295 if (operation
.id
=== this._breakpointHitId
) {
296 element
.classList
.add("breakpoint-hit");
302 * @param {number} operationId
303 * @param {!Event} event
305 _checkboxClicked: function(operationId
, event
)
307 var operation
= this.operationById(this._target
, operationId
);
310 var debuggerModel
= WebInspector
.DebuggerModel
.fromTarget(this._target
);
313 operation
[this._checkedSymbol
] = event
.target
.checked
;
314 if (event
.target
.checked
)
315 debuggerModel
.setAsyncOperationBreakpoint(operationId
);
317 debuggerModel
.removeAsyncOperationBreakpoint(operationId
);
324 this._operationIdToElement
.clear();
325 this._linkifier
.reset();
328 _hidePopover: function()
330 this._popoverHelper
.hidePopover();
334 * @param {!Element} element
335 * @param {!Event} event
336 * @return {!Element|!AnchorBox|undefined}
338 _getPopoverAnchor: function(element
, event
)
340 var anchor
= /** @type {?Element} */ (element
.enclosingNodeOrSelfWithNodeName("a"));
343 var operation
= this._operationForPopover(anchor
);
344 return operation
? anchor
: undefined;
348 * @param {!Element} anchor
349 * @param {!WebInspector.Popover} popover
351 _showPopover: function(anchor
, popover
)
353 var operation
= this._operationForPopover(anchor
);
356 var content
= WebInspector
.DOMPresentationUtils
.buildStackTracePreviewContents(this._target
, this._linkifier
, operation
.stackTrace
, operation
.asyncStackTrace
);
357 popover
.setCanShrink(true);
358 popover
.showForAnchor(content
, anchor
);
362 * @param {!Element} element
363 * @return {?DebuggerAgent.AsyncOperation}
365 _operationForPopover: function(element
)
367 var asyncOperations
= this._target
&& this._asyncOperationsByTarget
.get(this._target
);
368 if (!asyncOperations
)
370 var anchor
= element
.enclosingNodeOrSelfWithClass("async-operation");
373 var operationId
= anchor
[this._operationIdSymbol
];
374 var operation
= operationId
&& asyncOperations
.get(operationId
);
375 if (!operation
|| !operation
.stackTrace
)
380 __proto__
: WebInspector
.BreakpointsSidebarPaneBase
.prototype