UNPKG

prepack

Version:

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

260 lines (205 loc) 7.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.VariableManager = void 0; var _ReferenceMap = require("./ReferenceMap.js"); var _environment = require("./../../environment.js"); var _index = require("./../../values/index.js"); var _invariant = _interopRequireDefault(require("./../common/invariant.js")); var _is = require("./../../methods/is.js"); var _DebuggerError = require("./../common/DebuggerError.js"); var _singletons = require("./../../singletons.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 */ // This class manages the handling of variable requests in the debugger // The DebugProtocol specifies collections of variables are to be fetched using a // unique reference ID called a variablesReference. This class can generate new // variablesReferences to pass to the UI and then perform lookups for those // variablesReferences when they are requested. class VariableManager { constructor(realm) { this._containerCache = new Map(); this._referenceMap = new _ReferenceMap.ReferenceMap(); this._realm = realm; } // cache for created references // Given a container, either returns a cached reference for that container if // it exists or return a new reference getReferenceForValue(value) { let cachedRef = this._containerCache.get(value); if (cachedRef !== undefined) { return cachedRef; } let varRef = this._referenceMap.add(value); this._containerCache.set(value, varRef); return varRef; } // The entry point for retrieving a collection of variables by a reference getVariablesByReference(reference) { let container = this._referenceMap.get(reference); if (!container) return []; if (container instanceof _environment.LexicalEnvironment) { return this._getVariablesFromEnvRecord(container.environmentRecord); } else if (container instanceof _index.ObjectValue) { return this._getVariablesFromObject(container); } else if (container instanceof _index.AbstractValue) { return this._getAbstractValueContent(container); } else { (0, _invariant.default)(false, "Invalid variable container"); } } _getVariablesFromObject(object) { let variables = []; let names = object.properties.keys(); for (let name of names) { let binding = object.properties.get(name); (0, _invariant.default)(binding !== undefined); if (binding.descriptor) { if ((0, _is.IsDataDescriptor)(this._realm, binding.descriptor)) { let value = binding.descriptor.value; if (value instanceof _index.Value) { let variable = this._getVariableFromValue(name, value); variables.push(variable); } } } } return variables; } _getAbstractValueContent(value) { let kindVar = { name: "kind", value: value.kind || "undefined", variablesReference: 0 }; let contents = [kindVar]; let argCount = 1; for (let arg of value.args) { contents.push(this._getVariableFromValue("arg-" + argCount, arg)); argCount++; } return contents; } _getVariablesFromEnvRecord(envRecord) { if (envRecord instanceof _environment.DeclarativeEnvironmentRecord) { return this._getVariablesFromDeclarativeEnv(envRecord); } else if (envRecord instanceof _environment.ObjectEnvironmentRecord) { if (envRecord.object instanceof _index.ObjectValue) { return this._getVariablesFromObject(envRecord.object); } else if (envRecord.object instanceof _index.AbstractObjectValue) { // TODO: call _getVariablesFromAbstractObject when it is implemented return []; } else { (0, _invariant.default)(false, "Invalid type of object environment record"); } } else if (envRecord instanceof _environment.GlobalEnvironmentRecord) { let declVars = this._getVariablesFromEnvRecord(envRecord.$DeclarativeRecord); let objVars = this._getVariablesFromEnvRecord(envRecord.$ObjectRecord); return declVars.concat(objVars); } else { (0, _invariant.default)(false, "Invalid type of environment record"); } } _getVariablesFromDeclarativeEnv(env) { let variables = []; let bindings = env.bindings; for (let name in bindings) { let binding = bindings[name]; if (binding.value) { let variable = this._getVariableFromValue(name, binding.value); variables.push(variable); } } return variables; } _getVariableFromValue(name, value) { if (value instanceof _index.ConcreteValue) { return this._getVariableFromConcreteValue(name, value); } else if (value instanceof _index.AbstractValue) { return this._getVariableFromAbstractValue(name, value); } else { (0, _invariant.default)(false, "Value is neither concrete nor abstract"); } } _getVariableFromAbstractValue(name, value) { let variable = { name: name, value: this._getAbstractValueDisplay(value), variablesReference: this.getReferenceForValue(value) }; return variable; } _getAbstractValueDisplay(value) { if (value.intrinsicName !== undefined && !value.intrinsicName.startsWith("_")) { return value.intrinsicName; } return "Abstract " + value.types.getType().name; } _getVariableFromConcreteValue(name, value) { if (value instanceof _index.PrimitiveValue) { let variable = { name: name, value: value.toDisplayString(), variablesReference: 0 }; return variable; } else if (value instanceof _index.ObjectValue) { let variable = { name: name, value: value.getKind(), variablesReference: this.getReferenceForValue(value) }; return variable; } else { (0, _invariant.default)(false, "Concrete value must be primitive or object"); } } evaluate(frameId, expression) { let evalRealm = this._realm; let isDirect = false; let isStrict = false; if (frameId !== undefined) { if (frameId < 0 || frameId >= this._realm.contextStack.length) { throw new _DebuggerError.DebuggerError("Invalid command", "Invalid value for frame ID"); } // frameId's are in reverse order of context stack let stackIndex = this._realm.contextStack.length - 1 - frameId; let context = this._realm.contextStack[stackIndex]; isDirect = true; isStrict = true; evalRealm = context.realm; } let evalString = new _index.StringValue(this._realm, expression); try { let value = _singletons.Functions.PerformEval(this._realm, evalString, evalRealm, isStrict, isDirect); let varInfo = this._getVariableFromValue(expression, value); let result = { kind: "evaluate", displayValue: varInfo.value, type: value.getType().name, variablesReference: varInfo.variablesReference }; return result; } catch (e) { let result = { kind: "evaluate", displayValue: `Failed to evaluate: ${expression}`, type: "unknown", variablesReference: 0 }; return result; } } clean() { this._containerCache = new Map(); this._referenceMap.clean(); } } exports.VariableManager = VariableManager; //# sourceMappingURL=VariableManager.js.map