mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-10 05:35:05 +08:00
Move and rename files. NOAUTOREVERT=true NOPRESUBMIT=true NOTREECHECKS=true Bug: 768828 TBR=darin@chromium.org NOTRY=true Change-Id: I66d3b155808bc5bdbf237b80208e1e552bcf7f28 Reviewed-on: https://chromium-review.googlesource.com/1001153 Reviewed-by: Blink Reformat <blink-reformat@chromium.org> Commit-Queue: Blink Reformat <blink-reformat@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#549061} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 0aee4434a4dba42a42abaea9bfbc0cd196a63bc1
213 lines
6.2 KiB
JavaScript
213 lines
6.2 KiB
JavaScript
// Copyright 2018 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
/**
|
|
* @implements {SDK.SDKModelObserver<!SDK.RuntimeModel>}
|
|
* @implements {UI.ListDelegate<!Profiler.IsolateSelector.ListItem>}
|
|
*/
|
|
Profiler.IsolateSelector = class extends UI.VBox {
|
|
constructor() {
|
|
super(true);
|
|
|
|
/** @type {!UI.ListModel<!Profiler.IsolateSelector.ListItem>} */
|
|
this._items = new UI.ListModel();
|
|
/** @type {!UI.ListControl<!Profiler.IsolateSelector.ListItem>} */
|
|
this._list = new UI.ListControl(this._items, this, UI.ListMode.NonViewport);
|
|
this.contentElement.appendChild(this._list.element);
|
|
|
|
this.registerRequiredCSS('profiler/profileLauncherView.css');
|
|
/** @type {!Map<!SDK.RuntimeModel, !Promise<string>>} */
|
|
this._isolateByModel = new Map();
|
|
/** @type {!Map<string, !Profiler.IsolateSelector.ListItem>} */
|
|
this._itemByIsolate = new Map();
|
|
|
|
SDK.targetManager.observeModels(SDK.RuntimeModel, this);
|
|
SDK.targetManager.addEventListener(SDK.TargetManager.Events.NameChanged, this._targetChanged, this);
|
|
SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged, this._targetChanged, this);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!SDK.RuntimeModel} model
|
|
*/
|
|
modelAdded(model) {
|
|
this._modelAdded(model);
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.RuntimeModel} model
|
|
*/
|
|
async _modelAdded(model) {
|
|
const isolatePromise = model.isolateId();
|
|
this._isolateByModel.set(model, isolatePromise);
|
|
const isolate = await isolatePromise;
|
|
let item = this._itemByIsolate.get(isolate);
|
|
if (!item) {
|
|
item = new Profiler.IsolateSelector.ListItem(model);
|
|
const index = model.target() === SDK.targetManager.mainTarget() ? 0 : this._items.length;
|
|
this._items.insert(index, item);
|
|
this._itemByIsolate.set(isolate, item);
|
|
if (this._items.length === 1)
|
|
this._list.selectItem(item);
|
|
} else {
|
|
item.addModel(model);
|
|
}
|
|
this._update();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!SDK.RuntimeModel} model
|
|
*/
|
|
modelRemoved(model) {
|
|
this._modelRemoved(model);
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.RuntimeModel} model
|
|
*/
|
|
async _modelRemoved(model) {
|
|
const isolate = await this._isolateByModel.get(model);
|
|
this._isolateByModel.delete(model);
|
|
const item = this._itemByIsolate.get(isolate);
|
|
item.removeModel(model);
|
|
if (!item.models().length) {
|
|
this._items.remove(this._items.indexOf(item));
|
|
this._itemByIsolate.delete(isolate);
|
|
}
|
|
this._update();
|
|
}
|
|
|
|
/**
|
|
* @param {!Common.Event} event
|
|
*/
|
|
async _targetChanged(event) {
|
|
const target = /** @type {!SDK.Target} */ (event.data);
|
|
const model = target.model(SDK.RuntimeModel);
|
|
const isolate = model && await this._isolateByModel.get(model);
|
|
const item = isolate && this._itemByIsolate.get(isolate);
|
|
if (item)
|
|
item.updateTitle();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!Profiler.IsolateSelector.ListItem} item
|
|
* @return {!Element}
|
|
*/
|
|
createElementForItem(item) {
|
|
return item.element;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!Profiler.IsolateSelector.ListItem} item
|
|
* @return {number}
|
|
*/
|
|
heightForItem(item) {
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!Profiler.IsolateSelector.ListItem} item
|
|
* @return {boolean}
|
|
*/
|
|
isItemSelectable(item) {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {?Profiler.IsolateSelector.ListItem} from
|
|
* @param {?Profiler.IsolateSelector.ListItem} to
|
|
* @param {?Element} fromElement
|
|
* @param {?Element} toElement
|
|
*/
|
|
selectedItemChanged(from, to, fromElement, toElement) {
|
|
if (fromElement)
|
|
fromElement.classList.remove('selected');
|
|
if (toElement)
|
|
toElement.classList.add('selected');
|
|
const model = to && to.models()[0];
|
|
UI.context.setFlavor(SDK.HeapProfilerModel, model && model.heapProfilerModel());
|
|
UI.context.setFlavor(SDK.CPUProfilerModel, model && model.target().model(SDK.CPUProfilerModel));
|
|
}
|
|
|
|
_update() {
|
|
this._list.invalidateRange(0, this._items.length);
|
|
}
|
|
};
|
|
|
|
Profiler.IsolateSelector.ListItem = class {
|
|
/**
|
|
* @param {!SDK.RuntimeModel} model
|
|
*/
|
|
constructor(model) {
|
|
/** @type {!Set<!SDK.RuntimeModel>} */
|
|
this._models = new Set([model]);
|
|
this.element = createElementWithClass('div', 'profile-isolate-item hbox');
|
|
this._heapDiv = this.element.createChild('div', 'profile-isolate-item-heap');
|
|
this._nameDiv = this.element.createChild('div', 'profile-isolate-item-name');
|
|
this._updateTimer = null;
|
|
this.updateTitle();
|
|
this._updateStats();
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.RuntimeModel} model
|
|
*/
|
|
addModel(model) {
|
|
this._models.add(model);
|
|
this.updateTitle();
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.RuntimeModel} model
|
|
*/
|
|
removeModel(model) {
|
|
this._models.delete(model);
|
|
this.updateTitle();
|
|
if (this._models.size)
|
|
return;
|
|
clearTimeout(this._updateTimer);
|
|
}
|
|
|
|
/**
|
|
* @return {!Array<!SDK.RuntimeModel>}
|
|
*/
|
|
models() {
|
|
return Array.from(this._models);
|
|
}
|
|
|
|
async _updateStats() {
|
|
const heapStats = await this._models.values().next().value.heapUsage();
|
|
if (!heapStats)
|
|
return;
|
|
this._heapDiv.textContent =
|
|
`${Number.bytesToString(heapStats.usedSize)} / ${Number.bytesToString(heapStats.totalSize)}`;
|
|
const heapStatsUpdateIntervalMs = 2000;
|
|
this._updateTimer = setTimeout(() => this._updateStats(), heapStatsUpdateIntervalMs);
|
|
}
|
|
|
|
updateTitle() {
|
|
/** @type {!Map<string, number>} */
|
|
const modelCountByName = new Map();
|
|
for (const model of this._models.values()) {
|
|
const target = model.target();
|
|
const name = SDK.targetManager.mainTarget() !== target ? target.name() : '';
|
|
const parsedURL = new Common.ParsedURL(target.inspectedURL());
|
|
const domain = parsedURL.isValid ? parsedURL.domain() : '';
|
|
const title = target.decorateLabel(domain && name ? `${domain}: ${name}` : name || domain || ls`(empty)`);
|
|
modelCountByName.set(title, (modelCountByName.get(title) || 0) + 1);
|
|
}
|
|
this._nameDiv.removeChildren();
|
|
for (const [name, count] of modelCountByName) {
|
|
const lineDiv = this._nameDiv.createChild('div');
|
|
const title = count > 1 ? `${name} (${count})` : name;
|
|
lineDiv.textContent = title;
|
|
lineDiv.setAttribute('title', title);
|
|
}
|
|
}
|
|
};
|