UNPKG

prepack

Version:

Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.

208 lines (159 loc) 5.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ResidualHeapGraphGenerator = void 0; var _invariant = _interopRequireDefault(require("../invariant.js")); var _index = require("../values/index.js"); var _HeapInspector = require("../utils/HeapInspector.js"); var _ResidualHeapVisitor = require("./ResidualHeapVisitor.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ /* strict-local */ /** * Generate a visualizable objects graph for Prepack heap. */ class ResidualHeapGraphGenerator extends _ResidualHeapVisitor.ResidualHeapVisitor { constructor(realm, logger, modules, additionalFunctionValuesAndEffects, valueIdentifiers, valueToEdgeRecord) { super(realm, logger, modules, additionalFunctionValuesAndEffects); this._valueToEdgeRecord = valueToEdgeRecord; this._valueIdentifiers = valueIdentifiers; this._visitedValues = new Set(); this._valueIds = new Map(); this._idSeed = 0; this._path = []; this._edges = []; } // Override. preProcessValue(val) { if (this._shouldIgnore(val)) { return true; } this._updateEdge(val); if (this._visitedValues.has(val)) { return false; // Already visited. } this._visitedValues.add(val); return true; } // Override. postProcessValue(val) { if (this._shouldIgnore(val)) { return; } (0, _invariant.default)(this._path.length > 0); this._path.pop(); } _getValueId(val) { let id = this._valueIds.get(val); if (id === undefined) { this._valueIds.set(val, ++this._idSeed); id = this._idSeed; } return id; } _shouldIgnore(val) { return val instanceof _index.EmptyValue || val.isIntrinsic() || _HeapInspector.HeapInspector.isLeaf(val); } _updateEdge(val) { if (this._path.length > 0) { const parent = this._path[this._path.length - 1]; this._edges.push({ fromId: this._getValueId(parent), toId: this._getValueId(val) }); } this._path.push(val); } _getValueLabel(val) { // TODO: does not use ref count yet, figure out how to best visualize it later. const serializedId = this._valueIdentifiers.getIdentifier(val); (0, _invariant.default)(serializedId); return val.__originalName !== undefined ? `${serializedId.name}(${val.__originalName})` : serializedId.name; } _generateDotGraphData(nodes, edges) { let content = "digraph{\n"; for (const val of nodes) { const nodeId = this._getValueId(val); content += ` node${nodeId} [shape=${this._getValueShape(val)} label=${this._getValueLabel(val)}];\n`; } for (const edge of edges) { content += ` node${edge.fromId} -> node${edge.toId};\n`; } content += "}"; return content; } _generateVisJSGraphData(nodes, edges) { let nodesData = []; let edgesData = []; for (let node of nodes) { const nodeId = this._getValueId(node); let nodeData = { id: `${nodeId}`, label: this._getValueLabel(node), shape: this._getValueShape(node), color: this._getValueColor(node) }; nodesData.push(nodeData); } for (let [index, edge] of edges.entries()) { let edgeData = { id: index, from: `${edge.fromId}`, to: `${edge.toId}`, arrows: "to" }; edgesData.push(edgeData); } let graphData = { nodes: nodesData, edges: edgesData }; return JSON.stringify(graphData); } // TODO: find a way to comment the meaning of shape => value mapping in final graph language. _getValueShape(val) { let shape = null; if (val instanceof _index.FunctionValue) { shape = "circle"; } else if (val instanceof _index.AbstractValue) { shape = "diamond"; } else if (val instanceof _index.ProxyValue) { shape = "triangle"; } else if (val instanceof _index.SymbolValue) { shape = "star"; } else if (val instanceof _index.ObjectValue) { shape = "box"; } else { shape = "ellipse"; } return shape; } // TODO: find a way to comment the meaning of shape => value mapping in final graph language. _getValueColor(val) { let shape = null; if (val instanceof _index.FunctionValue) { shape = "red"; } else if (val instanceof _index.AbstractValue) { shape = "green"; } else if (val instanceof _index.ProxyValue) { shape = "orange"; } else if (val instanceof _index.SymbolValue) { shape = "yellow"; } else if (val instanceof _index.ObjectValue) { shape = "#3BB9FF"; // light blue } else { shape = "grey"; } return shape; } generateResult(heapGraphFormat) { return heapGraphFormat === "DotLanguage" ? this._generateDotGraphData(this._visitedValues, this._edges) : this._generateVisJSGraphData(this._visitedValues, this._edges); } } exports.ResidualHeapGraphGenerator = ResidualHeapGraphGenerator; //# sourceMappingURL=ResidualHeapGraphGenerator.js.map