| Index: third_party/WebKit/Source/devtools/front_end/sources/ThreadsSidebarPane.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/sources/ThreadsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/ThreadsSidebarPane.js
|
| index 2cfed689bcb276bd3ed0b734ab604dd455bf2104..58d8fc8d75a11051104bd4be131ffaec4c41c18a 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/sources/ThreadsSidebarPane.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/sources/ThreadsSidebarPane.js
|
| @@ -9,12 +9,14 @@ WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox {
|
| constructor() {
|
| super();
|
|
|
| - /** @type {!Map.<!WebInspector.DebuggerModel, !WebInspector.UIList.Item>} */
|
| - this._debuggerModelToListItems = new Map();
|
| - /** @type {!Map.<!WebInspector.UIList.Item, !WebInspector.Target>} */
|
| - this._listItemsToTargets = new Map();
|
| /** @type {?WebInspector.UIList.Item} */
|
| this._selectedListItem = null;
|
| + /** @type {!Map<!WebInspector.PendingTarget, !WebInspector.UIList.Item>} */
|
| + this._pendingToListItem = new Map();
|
| + /** @type {!Map<!WebInspector.Target, !WebInspector.PendingTarget>} */
|
| + this._targetToPending = new Map();
|
| + /** @type {?WebInspector.PendingTarget} */
|
| + this._mainTargetPending = null;
|
| this.threadList = new WebInspector.UIList();
|
| this.threadList.show(this.element);
|
| WebInspector.targetManager.addModelListener(
|
| @@ -29,28 +31,113 @@ WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox {
|
| WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._targetChanged, this);
|
| WebInspector.targetManager.addEventListener(
|
| WebInspector.TargetManager.Events.NameChanged, this._targetNameChanged, this);
|
| + WebInspector.targetManager.addModelListener(WebInspector.SubTargetsManager, WebInspector.SubTargetsManager.Events.PendingTargetAdded, this._addTargetItem, this);
|
| + WebInspector.targetManager.addModelListener(WebInspector.SubTargetsManager, WebInspector.SubTargetsManager.Events.PendingTargetRemoved, this._pendingTargetRemoved, this);
|
| + WebInspector.targetManager.addModelListener(WebInspector.SubTargetsManager, WebInspector.SubTargetsManager.Events.PendingTargetAttached, this._addTargetItem, this);
|
| + WebInspector.targetManager.addModelListener(WebInspector.SubTargetsManager, WebInspector.SubTargetsManager.Events.PendingTargetDetached, this._targetDetached, this);
|
| WebInspector.targetManager.observeTargets(this);
|
| +
|
| + var pendingTargets = [];
|
| + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Target))
|
| + pendingTargets = pendingTargets.concat(WebInspector.SubTargetsManager.fromTarget(target).pendingTargets());
|
| +
|
| + pendingTargets
|
| + .sort(WebInspector.ThreadsSidebarPane._pendingTargetsComparator)
|
| + .forEach(pendingTarget => this._addListItem(pendingTarget));
|
| }
|
|
|
| /**
|
| - * @override
|
| - * @param {!WebInspector.Target} target
|
| + * @return {boolean}
|
| */
|
| - targetAdded(target) {
|
| - var debuggerModel = WebInspector.DebuggerModel.fromTarget(target);
|
| - if (!debuggerModel)
|
| + static shouldBeShown() {
|
| + if (WebInspector.targetManager.targets(WebInspector.Target.Capability.JS).length > 1)
|
| + return true;
|
| + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Target)) {
|
| + var pendingTargets = WebInspector.SubTargetsManager.fromTarget(target).pendingTargets();
|
| + if (pendingTargets.some(pendingTarget => pendingTarget.canConnect()))
|
| + return true;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + /**
|
| + * Sorts show tha connected targets appear first, followed by pending subtargets.
|
| + *
|
| + * @param {!WebInspector.PendingTarget} c1
|
| + * @param {!WebInspector.PendingTarget} c2
|
| + * @return {number}
|
| + */
|
| + static _pendingTargetsComparator(c1, c2)
|
| + {
|
| + var t1 = c1.target();
|
| + var t2 = c2.target();
|
| + var name1 = t1 ? t1.name() : c1.name();
|
| + var name2 = t2 ? t2.name() : c2.name();
|
| + if (!!t1 === !!t2) { // Either both are connected or disconnected
|
| + return name1.toLowerCase().localeCompare(name2.toLowerCase());
|
| + } else if (t1) {
|
| + return -1;
|
| + }
|
| + return 1;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _addTargetItem(event) {
|
| + this._addListItem(/** @type {!WebInspector.PendingTarget} */ (event.data));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _pendingTargetRemoved(event) {
|
| + this._removeListItem(/** @type {!WebInspector.PendingTarget} */ (event.data));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _targetDetached(event) {
|
| + this._targetRemoved(/** @type {!WebInspector.PendingTarget} */ (event.data));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.PendingTarget} pendingTarget
|
| + */
|
| + _addListItem(pendingTarget) {
|
| + var target = pendingTarget.target();
|
| + if (!pendingTarget.canConnect() && !(target && target.hasJSCapability()))
|
| return;
|
|
|
| - var listItem = new WebInspector.UIList.Item(this._titleForTarget(target), '');
|
| - listItem.element.addEventListener('click', this._onListItemClick.bind(this, listItem), false);
|
| + var listItem = this._pendingToListItem.get(pendingTarget);
|
| + if (!listItem) {
|
| + listItem = new WebInspector.UIList.Item('', '', false);
|
| + listItem[WebInspector.ThreadsSidebarPane._pendingTargetSymbol] = pendingTarget;
|
| + listItem[WebInspector.ThreadsSidebarPane._targetSymbol] = target;
|
| + this._pendingToListItem.set(pendingTarget, listItem);
|
| + this.threadList.addItem(listItem);
|
| + listItem.element.addEventListener('click', this._onListItemClick.bind(this, listItem), false);
|
| + }
|
| + this._updateListItem(listItem, pendingTarget);
|
| + this._updateDebuggerState(pendingTarget);
|
| var currentTarget = WebInspector.context.flavor(WebInspector.Target);
|
| if (currentTarget === target)
|
| this._selectListItem(listItem);
|
| + if (target)
|
| + this._targetToPending.set(target, pendingTarget);
|
| + }
|
|
|
| - this._debuggerModelToListItems.set(debuggerModel, listItem);
|
| - this._listItemsToTargets.set(listItem, target);
|
| - this.threadList.addItem(listItem);
|
| - this._updateDebuggerState(debuggerModel);
|
| + /**
|
| + * @override
|
| + * @param {!WebInspector.Target} target
|
| + */
|
| + targetAdded(target) {
|
| + if (target !== WebInspector.targetManager.mainTarget())
|
| + return;
|
| + console.assert(!this._mainTargetPending);
|
| + this._mainTargetPending = new WebInspector.ThreadsSidebarPane.MainTargetConnection(target);
|
| + this._addListItem(this._mainTargetPending);
|
| }
|
|
|
| /**
|
| @@ -58,13 +145,15 @@ WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox {
|
| * @param {!WebInspector.Target} target
|
| */
|
| targetRemoved(target) {
|
| - var debuggerModel = WebInspector.DebuggerModel.fromTarget(target);
|
| - if (!debuggerModel)
|
| - return;
|
| - var listItem = this._debuggerModelToListItems.remove(debuggerModel);
|
| - if (listItem) {
|
| - this._listItemsToTargets.remove(listItem);
|
| - this.threadList.removeItem(listItem);
|
| + var subtargetManager = WebInspector.SubTargetsManager.fromTarget(target);
|
| + var pendingTargets = subtargetManager ? subtargetManager.pendingTargets() : [];
|
| + for (var pendingTarget of pendingTargets) {
|
| + if (pendingTarget.target())
|
| + this._targetRemoved(pendingTarget);
|
| + }
|
| + if (target === WebInspector.targetManager.mainTarget() && this._mainTargetPending) {
|
| + this._targetRemoved(this._mainTargetPending);
|
| + this._mainTargetPending = null;
|
| }
|
| }
|
|
|
| @@ -75,7 +164,7 @@ WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox {
|
| var target = /** @type {!WebInspector.Target} */ (event.data);
|
| var listItem = this._listItemForTarget(target);
|
| if (listItem)
|
| - listItem.setTitle(this._titleForTarget(target));
|
| + listItem.setTitle(this._titleForPending(this._targetToPending.get(target)));
|
| }
|
|
|
| /**
|
| @@ -92,17 +181,18 @@ WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox {
|
| * @return {?WebInspector.UIList.Item}
|
| */
|
| _listItemForTarget(target) {
|
| - var debuggerModel = WebInspector.DebuggerModel.fromTarget(target);
|
| - if (!debuggerModel)
|
| - return null;
|
| - return this._debuggerModelToListItems.get(debuggerModel) || null;
|
| + var pendingTarget = this._targetToPending.get(target);
|
| + return this._pendingToListItem.get(pendingTarget) || null;
|
| }
|
|
|
| /**
|
| - * @param {!WebInspector.Target} target
|
| + * @param {!WebInspector.PendingTarget} pendingTarget
|
| * @return {string}
|
| */
|
| - _titleForTarget(target) {
|
| + _titleForPending(pendingTarget) {
|
| + var target = pendingTarget.target();
|
| + if (!target)
|
| + return pendingTarget.name();
|
| var executionContext = target.runtimeModel.defaultExecutionContext();
|
| return executionContext && executionContext.label() ? executionContext.label() : target.name();
|
| }
|
| @@ -112,7 +202,8 @@ WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox {
|
| */
|
| _onDebuggerStateChanged(event) {
|
| var debuggerModel = /** @type {!WebInspector.DebuggerModel} */ (event.target);
|
| - this._updateDebuggerState(debuggerModel);
|
| + var pendingTarget = this._targetToPending.get(debuggerModel.target());
|
| + this._updateDebuggerState(pendingTarget);
|
| }
|
|
|
| /**
|
| @@ -122,19 +213,21 @@ WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox {
|
| var executionContext = /** @type {!WebInspector.ExecutionContext} */ (event.data);
|
| if (!executionContext.isDefault)
|
| return;
|
| - var debuggerModel =
|
| - /** @type {!WebInspector.DebuggerModel} */ (WebInspector.DebuggerModel.fromTarget(executionContext.target()));
|
| - var listItem = this._debuggerModelToListItems.get(debuggerModel);
|
| + var pendingTarget = this._targetToPending.get(executionContext.target());
|
| + var listItem = this._pendingToListItem.get(pendingTarget);
|
| if (listItem && executionContext.label())
|
| listItem.setTitle(executionContext.label());
|
| }
|
|
|
| /**
|
| - * @param {!WebInspector.DebuggerModel} debuggerModel
|
| + * @param {!WebInspector.PendingTarget} pendingTarget
|
| */
|
| - _updateDebuggerState(debuggerModel) {
|
| - var listItem = this._debuggerModelToListItems.get(debuggerModel);
|
| - listItem.setSubtitle(WebInspector.UIString(debuggerModel.isPaused() ? 'paused' : ''));
|
| + _updateDebuggerState(pendingTarget) {
|
| + var listItem = this._pendingToListItem.get(pendingTarget);
|
| + var target = pendingTarget.target();
|
| + var debuggerModel = target && WebInspector.DebuggerModel.fromTarget(target);
|
| + var isPaused = !!debuggerModel && debuggerModel.isPaused();
|
| + listItem.setSubtitle(WebInspector.UIString(isPaused ? 'paused' : ''));
|
| }
|
|
|
| /**
|
| @@ -155,7 +248,107 @@ WebInspector.ThreadsSidebarPane = class extends WebInspector.VBox {
|
| * @param {!WebInspector.UIList.Item} listItem
|
| */
|
| _onListItemClick(listItem) {
|
| - WebInspector.context.setFlavor(WebInspector.Target, this._listItemsToTargets.get(listItem));
|
| + var pendingTarget = listItem[WebInspector.ThreadsSidebarPane._pendingTargetSymbol];
|
| + var target = pendingTarget.target();
|
| + if (!target)
|
| + return;
|
| + WebInspector.context.setFlavor(WebInspector.Target, target);
|
| listItem.element.scrollIntoViewIfNeeded();
|
| }
|
| +
|
| + /**
|
| + * @param {!WebInspector.UIList.Item} item
|
| + * @param {!WebInspector.PendingTarget} pendingTarget
|
| + */
|
| + _updateListItem(item, pendingTarget) {
|
| + item.setTitle(this._titleForPending(pendingTarget));
|
| + item.setSubtitle('');
|
| + var target = pendingTarget.target();
|
| + var action = null;
|
| + var actionLabel = null;
|
| + if (pendingTarget.canConnect()) {
|
| + actionLabel = target ? 'Disconnect' : 'Connect';
|
| + action = this._toggleConnection.bind(this, pendingTarget);
|
| + }
|
| + item.setAction(actionLabel, action);
|
| + item.setDimmed(!target);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Target} target
|
| + */
|
| + _selectNewlyAddedTarget(target) {
|
| + setTimeout(() => WebInspector.context.setFlavor(WebInspector.Target, target));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.PendingTarget} pendingTarget
|
| + * @return {!Promise}
|
| + */
|
| + _toggleConnection(pendingTarget) {
|
| + var target = pendingTarget.target();
|
| + if (target)
|
| + return pendingTarget.detach();
|
| + else
|
| + return pendingTarget.attach().then(target => this._selectNewlyAddedTarget(target));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.PendingTarget} pendingTarget
|
| + */
|
| + _targetRemoved(pendingTarget) {
|
| + var item = this._pendingToListItem.get(pendingTarget);
|
| + if (!item) // Not all targets are represented in the UI.
|
| + return;
|
| + var target = item[WebInspector.ThreadsSidebarPane._targetSymbol];
|
| + item[WebInspector.ThreadsSidebarPane._targetSymbol] = null;
|
| + this._targetToPending.remove(target);
|
| + if (pendingTarget.canConnect())
|
| + this._updateListItem(item, pendingTarget);
|
| + else
|
| + this._removeListItem(pendingTarget);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.PendingTarget} pendingTarget
|
| + */
|
| + _removeListItem(pendingTarget) {
|
| + var item = this._pendingToListItem.get(pendingTarget);
|
| + if (!item)
|
| + return;
|
| + this.threadList.removeItem(item);
|
| + this._pendingToListItem.delete(pendingTarget);
|
| + }
|
| +};
|
| +
|
| +WebInspector.ThreadsSidebarPane._pendingTargetSymbol = Symbol('_subtargetSymbol');
|
| +WebInspector.ThreadsSidebarPane._targetSymbol = Symbol('_targetSymbol');
|
| +
|
| +/**
|
| + * @unrestricted
|
| + */
|
| +WebInspector.ThreadsSidebarPane.MainTargetConnection = class extends WebInspector.PendingTarget {
|
| + /**
|
| + * @param {!WebInspector.Target} target
|
| + */
|
| + constructor(target) {
|
| + super('main-target-list-node-' + target.id(), target.title, false, null);
|
| + this._target = target;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {!WebInspector.Target}
|
| + */
|
| + target() {
|
| + return this._target;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @return {string}
|
| + */
|
| + name() {
|
| + return this._target.name();
|
| + }
|
| };
|
|
|