"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PropertiesImplementation = undefined; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** * 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. */ var _completions = require("../completions.js"); var _realm = require("../realm.js"); var _index = require("../values/index.js"); var _ObjectExpression = require("../evaluators/ObjectExpression"); var _environment = require("../environment.js"); var _errors = require("../errors.js"); var _invariant = require("../invariant.js"); var _invariant2 = _interopRequireDefault(_invariant); var _index2 = require("../methods/index.js"); var _babelTypes = require("babel-types"); var t = _interopRequireWildcard(_babelTypes); var _singletons = require("../singletons.js"); var _strict3 = require("../utils/strict.js"); var _strict4 = _interopRequireDefault(_strict3); 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 }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function StringKey(key) { if (key instanceof _index.StringValue) key = key.value; if (typeof key !== "string") { // The generator currently only supports string keys. throw new _errors.FatalError(); } return key; } function InternalDescriptorPropertyToValue(realm, value) { if (value === undefined) return realm.intrinsics.undefined; if (typeof value === "boolean") return new _index.BooleanValue(realm, value); (0, _invariant2.default)(value instanceof _index.Value); return value; } function InternalGetPropertiesKey(P) { if (typeof P === "string") { return P; } else if (P instanceof _index.StringValue) { return P.value; } else if (P instanceof _index.SymbolValue) { return P; } // otherwise, undefined } function InternalGetPropertiesMap(O, P) { if (typeof P === "string" || P instanceof _index.StringValue) { return O.properties; } else if (P instanceof _index.SymbolValue) { return O.symbols; } else { (0, _invariant2.default)(false); } } function InternalSetProperty(realm, O, P, desc) { var map = InternalGetPropertiesMap(O, P); var key = InternalGetPropertiesKey(P); var propertyBinding = map.get(key); if (propertyBinding === undefined) { propertyBinding = { descriptor: undefined, object: O, key: key }; map.set(key, propertyBinding); } realm.recordModifiedProperty(propertyBinding); propertyBinding.descriptor = desc; } function InternalUpdatedProperty(realm, O, P, oldDesc) { var generator = realm.generator; if (!generator) return; if (!O.isIntrinsic()) return; if (P instanceof _index.SymbolValue) return; if (P instanceof _index.StringValue) P = P.value; (0, _invariant2.default)(!O.isLeakedObject()); // leaked objects are never updated (0, _invariant2.default)(typeof P === "string"); var propertyBinding = InternalGetPropertiesMap(O, P).get(P); (0, _invariant2.default)(propertyBinding !== undefined); // The callers ensure this var desc = propertyBinding.descriptor; if (desc === undefined) { // The property is being deleted if (O === realm.$GlobalObject) { generator.emitGlobalDelete(P, realm.getRunningContext().isStrict); } else { generator.emitPropertyDelete(O, P); } } else { var descValue = desc.value || realm.intrinsics.undefined; (0, _invariant2.default)(descValue instanceof _index.Value); if (oldDesc === undefined) { // The property is being created if (O === realm.$GlobalObject) { if ((0, _index2.IsDataDescriptor)(realm, desc)) { if ((0, _babelTypes.isValidIdentifier)(P) && !desc.configurable && desc.enumerable && desc.writable) { generator.emitGlobalDeclaration(P, descValue); } else if (desc.configurable && desc.enumerable && desc.writable) { generator.emitGlobalAssignment(P, descValue, realm.getRunningContext().isStrict); } else { generator.emitDefineProperty(O, P, desc); } } else { generator.emitDefineProperty(O, P, desc); } } else { if ((0, _index2.IsDataDescriptor)(realm, desc) && desc.configurable && desc.enumerable && desc.writable) { generator.emitPropertyAssignment(O, P, descValue); } else { generator.emitDefineProperty(O, P, desc); } } } else { // The property is being modified if ((0, _index2.equalDescriptors)(desc, oldDesc)) { // only the value is being modified if (O === realm.$GlobalObject) { generator.emitGlobalAssignment(P, descValue, realm.getRunningContext().isStrict); } else { generator.emitPropertyAssignment(O, P, descValue); } } else { generator.emitDefineProperty(O, P, desc, /*isDescChanged*/true); } } } } function leakDescriptor(realm, desc) { if (desc.value) { (0, _invariant2.default)(desc.value instanceof _index.Value, "internal fields should not leak"); _singletons.Leak.leakValue(realm, desc.value); } if (desc.get) { _singletons.Leak.leakValue(realm, desc.get); } if (desc.set) { _singletons.Leak.leakValue(realm, desc.set); } } // Determines if an object with parent O may create its own property P. function parentPermitsChildPropertyCreation(realm, O, P) { var ownDesc = O.$GetOwnProperty(P); var ownDescValue = !ownDesc ? realm.intrinsics.undefined : ownDesc.value === undefined ? realm.intrinsics.undefined : ownDesc.value; (0, _invariant2.default)(ownDescValue instanceof _index.Value); if (!ownDesc || ownDescValue.mightHaveBeenDeleted()) { // O might not object, so first ask its parent var parent = O.$GetPrototypeOf(); parent.throwIfNotConcrete(); //TODO #1016: deal with abstract parents if (!(parent instanceof _index.NullValue)) { if (!parentPermitsChildPropertyCreation(realm, parent, P)) return false; } // Parent is OK, so if O does not object return true if (!ownDesc) return true; // O has no opinion of its ownDesc } (0, _invariant2.default)(ownDesc !== undefined); // O might have a property P and so might object if ((0, _index2.IsDataDescriptor)(realm, ownDesc)) { if (ownDesc.writable) { // The grand parent does not object so it is OK that parent does not have P // If parent does have P, it is also OK because it is a writable data property return true; } } // If parent does not have property P, this is too pessimistic, but that is // the caller's problem. return false; } var PropertiesImplementation = exports.PropertiesImplementation = function () { function PropertiesImplementation() { _classCallCheck(this, PropertiesImplementation); } _createClass(PropertiesImplementation, [{ key: "OrdinarySet", // ECMA262 9.1.9.1 value: function OrdinarySet(realm, O, P, V, Receiver) { if (O.isLeakedObject()) { _singletons.Leak.leakValue(realm, V); if (realm.generator) { realm.generator.emitPropertyAssignment(O, StringKey(P), V); } return true; } var weakDeletion = V.mightHaveBeenDeleted(); // 1. Assert: IsPropertyKey(P) is true. (0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "expected property key"); // 2. Let ownDesc be ? O.[[GetOwnProperty]](P). var ownDesc = void 0; var existingBinding = InternalGetPropertiesMap(O, P).get(InternalGetPropertiesKey(P)); if (existingBinding !== undefined || !(O.isPartialObject() && O.isSimpleObject())) ownDesc = O.$GetOwnProperty(P); var ownDescValue = !ownDesc ? realm.intrinsics.undefined : ownDesc.value === undefined ? realm.intrinsics.undefined : ownDesc.value; (0, _invariant2.default)(ownDescValue instanceof _index.Value); // 3. If ownDesc is undefined (or might be), then if (!ownDesc || ownDescValue.mightHaveBeenDeleted()) { // a. Let parent be ? O.[[GetPrototypeOf]](). var parent = O.$GetPrototypeOf(); parent.throwIfNotConcrete(); //TODO #1016: deal with abstract parents // b. If parent is not null, then if (!(parent instanceof _index.NullValue)) { if (!ownDesc) { // i. Return ? parent.[[Set]](P, V, Receiver). return parent.$Set(P, V, Receiver); } // But since we don't know if O has its own property P, the parent might // actually have a say. Give up, unless the parent would be OK with it. if (!parentPermitsChildPropertyCreation(realm, parent, P)) { (0, _invariant2.default)(ownDescValue instanceof _index.AbstractValue); _index.AbstractValue.reportIntrospectionError(ownDescValue); throw new _errors.FatalError(); } // Since the parent is OK with us creating a local property for O // we can carry on as if there were no parent. } // i. Let ownDesc be the PropertyDescriptor{[[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}. if (!ownDesc) ownDesc = { value: realm.intrinsics.undefined, writable: true, enumerable: true, configurable: true }; } // joined descriptors need special treatment var joinCondition = ownDesc.joinCondition; if (joinCondition !== undefined) { var descriptor2 = ownDesc.descriptor2; ownDesc = ownDesc.descriptor1; var _Path$withCondition = _singletons.Path.withCondition(joinCondition, function () { return ownDesc !== undefined ? realm.evaluateForEffects(function () { return new _index.BooleanValue(realm, OrdinarySetHelper()); }) : (0, _realm.construct_empty_effects)(realm); }), _Path$withCondition2 = _slicedToArray(_Path$withCondition, 5), compl1 = _Path$withCondition2[0], gen1 = _Path$withCondition2[1], bindings1 = _Path$withCondition2[2], properties1 = _Path$withCondition2[3], createdObj1 = _Path$withCondition2[4]; ownDesc = descriptor2; var _Path$withInverseCond = _singletons.Path.withInverseCondition(joinCondition, function () { return ownDesc !== undefined ? realm.evaluateForEffects(function () { return new _index.BooleanValue(realm, OrdinarySetHelper()); }) : (0, _realm.construct_empty_effects)(realm); }), _Path$withInverseCond2 = _slicedToArray(_Path$withInverseCond, 5), compl2 = _Path$withInverseCond2[0], gen2 = _Path$withInverseCond2[1], bindings2 = _Path$withInverseCond2[2], properties2 = _Path$withInverseCond2[3], createdObj2 = _Path$withInverseCond2[4]; // Join the effects, creating an abstract view of what happened, regardless // of the actual value of ownDesc.joinCondition. var joinedEffects = _singletons.Join.joinEffects(realm, joinCondition, [compl1, gen1, bindings1, properties1, createdObj1], [compl2, gen2, bindings2, properties2, createdObj2]); var completion = joinedEffects[0]; if (completion instanceof _completions.PossiblyNormalCompletion) { // in this case one of the branches may complete abruptly, which means that // not all control flow branches join into one flow at this point. // Consequently we have to continue tracking changes until the point where // all the branches come together into one. completion = realm.composeWithSavedCompletion(completion); } // Note that the effects of (non joining) abrupt branches are not included // in joinedEffects, but are tracked separately inside completion. realm.applyEffects(joinedEffects); // return or throw completion if (completion instanceof _completions.AbruptCompletion) throw completion; (0, _invariant2.default)(completion instanceof _index.Value); return _singletons.To.ToBooleanPartial(realm, completion); } return OrdinarySetHelper(); function OrdinarySetHelper() { (0, _invariant2.default)(ownDesc !== undefined); (0, _invariant2.default)(ownDescValue instanceof _index.Value); // 4. If IsDataDescriptor(ownDesc) is true, then if ((0, _index2.IsDataDescriptor)(realm, ownDesc)) { // a. If ownDesc.[[Writable]] is false, return false. if (!ownDesc.writable && !weakDeletion) { // The write will fail if the property actually exists if (ownDescValue.mightHaveBeenDeleted()) { // But maybe it does not and thus would succeed. // Since we don't know what will happen, give up for now. (0, _invariant2.default)(ownDescValue instanceof _index.AbstractValue); _index.AbstractValue.reportIntrospectionError(ownDescValue); throw new _errors.FatalError(); } return false; } // b. If Type(Receiver) is not Object, return false. Receiver = Receiver.throwIfNotConcrete(); if (!(Receiver instanceof _index.ObjectValue)) return false; // c. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P). var existingDescriptor = void 0; var binding = InternalGetPropertiesMap(Receiver, P).get(InternalGetPropertiesKey(P)); if (binding !== undefined || !(Receiver.isPartialObject() && Receiver.isSimpleObject())) existingDescriptor = Receiver.$GetOwnProperty(P); if (existingDescriptor !== undefined) { if (existingDescriptor.descriptor1 === ownDesc) existingDescriptor = ownDesc;else if (existingDescriptor.descriptor2 === ownDesc) existingDescriptor = ownDesc; } var existingDescValue = !existingDescriptor ? realm.intrinsics.undefined : existingDescriptor.value === undefined ? realm.intrinsics.undefined : existingDescriptor.value; (0, _invariant2.default)(existingDescValue instanceof _index.Value); // d. If existingDescriptor is not undefined, then if (existingDescriptor !== undefined) { // i. If IsAccessorDescriptor(existingDescriptor) is true, return false. if ((0, _index2.IsAccessorDescriptor)(realm, existingDescriptor)) { (0, _invariant2.default)(!existingDescValue.mightHaveBeenDeleted(), "should not fail until weak deletes of accessors are suppported"); return false; } // ii. If existingDescriptor.[[Writable]] is false, return false. if (!existingDescriptor.writable && !(weakDeletion && existingDescriptor.configurable)) { // If we are not sure the receiver actually has a property P we can't just return false here. if (existingDescValue.mightHaveBeenDeleted()) { (0, _invariant2.default)(existingDescValue instanceof _index.AbstractValue); _index.AbstractValue.reportIntrospectionError(existingDescValue); throw new _errors.FatalError(); } return false; } // iii. Let valueDesc be the PropertyDescriptor{[[Value]]: V}. var valueDesc = { value: V }; // iv. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc). if (weakDeletion || existingDescValue.mightHaveBeenDeleted()) { // At this point we are not actually sure that Receiver actually has // a property P, however, if it has, we are sure that its a data property, // and that redefining the property with valueDesc will not change the // attributes of the property, so we delete it to make things nice for $DefineOwnProperty. Receiver.$Delete(P); valueDesc = existingDescriptor; valueDesc.value = V; } return Receiver.$DefineOwnProperty(P, valueDesc); } else { // e. Else Receiver does not currently have a property P, // i. Return ? CreateDataProperty(Receiver, P, V). return _singletons.Create.CreateDataProperty(realm, Receiver, P, V); } } // 5. Assert: IsAccessorDescriptor(ownDesc) is true. (0, _invariant2.default)((0, _index2.IsAccessorDescriptor)(realm, ownDesc), "expected accessor"); // 6. Let setter be ownDesc.[[Set]]. var setter = "set" in ownDesc ? ownDesc.set : undefined; // 7. If setter is undefined, return false. if (!setter || setter instanceof _index.UndefinedValue) return false; // 8. Perform ? Call(setter, Receiver, « V »). (0, _index2.Call)(realm, setter.throwIfNotConcrete(), Receiver, [V]); // 9. Return true. return true; } } // ECMA262 6.2.4.4 }, { key: "FromPropertyDescriptor", value: function FromPropertyDescriptor(realm, Desc) { // 1. If Desc is undefined, return undefined. if (!Desc) return realm.intrinsics.undefined; // 2. Let obj be ObjectCreate(%ObjectPrototype%). var obj = _singletons.Create.ObjectCreate(realm, realm.intrinsics.ObjectPrototype); // 3. Assert: obj is an extensible ordinary object with no own properties. (0, _invariant2.default)(obj.getExtensible(), "expected an extensible object"); (0, _invariant2.default)(!obj.properties.size, "expected an object with no own properties"); // 4. If Desc has a [[Value]] field, then var success = true; if ("value" in Desc) { (0, _invariant2.default)(Desc.value instanceof _index.Value); // a. Perform CreateDataProperty(obj, "value", Desc.[[Value]]). success = _singletons.Create.CreateDataProperty(realm, obj, "value", Desc.value) && success; } // 5. If Desc has a [[Writable]] field, then if ("writable" in Desc) { (0, _invariant2.default)(Desc.writable !== undefined); // a. Perform CreateDataProperty(obj, "writable", Desc.[[Writable]]). success = _singletons.Create.CreateDataProperty(realm, obj, "writable", new _index.BooleanValue(realm, Desc.writable)) && success; } // 6. If Desc has a [[Get]] field, then if ("get" in Desc) { (0, _invariant2.default)(Desc.get !== undefined); // a. Perform CreateDataProperty(obj, "get", Desc.[[Get]]). success = _singletons.Create.CreateDataProperty(realm, obj, "get", Desc.get) && success; } // 7. If Desc has a [[Set]] field, then if ("set" in Desc) { (0, _invariant2.default)(Desc.set !== undefined); // a. Perform CreateDataProperty(obj, "set", Desc.[[Set]]). success = _singletons.Create.CreateDataProperty(realm, obj, "set", Desc.set) && success; } // 8. If Desc has an [[Enumerable]] field, then if ("enumerable" in Desc) { (0, _invariant2.default)(Desc.enumerable !== undefined); // a. Perform CreateDataProperty(obj, "enumerable", Desc.[[Enumerable]]). success = _singletons.Create.CreateDataProperty(realm, obj, "enumerable", new _index.BooleanValue(realm, Desc.enumerable)) && success; } // 9. If Desc has a [[Configurable]] field, then if ("configurable" in Desc) { (0, _invariant2.default)(Desc.configurable !== undefined); // a. Perform CreateDataProperty(obj, "configurable", Desc.[[Configurable]]). success = _singletons.Create.CreateDataProperty(realm, obj, "configurable", new _index.BooleanValue(realm, Desc.configurable)) && success; } // 10. Assert: all of the above CreateDataProperty operations return true. (0, _invariant2.default)(success, "fails to create data property"); // 11. Return obj. return obj; } // }, { key: "OrdinaryDelete", value: function OrdinaryDelete(realm, O, P) { // 1. Assert: IsPropertyKey(P) is true. (0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "expected a property key"); // 2. Let desc be ? O.[[GetOwnProperty]](P). var desc = O.$GetOwnProperty(P); // 3. If desc is undefined, return true. if (!desc) { if (O.isLeakedObject()) { if (realm.generator) { realm.generator.emitPropertyDelete(O, StringKey(P)); } } return true; } // 4. If desc.[[Configurable]] is true, then if (desc.configurable) { if (O.isLeakedObject()) { if (realm.generator) { realm.generator.emitPropertyDelete(O, StringKey(P)); } return true; } // a. Remove the own property with name P from O. var key = InternalGetPropertiesKey(P); var map = InternalGetPropertiesMap(O, P); var propertyBinding = map.get(key); (0, _invariant2.default)(propertyBinding !== undefined); realm.recordModifiedProperty(propertyBinding); propertyBinding.descriptor = undefined; InternalUpdatedProperty(realm, O, P, desc); // b. Return true. return true; } // 5. Return false. return false; } // ECMA262 7.3.8 }, { key: "DeletePropertyOrThrow", value: function DeletePropertyOrThrow(realm, O, P) { // 1. Assert: Type(O) is Object. (0, _invariant2.default)(O instanceof _index.ObjectValue, "expected an object"); // 2. Assert: IsPropertyKey(P) is true. (0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "expected a property key"); // 3. Let success be ? O.[[Delete]](P). var success = O.$Delete(P); // 4. If success is false, throw a TypeError exception. if (!success) { throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "couldn't delete property"); } // 5. Return success. return success; } // ECMA262 6.2.4.6 }, { key: "CompletePropertyDescriptor", value: function CompletePropertyDescriptor(realm, Desc) { // 1. Assert: Desc is a Property Descriptor. // 2. Let like be Record{[[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false}. var like = { value: realm.intrinsics.undefined, get: realm.intrinsics.undefined, set: realm.intrinsics.undefined, writable: false, enumerable: false, configurable: false }; // 3. If either IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then if ((0, _index2.IsGenericDescriptor)(realm, Desc) || (0, _index2.IsDataDescriptor)(realm, Desc)) { // a. If Desc does not have a [[Value]] field, set Desc.[[Value]] to like.[[Value]]. if (!("value" in Desc)) Desc.value = like.value; // b. If Desc does not have a [[Writable]] field, set Desc.[[Writable]] to like.[[Writable]]. if (!("writable" in Desc)) Desc.writable = like.writable; } else { // 4. Else, // a. If Desc does not have a [[Get]] field, set Desc.[[Get]] to like.[[Get]]. if (!("get" in Desc)) Desc.get = like.get; // b. If Desc does not have a [[Set]] field, set Desc.[[Set]] to like.[[Set]]. if (!("set" in Desc)) Desc.set = like.set; } // 5. If Desc does not have an [[Enumerable]] field, set Desc.[[Enumerable]] to like.[[Enumerable]]. if (!("enumerable" in Desc)) Desc.enumerable = like.enumerable; // 6. If Desc does not have a [[Configurable]] field, set Desc.[[Configurable]] to like.[[Configurable]]. if (!("configurable" in Desc)) Desc.configurable = like.configurable; // 7. Return Desc. return Desc; } // ECMA262 9.1.6.2 }, { key: "IsCompatiblePropertyDescriptor", value: function IsCompatiblePropertyDescriptor(realm, extensible, Desc, current) { // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, Extensible, Desc, Current). return this.ValidateAndApplyPropertyDescriptor(realm, undefined, undefined, extensible, Desc, current); } // ECMA262 9.1.6.3 }, { key: "ValidateAndApplyPropertyDescriptor", value: function ValidateAndApplyPropertyDescriptor(realm, O, P, extensible, Desc, current) { // 1. Assert: If O is not undefined, then IsPropertyKey(P) is true. if (O !== undefined) { (0, _invariant2.default)(P !== undefined); (0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P)); } if (current && current.joinCondition !== undefined) { var jc = current.joinCondition; if (_singletons.Path.implies(jc)) current = current.descriptor1;else if (!_index.AbstractValue.createFromUnaryOp(realm, "!", jc, true).mightNotBeTrue()) current = current.descriptor2; } // 2. If current is undefined, then if (!current) { // a. If extensible is false, return false. if (!extensible) return false; // b. Assert: extensible is true. (0, _invariant2.default)(extensible === true, "expected extensible to be true"); if (O !== undefined && O.isLeakedObject() && P !== undefined) { leakDescriptor(realm, Desc); if (realm.generator) { realm.generator.emitDefineProperty(O, StringKey(P), Desc); } return true; } // c. If IsGenericDescriptor(Desc) is true or IsDataDescriptor(Desc) is true, then if ((0, _index2.IsGenericDescriptor)(realm, Desc) || (0, _index2.IsDataDescriptor)(realm, Desc)) { // i. If O is not undefined, create an own data property named P of object O whose [[Value]], // [[Writable]], [[Enumerable]] and [[Configurable]] attribute values are described by Desc. If the // value of an attribute field of Desc is absent, the attribute of the newly created property is set // to its default value. if (O !== undefined) { (0, _invariant2.default)(P !== undefined); InternalSetProperty(realm, O, P, { value: "value" in Desc ? Desc.value : realm.intrinsics.undefined, writable: "writable" in Desc ? Desc.writable : false, enumerable: "enumerable" in Desc ? Desc.enumerable : false, configurable: "configurable" in Desc ? Desc.configurable : false }); InternalUpdatedProperty(realm, O, P, undefined); } } else { // d. Else Desc must be an accessor Property Descriptor, // i. If O is not undefined, create an own accessor property named P of object O whose [[Get]], // [[Set]], [[Enumerable]] and [[Configurable]] attribute values are described by Desc. If the value // of an attribute field of Desc is absent, the attribute of the newly created property is set to its // default value. if (O !== undefined) { (0, _invariant2.default)(P !== undefined); InternalSetProperty(realm, O, P, { get: "get" in Desc ? Desc.get : realm.intrinsics.undefined, set: "set" in Desc ? Desc.set : realm.intrinsics.undefined, enumerable: "enumerable" in Desc ? Desc.enumerable : false, configurable: "configurable" in Desc ? Desc.configurable : false }); InternalUpdatedProperty(realm, O, P, undefined); } } // e. Return true. return true; } this.ThrowIfMightHaveBeenDeleted(current.value); // 3. Return true, if every field in Desc is absent. if (!Object.keys(Desc).length) return true; // 4. Return true, if every field in Desc also occurs in current and the value of every field in Desc is the // same value as the corresponding field in current when compared using the SameValue algorithm. var identical = true; for (var field in Desc) { if (!(field in current)) { identical = false; } else { var dval = InternalDescriptorPropertyToValue(realm, Desc[field]); var cval = InternalDescriptorPropertyToValue(realm, current[field]); if (dval instanceof _index.ConcreteValue && cval instanceof _index.ConcreteValue) identical = (0, _index2.SameValue)(realm, dval, cval);else { identical = dval === cval; // This might be false now but true at runtime. This does not // matter because the logic for non identical values will still // do the right thing in the cases below that does not blow up // when dealing with an abstract value. } } if (!identical) break; } if (identical) { return true; } // 5. If the [[Configurable]] field of current is false, then if (!current.configurable) { // a. Return false, if the [[Configurable]] field of Desc is true. if (Desc.configurable) return false; // b. Return false, if the [[Enumerable]] field of Desc is present and the [[Enumerable]] fields of current and Desc are the Boolean negation of each other. if ("enumerable" in Desc && Desc.enumerable !== current.enumerable) { return false; } } if (O !== undefined && O.isLeakedObject() && P !== undefined) { leakDescriptor(realm, Desc); if (realm.generator) { realm.generator.emitDefineProperty(O, StringKey(P), Desc); } return true; } var oldDesc = current; current = (0, _index2.cloneDescriptor)(current); (0, _invariant2.default)(current !== undefined); // 6. If IsGenericDescriptor(Desc) is true, no further validation is required. if ((0, _index2.IsGenericDescriptor)(realm, Desc)) {} else if ((0, _index2.IsDataDescriptor)(realm, current) !== (0, _index2.IsDataDescriptor)(realm, Desc)) { // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have different results, then // a. Return false, if the [[Configurable]] field of current is false. if (!current.configurable) return false; // b. If IsDataDescriptor(current) is true, then if ((0, _index2.IsDataDescriptor)(realm, current)) { // i. If O is not undefined, convert the property named P of object O from a data property to an accessor property. // Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and set the rest of the property's attributes to their default values. if (O !== undefined) { (0, _invariant2.default)(P !== undefined); var key = InternalGetPropertiesKey(P); var propertyBinding = InternalGetPropertiesMap(O, P).get(key); (0, _invariant2.default)(propertyBinding !== undefined); delete current.writable; delete current.value; current.get = realm.intrinsics.undefined; current.set = realm.intrinsics.undefined; } } else { // c. Else, // i. If O is not undefined, convert the property named P of object O from an accessor property to a data property. Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and set the rest of the property's attributes to their default values. if (O !== undefined) { (0, _invariant2.default)(P !== undefined); var _key = InternalGetPropertiesKey(P); var _propertyBinding = InternalGetPropertiesMap(O, P).get(_key); (0, _invariant2.default)(_propertyBinding !== undefined); delete current.get; delete current.set; current.writable = false; current.value = realm.intrinsics.undefined; } } } else if ((0, _index2.IsDataDescriptor)(realm, current) && (0, _index2.IsDataDescriptor)(realm, Desc)) { // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then // a. If the [[Configurable]] field of current is false, then if (!current.configurable) { // i. Return false, if the [[Writable]] field of current is false and the [[Writable]] field of Desc is true. if (!current.writable && Desc.writable) return false; // ii. If the [[Writable]] field of current is false, then if (!current.writable) { // 1. Return false, if the [[Value]] field of Desc is present and SameValue(Desc.[[Value]], current.[[Value]]) is false. var descValue = Desc.value || realm.intrinsics.undefined; (0, _invariant2.default)(descValue instanceof _index.Value); var currentValue = current.value || realm.intrinsics.undefined; (0, _invariant2.default)(currentValue instanceof _index.Value); if (Desc.value && !(0, _index2.SameValuePartial)(realm, descValue, currentValue)) { return false; } } } else { // b. Else the [[Configurable]] field of current is true, so any change is acceptable. } } else { // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) are both true, // a. If the [[Configurable]] field of current is false, then if (!current.configurable) { // i. Return false, if the [[Set]] field of Desc is present and SameValue(Desc.[[Set]], current.[[Set]]) is false. if (Desc.set && !(0, _index2.SameValuePartial)(realm, Desc.set, current.set || realm.intrinsics.undefined)) return false; // ii. Return false, if the [[Get]] field of Desc is present and SameValue(Desc.[[Get]], current.[[Get]]) is false. if (Desc.get && !(0, _index2.SameValuePartial)(realm, Desc.get, current.get || realm.intrinsics.undefined)) return false; } } // 10. If O is not undefined, then if (O !== undefined) { (0, _invariant2.default)(P !== undefined); var _key2 = InternalGetPropertiesKey(P); var map = InternalGetPropertiesMap(O, P); var _propertyBinding2 = map.get(_key2); if (_propertyBinding2 === undefined) { _propertyBinding2 = { descriptor: undefined, object: O, key: _key2 }; realm.recordModifiedProperty(_propertyBinding2); _propertyBinding2.descriptor = current; map.set(_key2, _propertyBinding2); } else if (_propertyBinding2.descriptor === undefined) { realm.recordModifiedProperty(_propertyBinding2); _propertyBinding2.descriptor = current; } else { realm.recordModifiedProperty(_propertyBinding2); _propertyBinding2.descriptor = current; } // a. For each field of Desc that is present, set the corresponding attribute of the property named P of // object O to the value of the field. for (var _field in Desc) { current[_field] = Desc[_field]; }InternalUpdatedProperty(realm, O, P, oldDesc); } // 11. Return true. return true; } // ECMA262 9.1.6.1 }, { key: "OrdinaryDefineOwnProperty", value: function OrdinaryDefineOwnProperty(realm, O, P, Desc) { (0, _invariant2.default)(O instanceof _index.ObjectValue); // 1. Let current be ? O.[[GetOwnProperty]](P). var current = void 0; var binding = InternalGetPropertiesMap(O, P).get(InternalGetPropertiesKey(P)); if (binding !== undefined || !(O.isPartialObject() && O.isSimpleObject())) current = O.$GetOwnProperty(P); // 2. Let extensible be the value of the [[Extensible]] internal slot of O. var extensible = O.getExtensible(); // 3. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current). return this.ValidateAndApplyPropertyDescriptor(realm, O, P, extensible, Desc, current); } // ECMA262 19.1.2.3.1 }, { key: "ObjectDefineProperties", value: function ObjectDefineProperties(realm, O, Properties) { // 1. If Type(O) is not Object, throw a TypeError exception. if (O.mightNotBeObject()) { if (O.mightBeObject()) O.throwIfNotConcrete(); throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError); } (0, _invariant2.default)(O instanceof _index.ObjectValue || O instanceof _index.AbstractObjectValue); // 2. Let props be ? ToObject(Properties). var props = _singletons.To.ToObject(realm, Properties.throwIfNotConcrete()); // 3. Let keys be ? props.[[OwnPropertyKeys]](). var keys = props.$OwnPropertyKeys(); // 4. Let descriptors be a new empty List. var descriptors = []; // 5. Repeat for each element nextKey of keys in List order, var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var nextKey = _step.value; // a. Let propDesc be ? props.[[GetOwnProperty]](nextKey). var propDesc = props.$GetOwnProperty(nextKey); // b. If propDesc is not undefined and propDesc.[[Enumerable]] is true, then if (propDesc && propDesc.enumerable) { this.ThrowIfMightHaveBeenDeleted(propDesc.value); // i. Let descObj be ? Get(props, nextKey). var descObj = (0, _index2.Get)(realm, props, nextKey); // ii. Let desc be ? ToPropertyDescriptor(descObj). var desc = _singletons.To.ToPropertyDescriptor(realm, descObj); // iii. Append the pair (a two element List) consisting of nextKey and desc to the end of descriptors. descriptors.push([nextKey, desc]); } } // 6. For each pair from descriptors in list order, } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = descriptors[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var pair = _step2.value; // a. Let P be the first element of pair. var P = pair[0]; // b. Let desc be the second element of pair. var desc = pair[1]; // c. Perform ? DefinePropertyOrThrow(O, P, desc). this.DefinePropertyOrThrow(realm, O, P, desc); } // 7. Return O. } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return O; } // ECMA262 7.3.3 }, { key: "Set", value: function Set(realm, O, P, V, Throw) { // 1. Assert: Type(O) is Object. // 2. Assert: IsPropertyKey(P) is true. (0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "expected property key"); // 3. Assert: Type(Throw) is Boolean. (0, _invariant2.default)(typeof Throw === "boolean", "expected boolean"); // 4. Let success be ? O.[[Set]](P, V, O). var success = O.$Set(P, V, O); // 5. If success is false and Throw is true, throw a TypeError exception. if (success === false && Throw === true) { throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError); } // 6. Return success. return success; } // ECMA262 7.3.7 }, { key: "DefinePropertyOrThrow", value: function DefinePropertyOrThrow(realm, O, P, desc) { // 1. Assert: Type(O) is Object. // 2. Assert: IsPropertyKey(P) is true. (0, _invariant2.default)(typeof P === "string" || (0, _index2.IsPropertyKey)(realm, P), "expected property key"); // 3. Let success be ? O.[[DefineOwnProperty]](P, desc). var success = O.$DefineOwnProperty(P, desc); // 4. If success is false, throw a TypeError exception. if (success === false) { throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError); } // 5. Return success. return success; } // ECMA262 6.2.3.2 }, { key: "PutValue", value: function PutValue(realm, V, W) { W = W.promoteEmptyToUndefined(); // The following two steps are not necessary as we propagate completions with exceptions. // 1. ReturnIfAbrupt(V). // 2. ReturnIfAbrupt(W). // 3. If Type(V) is not Reference, throw a ReferenceError exception. if (!(V instanceof _environment.Reference)) { throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError, "can't put a value to a non-reference"); } // 4. Let base be GetBase(V). var base = _singletons.Environment.GetBase(realm, V); // 5. If IsUnresolvableReference(V) is true, then if (_singletons.Environment.IsUnresolvableReference(realm, V)) { // a. If IsStrictReference(V) is true, then if (_singletons.Environment.IsStrictReference(realm, V)) { // i. Throw a ReferenceError exception. throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError); } // b. Let globalObj be GetGlobalObject(). var globalObj = (0, _index2.GetGlobalObject)(realm); // c. Return ? Set(globalObj, GetReferencedName(V), W, false). return this.Set(realm, globalObj, _singletons.Environment.GetReferencedName(realm, V), W, false); } // 6. Else if IsPropertyReference(V) is true, then if (_singletons.Environment.IsPropertyReference(realm, V)) { // a. If HasPrimitiveBase(V) is true, then if (_singletons.Environment.HasPrimitiveBase(realm, V)) { // i. Assert: In realm case, base will never be null or undefined. (0, _invariant2.default)(base instanceof _index.Value && !(0, _index2.HasSomeCompatibleType)(base, _index.UndefinedValue, _index.NullValue)); // ii. Set base to ToObject(base). base = _singletons.To.ToObjectPartial(realm, base); } (0, _invariant2.default)(base instanceof _index.ObjectValue || base instanceof _index.AbstractObjectValue); // b. Let succeeded be ? base.[[Set]](GetReferencedName(V), W, GetThisValue(V)). var succeeded = base.$SetPartial(_singletons.Environment.GetReferencedNamePartial(realm, V), W, (0, _index2.GetThisValue)(realm, V)); // c. If succeeded is false and IsStrictReference(V) is true, throw a TypeError exception. if (succeeded === false && _singletons.Environment.IsStrictReference(realm, V)) { throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError); } // d. Return. return; } // 7. Else base must be an Environment Record, if (base instanceof _environment.EnvironmentRecord) { // a. Return ? base.SetMutableBinding(GetReferencedName(V), W, IsStrictReference(V)) (see 8.1.1). var referencedName = _singletons.Environment.GetReferencedName(realm, V); (0, _invariant2.default)(typeof referencedName === "string"); return base.SetMutableBinding(referencedName, W, _singletons.Environment.IsStrictReference(realm, V)); } (0, _invariant2.default)(false); } // ECMA262 9.4.2.4 }, { key: "ArraySetLength", value: function ArraySetLength(realm, A, Desc) { // 1. If the [[Value]] field of Desc is absent, then var DescValue = Desc.value; if (!DescValue) { // a. Return OrdinaryDefineOwnProperty(A, "length", Desc). return this.OrdinaryDefineOwnProperty(realm, A, "length", Desc); } (0, _invariant2.default)(DescValue instanceof _index.Value); // 2. Let newLenDesc be a copy of Desc. var newLenDesc = Object.assign({}, Desc); // 3. Let newLen be ? ToUint32(Desc.[[Value]]). var newLen = _singletons.To.ToUint32(realm, DescValue); // 4. Let numberLen be ? ToNumber(Desc.[[Value]]). var numberLen = _singletons.To.ToNumber(realm, DescValue); // 5. If newLen ≠ numberLen, throw a RangeError exception. if (newLen !== numberLen) { throw realm.createErrorThrowCompletion(realm.intrinsics.RangeError, "should be a uint"); } // 6. Set newLenDesc.[[Value]] to newLen. newLenDesc.value = new _index.NumberValue(realm, newLen); // 7. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). var oldLenDesc = this.OrdinaryGetOwnProperty(realm, A, "length"); // 8. Assert: oldLenDesc will never be undefined or an accessor descriptor because Array objects are created // with a length data property that cannot be deleted or reconfigured. (0, _invariant2.default)(oldLenDesc !== undefined && !(0, _index2.IsAccessorDescriptor)(realm, oldLenDesc), "cannot be undefined or an accessor descriptor"); // 9. Let oldLen be oldLenDesc.[[Value]]. var oldLen = oldLenDesc.value; (0, _invariant2.default)(oldLen instanceof _index.Value); oldLen = oldLen.throwIfNotConcrete(); (0, _invariant2.default)(oldLen instanceof _index.NumberValue, "should be a number"); oldLen = oldLen.value; // 10. If newLen ≥ oldLen, then if (newLen >= oldLen) { // a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc). return this.OrdinaryDefineOwnProperty(realm, A, "length", newLenDesc); } // 11. If oldLenDesc.[[Writable]] is false, return false. if (!oldLenDesc.writable) return false; // 12. If newLenDesc.[[Writable]] is absent or has the value true, let newWritable be true. var newWritable = void 0; if (!("writable" in newLenDesc) || newLenDesc.writable === true) { newWritable = true; } else { // 13. Else, // a. Need to defer setting the [[Writable]] attribute to false in case any elements cannot be deleted. // b. Let newWritable be false. newWritable = false; // c. Set newLenDesc.[[Writable]] to true. newLenDesc.writable = true; } // 14. Let succeeded be ! OrdinaryDefineOwnProperty(A, "length", newLenDesc). var succeeded = this.OrdinaryDefineOwnProperty(realm, A, "length", newLenDesc); // 15. If succeeded is false, return false. if (succeeded === false) return false; // Here we diverge from the spec: instead of traversing all indices from // oldLen to newLen, only the indices that are actually present are touched. var oldLenCopy = oldLen; var keys = Array.from(A.properties.keys()).map(function (x) { return parseInt(x, 10); }).filter(function (x) { return newLen <= x && x <= oldLenCopy; }).sort().reverse(); // 16. While newLen < oldLen repeat, var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = keys[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var key = _step3.value; // a. Set oldLen to oldLen - 1. oldLen = key; // b. Let deleteSucceeded be ! A.[[Delete]](! ToString(oldLen)). var deleteSucceeded = A.$Delete(oldLen + ""); // c. If deleteSucceeded is false, then if (deleteSucceeded === false) { // i. Set newLenDesc.[[Value]] to oldLen + 1. newLenDesc.value = new _index.NumberValue(realm, oldLen + 1); // ii. If newWritable is false, set newLenDesc.[[Writable]] to false. if (newWritable === false) newLenDesc.writable = false; // iii. Let succeeded be ! OrdinaryDefineOwnProperty(A, "length", newLenDesc). succeeded = this.OrdinaryDefineOwnProperty(realm, A, "length", newLenDesc); // iv. Return false. return false; } } // 17. If newWritable is false, then } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } if (!newWritable) { // a. Return OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor{[[Writable]]: false}). This call will always return true. return this.OrdinaryDefineOwnProperty(realm, A, "length", { writable: false }); } // 18. Return true. return true; } // ECMA262 9.1.5.1 }, { key: "OrdinaryGetOwnProperty", value: function OrdinaryGetOwnProperty(realm, O, P) { if (O.isLeakedObject()) { (0, _invariant2.default)(realm.generator); var pname = realm.generator.getAsPropertyNameExpression(StringKey(P)); var absVal = _index.AbstractValue.createTemporalFromBuildFunction(realm, _index.Value, [O], function (_ref) { var _ref2 = _slicedToArray(_ref, 1), node = _ref2[0]; return t.memberExpression(node, pname, !t.isIdentifier(pname)); }); // TODO: We can't be sure what the descriptor will be, but the value will be abstract. return { configurable: true, enumerable: true, value: absVal, writable: true }; } // 1. Assert: IsPropertyKey(P) is true. (0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "expected a property key"); // 2. If O does not have an own property with key P, return undefined. var existingBinding = InternalGetPropertiesMap(O, P).get(InternalGetPropertiesKey(P)); if (!existingBinding) { if (O.isPartialObject()) { (0, _invariant2.default)(realm.useAbstractInterpretation); // __makePartial will already have thrown an error if not if (O.isSimpleObject()) { if (P instanceof _index.StringValue) P = P.value; if (typeof P === "string") { // In this case it is safe to defer the property access to runtime (at this point in time) (0, _invariant2.default)(realm.generator); var _pname = realm.generator.getAsPropertyNameExpression(P); var _absVal = _index.AbstractValue.createTemporalFromBuildFunction(realm, _index.Value, [O], function (_ref3) { var _ref4 = _slicedToArray(_ref3, 1), node = _ref4[0]; return t.memberExpression(node, _pname, !t.isIdentifier(_pname)); }); return { configurable: true, enumerable: true, value: _absVal, writable: true }; } else { (0, _invariant2.default)(P instanceof _index.SymbolValue); // Simple objects don't have symbol properties return undefined; } } _index.AbstractValue.reportIntrospectionError(O, P); throw new _errors.FatalError(); } return undefined; } realm.callReportPropertyAccess(existingBinding); if (!existingBinding.descriptor) return undefined; // 3. Let D be a newly created Property Descriptor with no fields. var D = {}; // 4. Let X be O's own property whose key is P. var X = existingBinding.descriptor; (0, _invariant2.default)(X !== undefined); if (X.joinCondition !== undefined) { D.joinCondition = X.joinCondition; D.descriptor1 = X.descriptor1; D.descriptor2 = X.descriptor2; return D; } // 5. If X is a data property, then if ((0, _index2.IsDataDescriptor)(realm, X)) { var value = X.value; if (O.isPartialObject() && value instanceof _index.AbstractValue && value.kind !== "resolved") { var realmGenerator = realm.generator; (0, _invariant2.default)(realmGenerator); value = realmGenerator.derive(value.types, value.values, value.args, value.getBuildNode(), { kind: "resolved" }); InternalSetProperty(realm, O, P, { value: value, writable: "writable" in X ? X.writable : false, enumerable: "enumerable" in X ? X.enumerable : false, configurable: "configurable" in X ? X.configurable : false }); } // a. Set D.[[Value]] to the value of X's [[Value]] attribute. D.value = value; // b. Set D.[[Writable]] to the value of X's [[Writable]] attribute. D.writable = X.writable; } else { // 6. Else X is an accessor property, (0, _invariant2.default)((0, _index2.IsAccessorDescriptor)(realm, X), "expected accessor property"); // a. Set D.[[Get]] to the value of X's [[Get]] attribute. D.get = X.get; // b. Set D.[[Set]] to the value of X's [[Set]] attribute. D.set = X.set; } // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute. D.enumerable = X.enumerable; // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute. D.configurable = X.configurable; // 9. Return D. return D; } // ECMA262 9.1.2.1 }, { key: "OrdinarySetPrototypeOf", value: function OrdinarySetPrototypeOf(realm, O, V) { if (O.isLeakedObject()) { throw new _errors.FatalError(); } // 1. Assert: Either Type(V) is Object or Type(V) is Null. (0, _invariant2.default)(V instanceof _index.ObjectValue || V instanceof _index.NullValue); // 2. Let extensible be the value of the [[Extensible]] internal slot of O. var extensible = O.getExtensible(); // 3. Let current be the value of the [[Prototype]] internal slot of O. var current = O.$Prototype; // 4. If SameValue(V, current) is true, return true. if ((0, _index2.SameValue)(realm, V, current)) return true; // 5. If extensible is false, return false. if (!extensible) return false; // 6. Let p be V. var p = V; // 7. Let done be false. var done = false; // 8. Repeat while done is false, while (!done) { // a. If p is null, let done be true. if (p instanceof _index.NullValue) { done = true; } else if ((0, _index2.SameValue)(realm, p, O)) { // b. Else if SameValue(p, O) is true, return false. return false; } else { // c. Else, // TODO #1017 i. If the [[GetPrototypeOf]] internal method of p is not the ordinary object internal method defined in 9.1.1, let done be true. // ii. Else, let p be the value of p's [[Prototype]] internal slot. p = p.$Prototype; } } // 9. Set the value of the [[Prototype]] internal slot of O to V. O.$Prototype = V; // 10. Return true. return true; } // ECMA262 13.7.5.15 }, { key: "EnumerateObjectProperties", value: function EnumerateObjectProperties(realm, O) { var _this = this; /*global global*/ var visited = new global.Set(); var obj = O; var keys = O.$OwnPropertyKeys(); var index = 0; var iterator = new _index.ObjectValue(realm); iterator.defineNativeMethod("next", 0, function () { while (true) { if (index >= keys.length) { var proto = obj.$GetPrototypeOf(); if (proto instanceof _index.NullValue) { return _singletons.Create.CreateIterResultObject(realm, realm.intrinsics.undefined, true); } obj = proto; keys = obj.$OwnPropertyKeys(); index = 0; } var key = keys[index]; // Omit symbols. if (!(key instanceof _index.StringValue)) { index += 1; continue; } // Omit non-enumerable properties. var desc = obj.$GetOwnProperty(key); if (desc && !desc.enumerable) { _this.ThrowIfMightHaveBeenDeleted(desc.value); index += 1; visited.add(key.value); continue; } // Omit duplicates. if (visited.has(key.value)) { index += 1; continue; } visited.add(key.value); // Yield the key. return _singletons.Create.CreateIterResultObject(realm, key, false); } }); return iterator; } }, { key: "ThrowIfMightHaveBeenDeleted", value: function ThrowIfMightHaveBeenDeleted(value) { if (!(value instanceof _index.Value)) return; if (!value.mightHaveBeenDeleted()) return; (0, _invariant2.default)(value instanceof _index.AbstractValue); // real empty values should never get here _index.AbstractValue.reportIntrospectionError(value); throw new _errors.FatalError(); } }, { key: "ThrowIfInternalSlotNotWritable", value: function ThrowIfInternalSlotNotWritable(realm, object, key) { if (!realm.isNewObject(object)) { _index.AbstractValue.reportIntrospectionError(object, key); throw new _errors.FatalError(); } return object; } // ECMA 14.3.9 }, { key: "PropertyDefinitionEvaluation", value: function PropertyDefinitionEvaluation(realm, MethodDefinition, object, env, strictCode, enumerable) { // MethodDefinition : PropertyName ( StrictFormalParameters ) { FunctionBody } if (MethodDefinition.kind === "method") { // 1. Let methodDef be DefineMethod of MethodDefinition with argument object. var methodDef = _singletons.Functions.DefineMethod(realm, MethodDefinition, object, env, strictCode); // 2. ReturnIfAbrupt(methodDef). // 3. Perform SetFunctionName(methodDef.[[closure]], methodDef.[[key]]). _singletons.Functions.SetFunctionName(realm, methodDef.$Closure, methodDef.$Key); // 4. Let desc be the Property Descriptor{[[Value]]: methodDef.[[closure]], [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true}. var desc = { value: methodDef.$Closure, writable: true, enumerable: enumerable, configurable: true }; // 5. Return DefinePropertyOrThrow(object, methodDef.[[key]], desc). return this.DefinePropertyOrThrow(realm, object, methodDef.$Key, desc); } else if (MethodDefinition.kind === "generator") { // MethodDefinition : GeneratorMethod // See 14.4. // ECMA 14.4.13 // 1. Let propKey be the result of evaluating PropertyName. var propKey = (0, _ObjectExpression.EvalPropertyName)(MethodDefinition, env, realm, strictCode); // 2. ReturnIfAbrupt(propKey). // 3. If the function code for this GeneratorMethod is strict mode code, let strict be true. Otherwise let strict be false. var strict = strictCode || (0, _strict4.default)(MethodDefinition.body); // 4. Let scope be the running execution context’s LexicalEnvironment. var scope = env; // 5. Let closure be GeneratorFunctionCreate(Method, StrictFormalParameters, GeneratorBody, scope, strict). var closure = _singletons.Functions.GeneratorFunctionCreate(realm, "method", MethodDefinition.params, MethodDefinition.body, scope, strict); // 6. Perform MakeMethod(closure, object). _singletons.Functions.MakeMethod(realm, closure, object); // 7. Let prototype be ObjectCreate(%GeneratorPrototype%). var prototype = _singletons.Create.ObjectCreate(realm, realm.intrinsics.GeneratorPrototype); prototype.originalConstructor = closure; // 8. Perform MakeConstructor(closure, true, prototype). (0, _index2.MakeConstructor)(realm, closure, true, prototype); // 9. Perform SetFunctionName(closure, propKey). _singletons.Functions.SetFunctionName(realm, closure, propKey); // 10. Let desc be the Property Descriptor{[[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true}. var _desc = { value: closure, writable: true, enumerable: enumerable, configurable: true }; // 11. Return DefinePropertyOrThrow(object, propKey, desc). return this.DefinePropertyOrThrow(realm, object, propKey, _desc); } else if (MethodDefinition.kind === "get") { // 1. Let propKey be the result of evaluating PropertyName. var _propKey = (0, _ObjectExpression.EvalPropertyName)(MethodDefinition, env, realm, strictCode); // 2. ReturnIfAbrupt(propKey). // 3. If the function code for this MethodDefinition is strict mode code, let strict be true. Otherwise let strict be false. var _strict = strictCode || (0, _strict4.default)(MethodDefinition.body); // 4. Let scope be the running execution context's LexicalEnvironment. var _scope = env; // 5. Let formalParameterList be the production FormalParameters:[empty] . var formalParameterList = []; // 6. Let closure be FunctionCreate(Method, formalParameterList, FunctionBody, scope, strict). var _closure = _singletons.Functions.FunctionCreate(realm, "method", formalParameterList, MethodDefinition.body, _scope, _strict); // 7. Perform MakeMethod(closure, object). _singletons.Functions.MakeMethod(realm, _closure, object); // 8. Perform SetFunctionName(closure, propKey, "get"). _singletons.Functions.SetFunctionName(realm, _closure, _propKey, "get"); // 9. Let desc be the PropertyDescriptor{[[Get]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true}. var _desc2 = { get: _closure, enumerable: true, configurable: true }; // 10. Return ? DefinePropertyOrThrow(object, propKey, desc). return this.DefinePropertyOrThrow(realm, object, _propKey, _desc2); } else { (0, _invariant2.default)(MethodDefinition.kind === "set"); // 1. Let propKey be the result of evaluating PropertyName. var _propKey2 = (0, _ObjectExpression.EvalPropertyName)(MethodDefinition, env, realm, strictCode); // 2. ReturnIfAbrupt(propKey). // 3. If the function code for this MethodDefinition is strict mode code, let strict be true. Otherwise let strict be false. var _strict2 = strictCode || (0, _strict4.default)(MethodDefinition.body); // 4. Let scope be the running execution context's LexicalEnvironment. var _scope2 = env; // 5. Let closure be FunctionCreate(Method, PropertySetParameterList, FunctionBody, scope, strict). var _closure2 = _singletons.Functions.FunctionCreate(realm, "method", MethodDefinition.params, MethodDefinition.body, _scope2, _strict2); // 6. Perform MakeMethod(closure, object). _singletons.Functions.MakeMethod(realm, _closure2, object); // 7. Perform SetFunctionName(closure, propKey, "set"). _singletons.Functions.SetFunctionName(realm, _closure2, _propKey2, "set"); // 8. Let desc be the PropertyDescriptor{[[Set]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true}. var _desc3 = { set: _closure2, enumerable: true, configurable: true }; // 9. Return ? DefinePropertyOrThrow(object, propKey, desc). return this.DefinePropertyOrThrow(realm, object, _propKey2, _desc3); } } }]); return PropertiesImplementation; }(); //# sourceMappingURL=properties.js.map