UNPKG

prepack

Version:

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

717 lines (639 loc) 30 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _errors = require("../errors.js"); var _generator = require("../utils/generator.js"); var _builder = require("../utils/builder.js"); var _builder2 = _interopRequireDefault(_builder); var _index = require("./index.js"); var _index2 = require("../methods/index.js"); var _index3 = require("../domains/index.js"); var _invariant = require("../invariant.js"); var _invariant2 = _interopRequireDefault(_invariant); var _babelTypes = require("babel-types"); var t = _interopRequireWildcard(_babelTypes); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class AbstractValue extends _index.Value { constructor(realm, types, values, hashValue, args, buildNode, optionalArgs) { (0, _invariant2.default)(realm.useAbstractInterpretation); super(realm, optionalArgs ? optionalArgs.intrinsicName : undefined); (0, _invariant2.default)(buildNode instanceof Function || args.length === 0); (0, _invariant2.default)(!_index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) || this instanceof _index.AbstractObjectValue); (0, _invariant2.default)(types.getType() !== _index.NullValue && types.getType() !== _index.UndefinedValue); this.types = types; this.values = values; this.mightBeEmpty = false; this._buildNode = buildNode; this.args = args; this.hashValue = hashValue; this.kind = optionalArgs ? optionalArgs.kind : undefined; } addSourceLocationsTo(locations, seenValues = new Set()) { if (seenValues.has(this)) return; seenValues.add(this); if (this._buildNode && !(this._buildNode instanceof Function)) { if (this._buildNode.loc) locations.push(this._buildNode.loc); } for (let val of this.args) { if (val instanceof AbstractValue) val.addSourceLocationsTo(locations, seenValues); } } addSourceNamesTo(names) { let gen = this.$Realm.preludeGenerator; function add_intrinsic(name) { if (name.startsWith("_$")) { if (gen === undefined) return; add_args(gen.derivedIds.get(name)); } else if (names.indexOf(name) < 0) { names.push(name); } } function add_args(args) { if (args === undefined) return; for (let val of args) { if (val.intrinsicName) { add_intrinsic(val.intrinsicName); } else if (val instanceof AbstractValue) { val.addSourceNamesTo(names); } else if (val instanceof _index.StringValue) { if (val.value.startsWith("__")) { names.push(val.value.slice(2)); } } } } if (this.intrinsicName) { add_intrinsic(this.intrinsicName); } add_args(this.args); } buildNode(args) { let buildNode = this.getBuildNode(); return buildNode instanceof Function ? buildNode(args) : buildNode; } equals(x) { if (x instanceof _index.ConcreteValue) return false; let thisArgs = this.args; let n = thisArgs.length; let argsAreEqual = () => { (0, _invariant2.default)(x instanceof AbstractValue); let xArgs = x.args; let m = xArgs.length; (0, _invariant2.default)(n === m); // Will be true if kinds are the same. Caller should see to it. for (let i = 0; i < n; i++) { let a = thisArgs[i]; let b = xArgs[i]; if (!a.equals(b)) return false; } return true; }; return this === x || x instanceof AbstractValue && this.kind === x.kind && this.hashValue === x.hashValue && (this.intrinsicName && this.intrinsicName.length > 0 && this.intrinsicName === x.intrinsicName || n > 0 && argsAreEqual()); } getBuildNode() { (0, _invariant2.default)(this._buildNode); return this._buildNode; } getHash() { return this.hashValue; } getType() { return this.types.getType(); } getIdentifier() { (0, _invariant2.default)(this.hasIdentifier()); return this._buildNode; } hasIdentifier() { return this._buildNode && this._buildNode.type === "Identifier"; } // this => val. A false value does not imply that !(this => val). implies(val) { if (this.equals(val)) return true; // x => x regardless of its value if (!this.mightNotBeFalse()) return true; // false => val if (!val.mightNotBeTrue()) return true; // x => true regardless of the value of x if (val instanceof AbstractValue) { // Neither this (x) nor val (y) is a known value, so we need to do some reasoning based on the structure // x => x || y if (val.kind === "||") { let [x, y] = val.args; return this.implies(x) || this.implies(y); } // x => !y if y => !x if (val.kind === "!") { let [y] = val.args; (0, _invariant2.default)(y instanceof AbstractValue); return y.impliesNot(this); } // x => x !== null && x !== undefined if (val.kind === "!==") { let [x, y] = val.args; if (this.implies(x)) return y instanceof _index.NullValue || y instanceof _index.UndefinedValue; if (this.implies(y)) return x instanceof _index.NullValue || x instanceof _index.UndefinedValue; } // !!x => y if x => y if (this.kind === "!") { let [nx] = this.args; (0, _invariant2.default)(nx instanceof AbstractValue); if (nx.kind === "!") { let [x] = nx.args; (0, _invariant2.default)(x instanceof AbstractValue); return x.implies(val); } } if (this.kind === "conditional") { let [c, x, y] = this.args; // (c ? x : y) => val if x is true and y is false and c = val if (!x.mightNotBeTrue() && !y.mightNotBeFalse()) { return c.equals(val); } // (c ? false : y) => y !== undefined && y !== null && y !== f if (val.kind === "!==") { let [vx, vy] = val.args; if (!x.mightNotBeFalse()) { if (y.implies(vx)) return vy instanceof _index.NullValue || vy instanceof _index.UndefinedValue; if (y.implies(vy)) return vx instanceof _index.NullValue || vx instanceof _index.UndefinedValue; } else if (!y.mightNotBeFalse()) { if (x.implies(vx)) return vy instanceof _index.NullValue || vy instanceof _index.UndefinedValue; if (x.implies(vy)) return vx instanceof _index.NullValue || vx instanceof _index.UndefinedValue; } } // (c ? x : (c || false)) => c (if c were false this value could not be true) if (y.kind === "||") { (0, _invariant2.default)(y instanceof AbstractValue); let [yx, yy] = y.args; return c.equals(yx) && !yy.mightNotBeFalse() && c.equals(val); } } // (0 !== x) => x since undefined, null, false, 0, NaN and "" are excluded by the !== and all other values are thruthy if (this.kind === "!==") { let [x, y] = this.args; if (x instanceof _index.NumberValue && x.value === 0) return y.equals(val); if (y instanceof _index.NumberValue && y.value === 0) return x.equals(val); } } return false; } // this => !val. A false value does not imply that !(this => !val). impliesNot(val) { if (this.equals(val)) return false; // x => x regardless of its value, hence x => !val is false if (!this.mightNotBeFalse()) return true; // false => !val if (!val.mightNotBeFalse()) return true; // x => !false regardless of the value of x if (val instanceof AbstractValue) { // !x => !y if y => x if (this.kind === "!") { let [x] = this.args; (0, _invariant2.default)(x instanceof AbstractValue); if (x.kind === "!") { // !!x => !y if y => !x (0, _invariant2.default)(x instanceof AbstractValue); let [xx] = x.args; (0, _invariant2.default)(xx instanceof AbstractValue); return xx.impliesNot(val); } return val.implies(x); } if (this.kind === "conditional") { let [c, x, y] = this.args; // (c ? x : y) => !val if x is false and y is true and c = val if (!x.mightNotBeFalse() && !y.mightNotBeTrue()) { return c.equals(val); } } } return false; } // todo: abstract values should never be of type UndefinedValue or NullValue, assert this mightBeFalse() { let valueType = this.getType(); if (valueType === _index.UndefinedValue) return true; if (valueType === _index.NullValue) return true; if (valueType === _index.SymbolValue) return false; if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return false; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightBeFalse()) return true; return false; } if (this.values.isTop()) return true; return this.values.mightBeFalse(); } mightNotBeFalse() { let valueType = this.getType(); if (valueType === _index.UndefinedValue) return false; if (valueType === _index.NullValue) return false; if (valueType === _index.SymbolValue) return true; if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return true; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightNotBeFalse()) return true; return false; } if (this.values.isTop()) return true; return this.values.mightNotBeFalse(); } mightBeNull() { let valueType = this.getType(); if (valueType === _index.NullValue) return true; if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightBeNull()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueOfType(_index.NullValue); } mightNotBeNull() { let valueType = this.getType(); if (valueType === _index.NullValue) return false; if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightNotBeNull()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueNotOfType(_index.NullValue); } mightBeNumber() { let valueType = this.getType(); if (_index.Value.isTypeCompatibleWith(valueType, _index.NumberValue)) return true; if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightBeNumber()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueOfType(_index.NumberValue); } mightNotBeNumber() { let valueType = this.getType(); if (_index.Value.isTypeCompatibleWith(valueType, _index.NumberValue)) return false; if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightNotBeNumber()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueNotOfType(_index.NumberValue); } mightNotBeObject() { let valueType = this.getType(); if (_index.Value.isTypeCompatibleWith(valueType, _index.PrimitiveValue)) return true; if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return false; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightNotBeObject()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueNotOfType(_index.ObjectValue); } mightBeObject() { let valueType = this.getType(); if (_index.Value.isTypeCompatibleWith(valueType, _index.PrimitiveValue)) return false; if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return true; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightBeObject()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueOfType(_index.ObjectValue); } mightBeString() { let valueType = this.getType(); if (valueType === _index.StringValue) return true; if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightBeString()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueOfType(_index.StringValue); } mightNotBeString() { let valueType = this.getType(); if (valueType === _index.StringValue) return false; if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightNotBeString()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueNotOfType(_index.StringValue); } mightBeUndefined() { let valueType = this.getType(); if (valueType === _index.UndefinedValue) return true; if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightBeUndefined()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueOfType(_index.UndefinedValue); } mightNotBeUndefined() { let valueType = this.getType(); if (valueType === _index.UndefinedValue) return false; if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true; if (this.kind === "abstractConcreteUnion") { for (let arg of this.args) if (arg.mightNotBeUndefined()) return true; return false; } if (this.values.isTop()) return true; return this.values.includesValueNotOfType(_index.UndefinedValue); } mightHaveBeenDeleted() { return this.mightBeEmpty; } promoteEmptyToUndefined() { if (this.values.isTop()) return this; if (!this.mightBeEmpty) return this; let cond = AbstractValue.createFromBinaryOp(this.$Realm, "===", this, this.$Realm.intrinsics.empty); let result = AbstractValue.createFromConditionalOp(this.$Realm, cond, this.$Realm.intrinsics.undefined, this); if (result instanceof AbstractValue) result.values = this.values.promoteEmptyToUndefined(); return result; } throwIfNotConcrete() { AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } throwIfNotConcreteNumber() { AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } throwIfNotConcreteString() { AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } throwIfNotConcreteBoolean() { AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } throwIfNotConcreteSymbol() { AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } throwIfNotConcreteObject() { AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } throwIfNotConcretePrimitive() { AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } throwIfNotObject() { (0, _invariant2.default)(!(this instanceof _index.AbstractObjectValue)); AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } static createFromBinaryOp(realm, op, left, right, loc, kind) { let leftTypes, leftValues; if (left instanceof AbstractValue) { leftTypes = left.types; leftValues = left.values; } else { leftTypes = new _index3.TypesDomain(left.getType()); (0, _invariant2.default)(left instanceof _index.ConcreteValue); leftValues = new _index3.ValuesDomain(left); } let rightTypes, rightValues; if (right instanceof AbstractValue) { rightTypes = right.types; rightValues = right.values; } else { rightTypes = new _index3.TypesDomain(right.getType()); (0, _invariant2.default)(right instanceof _index.ConcreteValue); rightValues = new _index3.ValuesDomain(right); } let resultTypes = _index3.TypesDomain.binaryOp(op, leftTypes, rightTypes); let resultValues = kind === "template for property name condition" ? _index3.ValuesDomain.topVal : _index3.ValuesDomain.binaryOp(realm, op, leftValues, rightValues); let [hash, args] = kind === undefined ? (0, _index2.hashBinary)(op, left, right) : (0, _index2.hashCall)(kind, left, right); let result = new AbstractValue(realm, resultTypes, resultValues, hash, args, ([x, y]) => t.binaryExpression(op, x, y)); result.kind = kind || op; result.expressionLocation = loc; return result; } static createFromLogicalOp(realm, op, left, right, loc, isCondition) { let leftTypes, leftValues; if (left instanceof AbstractValue) { leftTypes = left.types; leftValues = left.values; } else { leftTypes = new _index3.TypesDomain(left.getType()); (0, _invariant2.default)(left instanceof _index.ConcreteValue); leftValues = new _index3.ValuesDomain(left); } let rightTypes, rightValues; if (right instanceof AbstractValue) { rightTypes = right.types; rightValues = right.values; } else { rightTypes = new _index3.TypesDomain(right.getType()); (0, _invariant2.default)(right instanceof _index.ConcreteValue); rightValues = new _index3.ValuesDomain(right); } let resultTypes = _index3.TypesDomain.logicalOp(op, leftTypes, rightTypes); let resultValues = _index3.ValuesDomain.logicalOp(realm, op, leftValues, rightValues); let [hash, args] = (0, _index2.hashCall)(op, left, right); let Constructor = _index.Value.isTypeCompatibleWith(resultTypes.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue; let result = new Constructor(realm, resultTypes, resultValues, hash, args, ([x, y]) => t.logicalExpression(op, x, y)); result.kind = op; result.expressionLocation = loc; return isCondition ? realm.simplifyAndRefineAbstractCondition(result) : realm.simplifyAndRefineAbstractValue(result); } static createFromConditionalOp(realm, condition, left, right, loc, isCondition) { let types = _index3.TypesDomain.joinValues(left, right); if (types.getType() === _index.NullValue) return realm.intrinsics.null; if (types.getType() === _index.UndefinedValue) return realm.intrinsics.undefined; let values = _index3.ValuesDomain.joinValues(realm, left, right); let [hash, args] = (0, _index2.hashTernary)(condition, left || realm.intrinsics.undefined, right || realm.intrinsics.undefined); let Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue; let result = new Constructor(realm, types, values, hash, args, ([c, x, y]) => t.conditionalExpression(c, x, y), { kind: "conditional" }); result.expressionLocation = loc; if (left) result.mightBeEmpty = left.mightHaveBeenDeleted(); if (right && !result.mightBeEmpty) result.mightBeEmpty = right.mightHaveBeenDeleted(); if (result.mightBeEmpty) return result; return isCondition ? realm.simplifyAndRefineAbstractCondition(result) : realm.simplifyAndRefineAbstractValue(result); } static createFromUnaryOp(realm, op, operand, prefix, loc, isCondition) { (0, _invariant2.default)(op !== "delete" && op !== "++" && op !== "--"); // The operation must be pure let resultTypes = _index3.TypesDomain.unaryOp(op, new _index3.TypesDomain(operand.getType())); let resultValues = _index3.ValuesDomain.unaryOp(realm, op, operand.values); let result = new AbstractValue(realm, resultTypes, resultValues, (0, _index2.hashUnary)(op, operand), [operand], ([x]) => t.unaryExpression(op, x, prefix)); result.kind = op; result.expressionLocation = loc; return isCondition ? realm.simplifyAndRefineAbstractCondition(result) : realm.simplifyAndRefineAbstractValue(result); } /* Note that the template is parameterized by the names A, B, C and so on. When the abstract value is serialized, the serialized operations are substituted for the corresponding parameters and the resulting template is parsed into an AST subtree that is incorporated into the AST produced by the serializer. */ static createFromTemplate(realm, template, resultType, operands, kind, loc) { let resultTypes = new _index3.TypesDomain(resultType); let resultValues = _index3.ValuesDomain.topVal; let hash; [hash, operands] = (0, _index2.hashCall)(kind, ...operands); let Constructor = _index.Value.isTypeCompatibleWith(resultType, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue; let labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; (0, _invariant2.default)(labels.length >= operands.length); let result = new Constructor(realm, resultTypes, resultValues, hash, operands, args => { (0, _invariant2.default)(realm.preludeGenerator !== undefined); let generatorArgs = {}; let i = 0; for (let arg of args) generatorArgs[labels.charAt(i++)] = arg; return template(realm.preludeGenerator)(generatorArgs); }); result.kind = kind; result.expressionLocation = loc || realm.currentLocation; return result; } static createFromType(realm, resultType, kind) { let types = new _index3.TypesDomain(resultType); let Constructor = _index.Value.isTypeCompatibleWith(resultType, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue; let hash = (0, _index2.hashString)(resultType.name + (kind || "")); let result = new Constructor(realm, types, _index3.ValuesDomain.topVal, hash, []); if (kind) result.kind = kind; result.expressionLocation = realm.currentLocation; return result; } /* Emits a declaration for an identifier into the generator at the current point in time and initializes it with an expression constructed from the given template. Returns an abstract value that refers to the newly declared identifier. Note that the template must generate an expression which has no side-effects on the prepack state. It is assumed, however, that there could be side-effects on the native state unless the isPure option is specified. */ static createTemporalFromTemplate(realm, template, resultType, operands, optionalArgs) { (0, _invariant2.default)(resultType !== _index.UndefinedValue); let temp = AbstractValue.createFromTemplate(realm, template, resultType, operands, ""); let types = temp.types; let values = temp.values; let args = temp.args; let buildNode_ = temp.getBuildNode(); (0, _invariant2.default)(realm.generator !== undefined); return realm.generator.derive(types, values, args, buildNode_, optionalArgs); } static createFromBuildFunction(realm, resultType, args, buildFunction, optionalArgs) { let types = new _index3.TypesDomain(resultType); let values = _index3.ValuesDomain.topVal; let Constructor = _index.Value.isTypeCompatibleWith(resultType, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue; let kind = optionalArgs && optionalArgs.kind || "build function"; let hash; [hash, args] = (0, _index2.hashCall)(kind, ...args); let result = new Constructor(realm, types, values, hash, args, buildFunction); result.kind = kind; return result; } static createTemporalFromBuildFunction(realm, resultType, args, buildFunction, optionalArgs) { let types = new _index3.TypesDomain(resultType); let values = _index3.ValuesDomain.topVal; (0, _invariant2.default)(realm.generator !== undefined); if (resultType === _index.UndefinedValue) { return realm.generator.emitVoidExpression(types, values, args, buildFunction); } else { return realm.generator.derive(types, values, args, buildFunction, optionalArgs); } } // Creates a union of an abstract value with one or more concrete values. // The build node for the abstract values becomes the build node for the union. // Use this only to allow instrinsic abstract objects to be null and/or undefined. static createAbstractConcreteUnion(realm, ...elements) { let concreteValues = elements.filter(e => e instanceof _index.ConcreteValue); (0, _invariant2.default)(concreteValues.length > 0 && concreteValues.length === elements.length - 1); let concreteSet = new Set(concreteValues); let abstractValue = elements.find(e => e instanceof AbstractValue); (0, _invariant2.default)(abstractValue instanceof AbstractValue); let values; if (!abstractValue.values.isTop()) { abstractValue.values.getElements().forEach(v => concreteSet.add(v)); values = new _index3.ValuesDomain(concreteSet); } else { values = _index3.ValuesDomain.topVal; } let types = _index3.TypesDomain.topVal; let [hash, operands] = (0, _index2.hashCall)("abstractConcreteUnion", abstractValue, ...concreteValues); let result = new AbstractValue(realm, types, values, hash, operands, nodes => nodes[0], { kind: "abstractConcreteUnion" }); result.expressionLocation = realm.currentLocation; return result; } static createFromWidenedProperty(realm, resultTemplate, args, buildFunction) { let types = resultTemplate.types; let values = resultTemplate.values; let [hash] = (0, _index2.hashCall)("widened property", ...args); let Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue; let result = new Constructor(realm, types, values, hash, args, buildFunction); result.kind = "widened property"; result.mightBeEmpty = resultTemplate.mightBeEmpty; result.expressionLocation = resultTemplate.expressionLocation; return result; } static createFromWidening(realm, value1, value2) { // todo: #1174 look at kind and figure out much narrower widenings let types = _index3.TypesDomain.joinValues(value1, value2); let values = _index3.ValuesDomain.topVal; let [hash] = (0, _index2.hashCall)("widened"); let Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue; let result = new Constructor(realm, types, values, hash, []); result.kind = "widened"; result.mightBeEmpty = value1.mightHaveBeenDeleted() || value2.mightHaveBeenDeleted(); result.expressionLocation = value1.expressionLocation; return result; } static generateErrorInformationForAbstractVal(val) { let names = []; val.addSourceNamesTo(names); if (names.length === 0) { val.addSourceNamesTo(names); } return `abstract value${names.length > 1 ? "s" : ""} ${names.join(" and ")}`; } static describe(val, propertyName) { let realm = val.$Realm; let identity; if (val === realm.$GlobalObject) identity = "global";else if (val instanceof AbstractValue) { identity = this.generateErrorInformationForAbstractVal(val); } else identity = val.intrinsicName || "(some value)"; let source_locations = []; if (val instanceof AbstractValue) val.addSourceLocationsTo(source_locations); let location; if (propertyName instanceof _index.SymbolValue) { let desc = propertyName.$Description; if (desc) { location = `at symbol [${desc.throwIfNotConcreteString().value}]`; } else { location = `at symbol [${"(no description)"}]`; } } else if (propertyName instanceof _index.StringValue) location = `at ${propertyName.value}`;else if (typeof propertyName === "string") location = `at ${propertyName}`;else location = source_locations.length === 0 ? "" : `at ${source_locations.join("\n")}`; return `${identity} ${location}`; } static reportIntrospectionError(val, propertyName) { let message = `This operation is not yet supported on ${AbstractValue.describe(val, propertyName)}`; let realm = val.$Realm; return realm.reportIntrospectionError(message); } static createAbstractObject(realm, name, template) { let value; if (template === undefined) { template = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype); } template.makePartial(); template.makeSimple(); value = AbstractValue.createFromTemplate(realm, (0, _builder2.default)(name), _index.ObjectValue, [], name); value.intrinsicName = name; value.values = new _index3.ValuesDomain(new Set([template])); realm.rebuildNestedProperties(value, name); (0, _invariant2.default)(value instanceof _index.AbstractObjectValue); return value; } } exports.default = AbstractValue; /** * 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. */ //# sourceMappingURL=AbstractValue.js.map