mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-10 13:44:39 +08:00
The unrestricted annotation is Closure-specific and can be removed. This patch removes all comments with only the unrestricted annotation in them. R=szuend@chromium.org No-Presubmit: True Bug: 1011811 Change-Id: Iba0723644f53f5307c3077d341271af86becc32a Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2569758 Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org> Auto-Submit: Tim van der Lippe <tvanderlippe@chromium.org>
144 lines
3.1 KiB
JavaScript
144 lines
3.1 KiB
JavaScript
// Copyright 2016 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.
|
|
|
|
import {Target} from './SDKModel.js'; // eslint-disable-line no-unused-vars
|
|
|
|
export class ProfileNode {
|
|
/**
|
|
* @param {!Protocol.Runtime.CallFrame} callFrame
|
|
*/
|
|
constructor(callFrame) {
|
|
/** @type {!Protocol.Runtime.CallFrame} */
|
|
this.callFrame = callFrame;
|
|
/** @type {string} */
|
|
this.callUID = `${callFrame.functionName}@${callFrame.scriptId}:${callFrame.lineNumber}:${callFrame.columnNumber}`;
|
|
/** @type {number} */
|
|
this.self = 0;
|
|
/** @type {number} */
|
|
this.total = 0;
|
|
/** @type {number} */
|
|
this.id = 0;
|
|
/** @type {?ProfileNode} */
|
|
this.parent = null;
|
|
/** @type {!Array<!ProfileNode>} */
|
|
this.children = [];
|
|
/** @type {number} */
|
|
this.depth;
|
|
/** @type {?string} */
|
|
this.deoptReason;
|
|
}
|
|
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
get functionName() {
|
|
return this.callFrame.functionName;
|
|
}
|
|
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
get scriptId() {
|
|
return this.callFrame.scriptId;
|
|
}
|
|
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
get url() {
|
|
return this.callFrame.url;
|
|
}
|
|
|
|
/**
|
|
* @return {number}
|
|
*/
|
|
get lineNumber() {
|
|
return this.callFrame.lineNumber;
|
|
}
|
|
|
|
/**
|
|
* @return {number}
|
|
*/
|
|
get columnNumber() {
|
|
return this.callFrame.columnNumber;
|
|
}
|
|
}
|
|
|
|
export class ProfileTreeModel {
|
|
/**
|
|
* @param {?Target=} target
|
|
*/
|
|
constructor(target) {
|
|
this._target = target || null;
|
|
/** @type {!ProfileNode} */
|
|
this.root;
|
|
/** @type {number} */
|
|
this.total;
|
|
/** @type {number} */
|
|
this.maxDepth;
|
|
}
|
|
|
|
/**
|
|
* @param {!ProfileNode} root
|
|
* @protected
|
|
*/
|
|
initialize(root) {
|
|
this.root = root;
|
|
this._assignDepthsAndParents();
|
|
this.total = this._calculateTotals(this.root);
|
|
}
|
|
|
|
_assignDepthsAndParents() {
|
|
const root = this.root;
|
|
root.depth = -1;
|
|
root.parent = null;
|
|
this.maxDepth = 0;
|
|
const nodesToTraverse = [root];
|
|
while (nodesToTraverse.length) {
|
|
const parent = /** @type {!ProfileNode} */ (nodesToTraverse.pop());
|
|
const depth = parent.depth + 1;
|
|
if (depth > this.maxDepth) {
|
|
this.maxDepth = depth;
|
|
}
|
|
const children = parent.children;
|
|
for (const child of children) {
|
|
child.depth = depth;
|
|
child.parent = parent;
|
|
if (child.children.length) {
|
|
nodesToTraverse.push(child);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {!ProfileNode} root
|
|
* @return {number}
|
|
*/
|
|
_calculateTotals(root) {
|
|
const nodesToTraverse = [root];
|
|
const dfsList = [];
|
|
while (nodesToTraverse.length) {
|
|
const node = /** @type {!ProfileNode} */ (nodesToTraverse.pop());
|
|
node.total = node.self;
|
|
dfsList.push(node);
|
|
nodesToTraverse.push(...node.children);
|
|
}
|
|
while (dfsList.length > 1) {
|
|
const node = /** @type {!ProfileNode} */ (dfsList.pop());
|
|
if (node.parent) {
|
|
node.parent.total += node.total;
|
|
}
|
|
}
|
|
return root.total;
|
|
}
|
|
|
|
/**
|
|
* @return {?Target}
|
|
*/
|
|
target() {
|
|
return this._target;
|
|
}
|
|
}
|