UNPKG

prepack

Version:

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

579 lines (534 loc) 22.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _errors = require("../errors.js"); var _index = require("./index.js"); var _index2 = require("../domains/index.js"); var _index3 = require("../methods/index.js"); var _singletons = require("../singletons.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 AbstractObjectValue extends _index.AbstractValue { constructor(realm, types, values, hashValue, args, buildNode, optionalArgs) { super(realm, types, values, hashValue, args, buildNode, optionalArgs); if (!values.isTop()) { for (let element of this.values.getElements()) (0, _invariant2.default)(element instanceof _index.ObjectValue); } } getTemplate() { for (let element of this.values.getElements()) { (0, _invariant2.default)(element instanceof _index.ObjectValue); if (element.isPartialObject()) { return element; } else { break; } } _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } isPartialObject() { // At the very least, the identity of the object is unknown return true; } isSimpleObject() { if (this.cachedIsSimpleObject === undefined) this.cachedIsSimpleObject = this._elementsAreSimpleObjects(); return this.cachedIsSimpleObject; } _elementsAreSimpleObjects() { if (this.values.isTop()) return false; let result; for (let element of this.values.getElements()) { (0, _invariant2.default)(element instanceof _index.ObjectValue); if (result === undefined) { result = element.isSimpleObject(); } else if (result !== element.isSimpleObject()) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } } if (result === undefined) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } return result; } isFinalObject() { if (this.values.isTop()) return false; let result; for (let element of this.values.getElements()) { (0, _invariant2.default)(element instanceof _index.ObjectValue); if (result === undefined) { result = element.isFinalObject(); } else if (result !== element.isFinalObject()) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } } if (result === undefined) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } return result; } mightBeFalse() { return false; } mightNotBeFalse() { return true; } makeNotPartial() { if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } for (let element of this.values.getElements()) { (0, _invariant2.default)(element instanceof _index.ObjectValue); element.makeNotPartial(); } } makePartial() { if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } for (let element of this.values.getElements()) { (0, _invariant2.default)(element instanceof _index.ObjectValue); element.makePartial(); } } makeSimple(option) { if (this.values.isTop() && this.getType() === _index.ObjectValue) { let obj = new _index.ObjectValue(this.$Realm, this.$Realm.intrinsics.ObjectPrototype); obj.intrinsicName = this.intrinsicName; obj.intrinsicNameGenerated = true; obj.makePartial(); obj._templateFor = this; this.values = new _index2.ValuesDomain(obj); } if (!this.values.isTop()) { for (let element of this.values.getElements()) { (0, _invariant2.default)(element instanceof _index.ObjectValue); element.makeSimple(option); } } this.cachedIsSimpleObject = true; } makeFinal() { if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } for (let element of this.values.getElements()) { (0, _invariant2.default)(element instanceof _index.ObjectValue); element.makeFinal(); } } throwIfNotObject() { return this; } // ECMA262 9.1.3 $IsExtensible() { return false; } // ECMA262 9.1.5 $GetOwnProperty(P) { if (P instanceof _index.StringValue) P = P.value; if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); return cv.$GetOwnProperty(P, cv); } (0, _invariant2.default)(false); } else if (this.kind === "conditional") { // this is the join of two concrete objects let [cond, ob1, ob2] = this.args; (0, _invariant2.default)(cond instanceof _index.AbstractValue); (0, _invariant2.default)(ob1 instanceof _index.ObjectValue); (0, _invariant2.default)(ob2 instanceof _index.ObjectValue); let d1 = ob1.$GetOwnProperty(P); let d2 = ob2.$GetOwnProperty(P); if (d1 === undefined || d2 === undefined || !(0, _index3.equalDescriptors)(d1, d2)) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let desc = (0, _index3.cloneDescriptor)(d1); (0, _invariant2.default)(desc !== undefined); if ((0, _index3.IsDataDescriptor)(this.$Realm, desc)) { let d1Value = d1.value; (0, _invariant2.default)(d1Value === undefined || d1Value instanceof _index.Value); let d2Value = d2.value; (0, _invariant2.default)(d2Value === undefined || d2Value instanceof _index.Value); desc.value = _singletons.Join.joinValuesAsConditional(this.$Realm, cond, d1Value, d2Value); } return desc; } else if (this.kind === "widened") { // This abstract object was created by repeated assignments of freshly allocated objects to the same binding inside a loop let [ob1, ob2] = this.args; // ob1: summary of iterations 1...n, ob2: summary of iteration n+1 (0, _invariant2.default)(ob1 instanceof _index.ObjectValue); (0, _invariant2.default)(ob2 instanceof _index.ObjectValue); let d1 = ob1.$GetOwnProperty(P); let d2 = ob2.$GetOwnProperty(P); if (d1 === undefined || d2 === undefined || !(0, _index3.equalDescriptors)(d1, d2)) { // We do not handle the case where different loop iterations result in different kinds of propperties _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let desc = (0, _index3.cloneDescriptor)(d1); (0, _invariant2.default)(desc !== undefined); if ((0, _index3.IsDataDescriptor)(this.$Realm, desc)) { // Values may be different, i.e. values may be loop variant, so the widened value summarizes the entire loop let d1Value = d1.value; (0, _invariant2.default)(d1Value === undefined || d1Value instanceof _index.Value); let d2Value = d2.value; (0, _invariant2.default)(d2Value === undefined || d2Value instanceof _index.Value); desc.value = _singletons.Widen.widenValues(this.$Realm, d1Value, d2Value); } else { // In this case equalDescriptors guarantees exact equality betwee d1 and d2. // Inlining the accessors will eventually bring in data properties if the accessors have loop variant behavior } return desc; } else { let hasProp = false; let doesNotHaveProp = false; let desc; for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); let d = cv.$GetOwnProperty(P); if (d === undefined) doesNotHaveProp = true;else { hasProp = true; if (desc === undefined) { desc = (0, _index3.cloneDescriptor)(d); (0, _invariant2.default)(desc !== undefined); if (!(0, _index3.IsDataDescriptor)(this.$Realm, d)) continue; } else { if (!(0, _index3.equalDescriptors)(d, desc)) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } if (!(0, _index3.IsDataDescriptor)(this.$Realm, desc)) continue; // values may be different let cond = _index.AbstractValue.createFromBinaryOp(this.$Realm, "===", this, cv, this.expressionLocation); desc.value = _singletons.Join.joinValuesAsConditional(this.$Realm, cond, d.value, desc.value); } } } if (hasProp && doesNotHaveProp) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } return desc; } } // ECMA262 9.1.6 $DefineOwnProperty(P, Desc) { if (P instanceof _index.StringValue) P = P.value; if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); return cv.$DefineOwnProperty(P, Desc); } (0, _invariant2.default)(false); } else { if (!(0, _index3.IsDataDescriptor)(this.$Realm, Desc)) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let desc = { value: "value" in Desc ? Desc.value : this.$Realm.intrinsics.undefined, writable: "writable" in Desc ? Desc.writable : false, enumerable: "enumerable" in Desc ? Desc.enumerable : false, configurable: "configurable" in Desc ? Desc.configurable : false }; let new_val = desc.value; (0, _invariant2.default)(new_val instanceof _index.Value); let sawTrue = false; let sawFalse = false; for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); let d = cv.$GetOwnProperty(P); if (d !== undefined && !(0, _index3.equalDescriptors)(d, desc)) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let dval = d === undefined || d.vale === undefined ? this.$Realm.intrinsics.empty : d.value; (0, _invariant2.default)(dval instanceof _index.Value); let cond = _index.AbstractValue.createFromBinaryOp(this.$Realm, "===", this, cv, this.expressionLocation); desc.value = _singletons.Join.joinValuesAsConditional(this.$Realm, cond, new_val, dval); if (cv.$DefineOwnProperty(P, desc)) { sawTrue = true; } else sawFalse = true; } if (sawTrue && sawFalse) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } return sawTrue; } } // ECMA262 9.1.7 $HasProperty(P) { if (P instanceof _index.StringValue) P = P.value; if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); return cv.$HasProperty(P, cv); } (0, _invariant2.default)(false); } else { let hasProp = false; let doesNotHaveProp = false; for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); if (cv.$HasProperty(P)) hasProp = true;else doesNotHaveProp = true; } if (hasProp && doesNotHaveProp) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } return hasProp; } } // ECMA262 9.1.8 $Get(P, Receiver) { if (P instanceof _index.StringValue) P = P.value; if (this.values.isTop()) { let generateAbstractGet = () => { let type = _index.Value; if (P === "length" && _index.Value.isTypeCompatibleWith(this.getType(), _index.ArrayValue)) type = _index.NumberValue; return _index.AbstractValue.createTemporalFromBuildFunction(this.$Realm, type, [this], ([o]) => { (0, _invariant2.default)(typeof P === "string"); return t.isValidIdentifier(P) ? t.memberExpression(o, t.identifier(P), false) : t.memberExpression(o, t.stringLiteral(P), true); }, { skipInvariant: true }); }; if (this.isSimpleObject() && this.isIntrinsic()) { return generateAbstractGet(); } else if (this.$Realm.isInPureScope()) { // This object might have leaked to a getter. _singletons.Havoc.value(this.$Realm, this); // The getter might throw anything. return this.$Realm.evaluateWithPossibleThrowCompletion(generateAbstractGet, _index2.TypesDomain.topVal, _index2.ValuesDomain.topVal); } _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); return cv.$Get(P, Receiver); } (0, _invariant2.default)(false); } else if (this.kind === "conditional") { // this is the join of two concrete objects let [cond, ob1, ob2] = this.args; (0, _invariant2.default)(cond instanceof _index.AbstractValue); (0, _invariant2.default)(ob1 instanceof _index.ObjectValue); (0, _invariant2.default)(ob2 instanceof _index.ObjectValue); let d1 = ob1.$GetOwnProperty(P); let d1val = d1 === undefined ? this.$Realm.intrinsics.undefined : (0, _index3.IsDataDescriptor)(this.$Realm, d1) ? d1.value : undefined; let d2 = ob2.$GetOwnProperty(P); let d2val = d2 === undefined ? this.$Realm.intrinsics.undefined : (0, _index3.IsDataDescriptor)(this.$Realm, d2) ? d2.value : undefined; if (d1val === undefined || d2val === undefined) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } (0, _invariant2.default)(d1val instanceof _index.Value); (0, _invariant2.default)(d2val instanceof _index.Value); return _singletons.Join.joinValuesAsConditional(this.$Realm, cond, d1val, d2val); } else { let result; for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); let d = cv.$GetOwnProperty(P); // We do not currently join property getters if (d !== undefined && !(0, _index3.IsDataDescriptor)(this.$Realm, d)) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let cvVal = d === undefined ? this.$Realm.intrinsics.undefined : d.value; if (result === undefined) result = cvVal;else { let cond = _index.AbstractValue.createFromBinaryOp(this.$Realm, "===", this, cv, this.expressionLocation); result = _singletons.Join.joinValuesAsConditional(this.$Realm, cond, cvVal, result); } } (0, _invariant2.default)(result !== undefined); return result; } } $GetPartial(P, Receiver) { if (!(P instanceof _index.AbstractValue)) return this.$Get(P, Receiver); (0, _invariant2.default)(this === Receiver, "TODO #1021"); if (this.values.isTop()) { if (this.isSimpleObject() && this.isIntrinsic()) { return _index.AbstractValue.createTemporalFromBuildFunction(this.$Realm, _index.Value, [this, P], ([o, p]) => t.memberExpression(o, p, true)); } _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { return cv.$GetPartial(P, cv); } (0, _invariant2.default)(false); } else { let result; for (let cv of elements) { let cvVal = cv.$GetPartial(P, cv); if (result === undefined) result = cvVal;else { let cond = _index.AbstractValue.createFromBinaryOp(this.$Realm, "===", this, cv, this.expressionLocation); result = _singletons.Join.joinValuesAsConditional(this.$Realm, cond, cvVal, result); } } (0, _invariant2.default)(result !== undefined); return result; } } // ECMA262 9.1.9 $Set(P, V, Receiver) { if (P instanceof _index.StringValue) P = P.value; (0, _invariant2.default)(this === Receiver, "TODO #1021"); if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); return cv.$Set(P, V, cv); } (0, _invariant2.default)(false); } else { let sawTrue = false; let sawFalse = false; for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); let d = cv.$GetOwnProperty(P); if (d !== undefined && !(0, _index3.IsDataDescriptor)(this.$Realm, d)) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let oldVal = d === undefined ? this.$Realm.intrinsics.empty : d.value; let cond = _index.AbstractValue.createFromBinaryOp(this.$Realm, "===", this, cv, this.expressionLocation); let v = _singletons.Join.joinValuesAsConditional(this.$Realm, cond, V, oldVal); if (cv.$Set(P, v, cv)) sawTrue = true;else sawFalse = true; } if (sawTrue && sawFalse) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } return sawTrue; } } $SetPartial(P, V, Receiver) { if (!(P instanceof _index.AbstractValue)) return this.$Set(P, V, Receiver); (0, _invariant2.default)(this === Receiver, "TODO #1021"); if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); return cv.$SetPartial(P, V, cv); } (0, _invariant2.default)(false); } else { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); let oldVal = this.$GetPartial(P, Receiver); let cond = _index.AbstractValue.createFromBinaryOp(this.$Realm, "===", this, cv, this.expressionLocation); let v = _singletons.Join.joinValuesAsConditional(this.$Realm, cond, V, oldVal); cv.$SetPartial(P, v, cv); } return true; } } // ECMA262 9.1.10 $Delete(P) { if (P instanceof _index.StringValue) P = P.value; if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); return cv.$Delete(P); } (0, _invariant2.default)(false); } else { let sawTrue = false; let sawFalse = false; for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); let d = cv.$GetOwnProperty(P); if (d === undefined) continue; if (!(0, _index3.IsDataDescriptor)(this.$Realm, d)) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } let cond = _index.AbstractValue.createFromBinaryOp(this.$Realm, "===", this, cv, this.expressionLocation); let v = _singletons.Join.joinValuesAsConditional(this.$Realm, cond, this.$Realm.intrinsics.empty, d.value); if (cv.$Set(P, v, cv)) sawTrue = true;else sawFalse = true; } if (sawTrue && sawFalse) { _index.AbstractValue.reportIntrospectionError(this, P); throw new _errors.FatalError(); } return sawTrue; } } $OwnPropertyKeys() { if (this.values.isTop()) { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } let elements = this.values.getElements(); if (elements.size === 1) { for (let cv of elements) { (0, _invariant2.default)(cv instanceof _index.ObjectValue); return cv.$OwnPropertyKeys(); } (0, _invariant2.default)(false); } else { _index.AbstractValue.reportIntrospectionError(this); throw new _errors.FatalError(); } } } exports.default = AbstractObjectValue; /** * 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=AbstractObjectValue.js.map