"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Reference = exports.LexicalEnvironment = exports.GlobalEnvironmentRecord = exports.FunctionEnvironmentRecord = exports.ObjectEnvironmentRecord = exports.DeclarativeEnvironmentRecord = exports.EnvironmentRecord = 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; }; }(); exports.leakBinding = leakBinding; exports.canBecomeAnObject = canBecomeAnObject; var _completions = require("./completions.js"); var _errors = require("./errors.js"); var _options = require("./options"); var _realm = require("./realm.js"); var _index = require("./values/index.js"); var _babelGenerator = require("babel-generator"); var _babelGenerator2 = _interopRequireDefault(_babelGenerator); var _parse = require("./utils/parse.js"); var _parse2 = _interopRequireDefault(_parse); var _invariant = require("./invariant.js"); var _invariant2 = _interopRequireDefault(_invariant); var _traverseFast = require("./utils/traverse-fast.js"); var _traverseFast2 = _interopRequireDefault(_traverseFast); var _index2 = require("./methods/index.js"); var _singletons = require("./singletons.js"); var _babelTypes = require("babel-types"); var t = _interopRequireWildcard(_babelTypes); var _index3 = require("./domains/index.js"); 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 _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * 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 sourceMap = require("source-map"); function deriveGetBinding(realm, binding) { var types = _index3.TypesDomain.topVal; var values = _index3.ValuesDomain.topVal; (0, _invariant2.default)(realm.generator !== undefined); return realm.generator.derive(types, values, [], function (_, context) { return context.serializeBinding(binding); }); } function leakBinding(binding) { var realm = binding.environment.realm; if (!binding.hasLeaked) { realm.recordModifiedBinding(binding).hasLeaked = true; } } // ECMA262 8.1.1 var EnvironmentRecord = exports.EnvironmentRecord = function EnvironmentRecord(realm) { _classCallCheck(this, EnvironmentRecord); (0, _invariant2.default)(realm, "expected realm"); this.realm = realm; this.isReadOnly = false; }; // ECMA262 8.1.1.1 var DeclarativeEnvironmentRecord = exports.DeclarativeEnvironmentRecord = function (_EnvironmentRecord) { _inherits(DeclarativeEnvironmentRecord, _EnvironmentRecord); function DeclarativeEnvironmentRecord(realm) { _classCallCheck(this, DeclarativeEnvironmentRecord); var _this = _possibleConstructorReturn(this, (DeclarativeEnvironmentRecord.__proto__ || Object.getPrototypeOf(DeclarativeEnvironmentRecord)).call(this, realm)); _this.bindings = Object.create(null); _this.frozen = false; return _this; } // Frozen Records cannot have bindings created or deleted but can have bindings updated _createClass(DeclarativeEnvironmentRecord, [{ key: "HasBinding", // ECMA262 8.1.1.1.1 value: function HasBinding(N) { // 1. Let envRec be the declarative Environment Record for which the method was invoked. var envRec = this; // 2. If envRec has a binding for the name that is the value of N, return true. if (envRec.bindings[N]) return true; // 3. Return false. return false; } // ECMA262 8.1.1.1.2 }, { key: "CreateMutableBinding", value: function CreateMutableBinding(N, D) { var isGlobal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; (0, _invariant2.default)(!this.frozen); var realm = this.realm; // 1. Let envRec be the declarative Environment Record for which the method was invoked. var envRec = this; // 2. Assert: envRec does not already have a binding for N. (0, _invariant2.default)(!envRec.bindings[N], "shouldn't have the binding " + N); // 3. Create a mutable binding in envRec for N and record that it is uninitialized. If D is true, record that the newly created binding may be deleted by a subsequent DeleteBinding call. this.bindings[N] = realm.recordModifiedBinding({ initialized: false, mutable: true, deletable: D, environment: envRec, name: N, isGlobal: isGlobal, hasLeaked: false }); // 4. Return NormalCompletion(empty). return realm.intrinsics.undefined; } // ECMA262 8.1.1.1.3 }, { key: "CreateImmutableBinding", value: function CreateImmutableBinding(N, S) { var isGlobal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; (0, _invariant2.default)(!this.frozen); var realm = this.realm; // 1. Let envRec be the declarative Environment Record for which the method was invoked. var envRec = this; // 2. Assert: envRec does not already have a binding for N. (0, _invariant2.default)(!envRec.bindings[N], "shouldn't have the binding " + N); // 3. Create an immutable binding in envRec for N and record that it is uninitialized. If S is true, record that the newly created binding is a strict binding. this.bindings[N] = realm.recordModifiedBinding({ initialized: false, strict: S, deletable: false, environment: envRec, name: N, isGlobal: isGlobal, hasLeaked: false }); // 4. Return NormalCompletion(empty). return realm.intrinsics.undefined; } // ECMA262 8.1.1.1.4 }, { key: "InitializeBinding", value: function InitializeBinding(N, V) { // 1. Let envRec be the declarative Environment Record for which the method was invoked. var envRec = this; var binding = envRec.bindings[N]; // 2. Assert: envRec must have an uninitialized binding for N. (0, _invariant2.default)(binding && !binding.initialized, "shouldn't have the binding " + N); // 3. Set the bound value for N in envRec to V. this.realm.recordModifiedBinding(binding).value = V; // 4. Record that the binding for N in envRec has been initialized. binding.initialized = true; // 5. Return NormalCompletion(empty). return this.realm.intrinsics.empty; } // ECMA262 8.1.1.1.5 }, { key: "SetMutableBinding", value: function SetMutableBinding(N, V, S) { // We can mutate frozen bindings because of captured bindings. var realm = this.realm; // 1. Let envRec be the declarative Environment Record for which the method was invoked. var envRec = this; var binding = envRec.bindings[N]; // 2. If envRec does not have a binding for N, then if (!binding) { // a. If S is true, throw a ReferenceError exception. if (S) { throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError, N + " not found"); } // b. Perform envRec.CreateMutableBinding(N, true). envRec.CreateMutableBinding(N, true); // c. Perform envRec.InitializeBinding(N, V). envRec.InitializeBinding(N, V); // d. Return NormalCompletion(empty). return this.realm.intrinsics.empty; } // 3. If the binding for N in envRec is a strict binding, let S be true. if (binding.strict) S = true; // 4. If the binding for N in envRec has not yet been initialized, throw a ReferenceError exception. if (!binding.initialized) { throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError, N + " has not yet been initialized"); } else if (binding.mutable) { // 5. Else if the binding for N in envRec is a mutable binding, change its bound value to V. if (binding.hasLeaked) { _singletons.Leak.leakValue(realm, V); (0, _invariant2.default)(realm.generator); realm.generator.emitBindingAssignment(binding, V); } else { realm.recordModifiedBinding(binding).value = V; } } else { // 6. Else, // a. Assert: This is an attempt to change the value of an immutable binding. // b. If S is true, throw a TypeError exception. if (S) { throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "attempt to change immutable binding"); } } // 7. Return NormalCompletion(empty). return this.realm.intrinsics.empty; } // ECMA262 8.1.1.1.6 }, { key: "GetBindingValue", value: function GetBindingValue(N, S) { var realm = this.realm; // 1. Let envRec be the declarative Environment Record for which the method was invoked. var envRec = this; var binding = envRec.bindings[N]; // 2. Assert: envRec has a binding for N. (0, _invariant2.default)(binding, "expected binding"); // 3. If the binding for N in envRec is an uninitialized binding, throw a ReferenceError exception. if (!binding.initialized) { throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError); } // 4. Return the value currently bound to N in envRec. if (binding.hasLeaked) { return deriveGetBinding(realm, binding); } (0, _invariant2.default)(binding.value); return binding.value; } // ECMA262 8.1.1.1.7 }, { key: "DeleteBinding", value: function DeleteBinding(N) { (0, _invariant2.default)(!this.frozen); // 1. Let envRec be the declarative Environment Record for which the method was invoked. var envRec = this; // 2. Assert: envRec has a binding for the name that is the value of N. (0, _invariant2.default)(envRec.bindings[N], "expected binding to exist"); // 3. If the binding for N in envRec cannot be deleted, return false. if (!envRec.bindings[N].deletable) return false; // 4. Remove the binding for N from envRec. this.realm.recordModifiedBinding(envRec.bindings[N]).value = undefined; delete envRec.bindings[N]; // 5. Return true. return true; } // ECMA262 8.1.1.1.8 }, { key: "HasThisBinding", value: function HasThisBinding() { // 1. Return false. return false; } // ECMA262 8.1.1.1.9 }, { key: "HasSuperBinding", value: function HasSuperBinding() { // 1. Return false. return false; } // ECMA262 8.1.1.1.10 }, { key: "WithBaseObject", value: function WithBaseObject() { // 1. Return undefined. return this.realm.intrinsics.undefined; } }]); return DeclarativeEnvironmentRecord; }(EnvironmentRecord); // ECMA262 8.1.1.2 var ObjectEnvironmentRecord = exports.ObjectEnvironmentRecord = function (_EnvironmentRecord2) { _inherits(ObjectEnvironmentRecord, _EnvironmentRecord2); function ObjectEnvironmentRecord(realm, obj) { _classCallCheck(this, ObjectEnvironmentRecord); var _this2 = _possibleConstructorReturn(this, (ObjectEnvironmentRecord.__proto__ || Object.getPrototypeOf(ObjectEnvironmentRecord)).call(this, realm)); _this2.object = obj; return _this2; } // ECMA262 8.1.1.2.1 _createClass(ObjectEnvironmentRecord, [{ key: "HasBinding", value: function HasBinding(N) { var realm = this.realm; // 1. Let envRec be the object Environment Record for which the method was invoked. var envRec = this; // 2. Let bindings be the binding object for envRec. var bindings = this.object; // 3. Let foundBinding be ? HasProperty(bindings, N). var foundBinding = (0, _index2.HasProperty)(realm, bindings, N); // 4. If foundBinding is false, return false. if (!foundBinding) return false; // 5. If the withEnvironment flag of envRec is false, return true. if (!envRec.withEnvironment) return true; // 6. Let unscopables be ? Get(bindings, @@unscopables). var unscopables = (0, _index2.Get)(realm, bindings, realm.intrinsics.SymbolUnscopables); // 7. If Type(unscopables) is Object, then if (unscopables instanceof _index.ObjectValue || unscopables instanceof _index.AbstractObjectValue) { // a. Let blocked be ToBoolean(? Get(unscopables, N)). var blocked = _singletons.To.ToBooleanPartial(realm, (0, _index2.Get)(realm, unscopables, N)); // b. If blocked is true, return false. if (blocked) return false; } unscopables.throwIfNotConcrete(); // 8. Return true. return true; } // ECMA262 8.1.1.2.2 }, { key: "CreateMutableBinding", value: function CreateMutableBinding(N, D) { var realm = this.realm; // 1. Let envRec be the object Environment Record for which the method was invoked. var envRec = this; // 2. Let bindings be the binding object for envRec. var bindings = envRec.object; // 3. If D is true, let configValue be true; otherwise let configValue be false. var configValue = D ? true : false; // 4. Return ? DefinePropertyOrThrow(bindings, N, PropertyDescriptor{[[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: configValue}). return new _index.BooleanValue(realm, _singletons.Properties.DefinePropertyOrThrow(realm, bindings, N, { value: realm.intrinsics.undefined, writable: true, enumerable: true, configurable: configValue })); } // ECMA262 8.1.1.2.3 }, { key: "CreateImmutableBinding", value: function CreateImmutableBinding(N, S) { // The concrete Environment Record method CreateImmutableBinding is never used within this specification in association with object Environment Records. (0, _invariant2.default)(false); } // ECMA262 8.1.1.2.4 }, { key: "InitializeBinding", value: function InitializeBinding(N, V) { // 1. Let envRec be the object Environment Record for which the method was invoked. var envRec = this; // 2. Assert: envRec must have an uninitialized binding for N. // 3. Record that the binding for N in envRec has been initialized. // 4. Return ? envRec.SetMutableBinding(N, V, false). return envRec.SetMutableBinding(N, V, false); } // ECMA262 8.1.1.2.5 }, { key: "SetMutableBinding", value: function SetMutableBinding(N, V, S) { var realm = this.realm; // 1. Let envRec be the object Environment Record for which the method was invoked. var envRec = this; // 2. Let bindings be the binding object for envRec. var bindings = envRec.object; // 3. Return ? Set(bindings, N, V, S). return new _index.BooleanValue(realm, _singletons.Properties.Set(realm, bindings, N, V, S)); } // ECMA262 8.1.1.2.6 }, { key: "GetBindingValue", value: function GetBindingValue(N, S) { var realm = this.realm; // 1. Let envRec be the object Environment Record for which the method was invoked. var envRec = this; // 2. Let bindings be the binding object for envRec. var bindings = envRec.object; // 3. Let value be ? HasProperty(bindings, N). var value = (0, _index2.HasProperty)(realm, bindings, N); // 4. If value is false, then if (!value) { // a. If S is false, return the value undefined; otherwise throw a ReferenceError exception. if (!S) { return realm.intrinsics.undefined; } else { throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError); } } // 5. Return ? Get(bindings, N). return (0, _index2.Get)(realm, bindings, N); } // ECMA262 8.1.1.2.7 }, { key: "DeleteBinding", value: function DeleteBinding(N) { // 1. Let envRec be the object Environment Record for which the method was invoked. var envRec = this; // 2. Let bindings be the binding object for envRec. var bindings = envRec.object; // 3. Return ? bindings.[[Delete]](N). return bindings.$Delete(N); } // ECMA262 8.1.1.2.8 }, { key: "HasThisBinding", value: function HasThisBinding() { // 1. Return false. return false; } // ECMA262 8.1.1.2.9 }, { key: "HasSuperBinding", value: function HasSuperBinding() { // 1. Return false. return false; } // ECMA262 8.1.1.2.10 }, { key: "WithBaseObject", value: function WithBaseObject() { // 1. Let envRec be the object Environment Record for which the method was invoked. var envRec = this; // 2. If the withEnvironment flag of envRec is true, return the binding object for envRec. if (envRec.withEnvironment) return envRec.object; // 3. Otherwise, return undefined. return this.realm.intrinsics.undefined; } }]); return ObjectEnvironmentRecord; }(EnvironmentRecord); // ECMA262 8.1.1.3 var FunctionEnvironmentRecord = exports.FunctionEnvironmentRecord = function (_DeclarativeEnvironme) { _inherits(FunctionEnvironmentRecord, _DeclarativeEnvironme); function FunctionEnvironmentRecord() { _classCallCheck(this, FunctionEnvironmentRecord); return _possibleConstructorReturn(this, (FunctionEnvironmentRecord.__proto__ || Object.getPrototypeOf(FunctionEnvironmentRecord)).apply(this, arguments)); } _createClass(FunctionEnvironmentRecord, [{ key: "BindThisValue", // ECMA262 8.1.1.3.1 value: function BindThisValue(V) { var realm = this.realm; // 1. Let envRec be the function Environment Record for which the method was invoked. var envRec = this; // 2. Assert: envRec.[[ThisBindingStatus]] is not "lexical". (0, _invariant2.default)(envRec.$ThisBindingStatus !== "lexical", "this binding status shouldn't be lexical"); // 3. If envRec.[[ThisBindingStatus]] is "initialized", throw a ReferenceError exception. if (envRec.$ThisBindingStatus === "initialized") { throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError); } // 4. Set envRec.[[ThisValue]] to V. envRec.$ThisValue = V; // 5. Set envRec.[[ThisBindingStatus]] to "initialized". envRec.$ThisBindingStatus = "initialized"; // 6. Return V. return V; } // ECMA262 8.1.1.3.2 }, { key: "HasThisBinding", value: function HasThisBinding() { // 1. Let envRec be the function Environment Record for which the method was invoked. var envRec = this; // 2. If envRec.[[ThisBindingStatus]] is "lexical", return false; otherwise, return true. return envRec.$ThisBindingStatus === "lexical" ? false : true; } // ECMA262 8.1.1.3.3 }, { key: "HasSuperBinding", value: function HasSuperBinding() { // 1. Let envRec be the function Environment Record for which the method was invoked. var envRec = this; // 2. If envRec.[[ThisBindingStatus]] is "lexical", return false. if (envRec.$ThisBindingStatus === "lexical") return false; // 3. If envRec.[[HomeObject]] has the value undefined, return false; otherwise, return true. if (envRec.$HomeObject === undefined) { return false; } else { return true; } } // ECMA262 8.1.1.3.4 }, { key: "GetThisBinding", value: function GetThisBinding() { var realm = this.realm; // 1. Let envRec be the function Environment Record for which the method was invoked. var envRec = this; // 2. Assert: envRec.[[ThisBindingStatus]] is not "lexical". (0, _invariant2.default)(envRec.$ThisBindingStatus !== "lexical", "this binding status shouldn't be lexical"); // 3. If envRec.[[ThisBindingStatus]] is "uninitialized", throw a ReferenceError exception. if (envRec.$ThisBindingStatus === "uninitialized") { throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError); } // 4. Return envRec.[[ThisValue]]. return envRec.$ThisValue; } // ECMA262 8.1.1.3.5 }, { key: "GetSuperBase", value: function GetSuperBase() { // 1. Let envRec be the function Environment Record for which the method was invoked. var envRec = this; // 2. Let home be the value of envRec.[[HomeObject]]. var home = envRec.$HomeObject; // 3. If home has the value undefined, return undefined. if (home === undefined) return this.realm.intrinsics.undefined; // 4. Assert: Type(home) is Object. (0, _invariant2.default)(home instanceof _index.ObjectValue, "expected object value"); // 5. Return ? home.[[GetPrototypeOf]](). return home.$GetPrototypeOf(); } }]); return FunctionEnvironmentRecord; }(DeclarativeEnvironmentRecord); // ECMA262 8.1.1.4 var GlobalEnvironmentRecord = exports.GlobalEnvironmentRecord = function (_EnvironmentRecord3) { _inherits(GlobalEnvironmentRecord, _EnvironmentRecord3); function GlobalEnvironmentRecord() { _classCallCheck(this, GlobalEnvironmentRecord); return _possibleConstructorReturn(this, (GlobalEnvironmentRecord.__proto__ || Object.getPrototypeOf(GlobalEnvironmentRecord)).apply(this, arguments)); } _createClass(GlobalEnvironmentRecord, [{ key: "HasBinding", // ECMA262 8.1.1.4.1 value: function HasBinding(N) { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let DclRec be envRec.[[DeclarativeRecord]]. var DclRec = envRec.$DeclarativeRecord; // 3. If DclRec.HasBinding(N) is true, return true. if (DclRec.HasBinding(N)) return true; // 4. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 5. Return ? ObjRec.HasBinding(N). return ObjRec.HasBinding(N); } // ECMA262 8.1.1.4.2 }, { key: "CreateMutableBinding", value: function CreateMutableBinding(N, D) { var realm = this.realm; // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let DclRec be envRec.[[DeclarativeRecord]]. var DclRec = envRec.$DeclarativeRecord; // 3. If DclRec.HasBinding(N) is true, throw a TypeError exception. if (DclRec.HasBinding(N)) { throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError); } // 4. Return DclRec.CreateMutableBinding(N, D). return DclRec.CreateMutableBinding(N, D, true); } // ECMA262 8.1.1.4.3 }, { key: "CreateImmutableBinding", value: function CreateImmutableBinding(N, S) { var realm = this.realm; // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let DclRec be envRec.[[DeclarativeRecord]]. var DclRec = envRec.$DeclarativeRecord; // 3. If DclRec.HasBinding(N) is true, throw a TypeError exception. if (DclRec.HasBinding(N)) { throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError); } // 4. Return DclRec.CreateImmutableBinding(N, S). return DclRec.CreateImmutableBinding(N, S, true); } // ECMA262 8.1.1.4.4 }, { key: "InitializeBinding", value: function InitializeBinding(N, V) { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let DclRec be envRec.[[DeclarativeRecord]]. var DclRec = envRec.$DeclarativeRecord; // 3. If DclRec.HasBinding(N) is true, then if (DclRec.HasBinding(N)) { // a. Return DclRec.InitializeBinding(N, V). return DclRec.InitializeBinding(N, V); } // 4. Assert: If the binding exists, it must be in the object Environment Record. // 5. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 6. Return ? ObjRec.InitializeBinding(N, V). return ObjRec.InitializeBinding(N, V); } // ECMA262 8.1.1.4.5 }, { key: "SetMutableBinding", value: function SetMutableBinding(N, V, S) { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let DclRec be envRec.[[DeclarativeRecord]]. var DclRec = envRec.$DeclarativeRecord; // 3. If DclRec.HasBinding(N) is true, then if (DclRec.HasBinding(N)) { // a. Return DclRec.SetMutableBinding(N, V, S). return DclRec.SetMutableBinding(N, V, S); } // 4. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 5. Return ? ObjRec.SetMutableBinding(N, V, S). return ObjRec.SetMutableBinding(N, V, S); } // ECMA262 8.1.1.4.6 }, { key: "GetBindingValue", value: function GetBindingValue(N, S) { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let DclRec be envRec.[[DeclarativeRecord]]. var DclRec = envRec.$DeclarativeRecord; // 3. If DclRec.HasBinding(N) is true, then if (DclRec.HasBinding(N)) { // a. Return DclRec.GetBindingValue(N, S). return DclRec.GetBindingValue(N, S); } // 4. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 5. Return ? ObjRec.GetBindingValue(N, S). return ObjRec.GetBindingValue(N, S); } // ECMA262 8.1.1.4.7 }, { key: "DeleteBinding", value: function DeleteBinding(N) { var realm = this.realm; // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let DclRec be envRec.[[DeclarativeRecord]]. var DclRec = envRec.$DeclarativeRecord; // 3. If DclRec.HasBinding(N) is true, then if (DclRec.HasBinding(N)) { // a. Return DclRec.DeleteBinding(N). return DclRec.DeleteBinding(N); } // 4. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 5. Let globalObject be the binding object for ObjRec. var globalObject = ObjRec.object; // 6. Let existingProp be ? HasOwnProperty(globalObject, N). var existingProp = (0, _index2.HasOwnProperty)(realm, globalObject, N); // 7. If existingProp is true, then if (existingProp) { // a. Let status be ? ObjRec.DeleteBinding(N). var status = ObjRec.DeleteBinding(N); // b. If status is true, then if (status) { // i. Let varNames be envRec.[[VarNames]]. var varNames = envRec.$VarNames; // ii. If N is an element of varNames, remove that element from the varNames. if (varNames.indexOf(N) >= 0) { varNames.splice(varNames.indexOf(N), 1); } } // c. Return status. return status; } // 8. Return true. return true; } // ECMA262 8.1.1.4.8 }, { key: "HasThisBinding", value: function HasThisBinding() { // 1. Return true. return true; } // ECMA262 8.1.1.4.9 }, { key: "HasSuperBinding", value: function HasSuperBinding() { // 1. Return true. return true; } // ECMA262 8.1.1.4.10 }, { key: "WithBaseObject", value: function WithBaseObject() { // 1. Return undefined. return this.realm.intrinsics.undefined; } // ECMA262 8.1.1.4.11 }, { key: "GetThisBinding", value: function GetThisBinding() { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; (0, _invariant2.default)(envRec.$GlobalThisValue); // 2. Return envRec.[[GlobalThisValue]]. return envRec.$GlobalThisValue; } // ECMA262 8.1.1.4.12 }, { key: "HasVarDeclaration", value: function HasVarDeclaration(N) { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let varDeclaredNames be envRec.[[VarNames]]. var varDeclaredNames = envRec.$VarNames; // 3. If varDeclaredNames contains the value of N, return true. if (varDeclaredNames.indexOf(N) >= 0) return true; // 4. Return false. return false; } // ECMA262 8.1.1.4.13 }, { key: "HasLexicalDeclaration", value: function HasLexicalDeclaration(N) { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let DclRec be envRec.[[DeclarativeRecord]]. var DclRec = envRec.$DeclarativeRecord; // 3. Return DclRec.HasBinding(N). return DclRec.HasBinding(N); } // ECMA262 8.1.1.4.14 }, { key: "HasRestrictedGlobalProperty", value: function HasRestrictedGlobalProperty(N) { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 3. Let globalObject be the binding object for ObjRec. var globalObject = ObjRec.object; // 4. Let existingProp be ? globalObject.[[GetOwnProperty]](N). var existingProp = globalObject.$GetOwnProperty(N); // 5. If existingProp is undefined, return false. if (!existingProp) return false; _singletons.Properties.ThrowIfMightHaveBeenDeleted(existingProp.value); // 6. If existingProp.[[Configurable]] is true, return false. if (existingProp.configurable) return false; // 7. Return true. return true; } // ECMA262 8.1.1.4.15 }, { key: "CanDeclareGlobalVar", value: function CanDeclareGlobalVar(N) { var realm = this.realm; // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 3. Let globalObject be the binding object for ObjRec. var globalObject = ObjRec.object; // 4. Let hasProperty be ? HasOwnProperty(globalObject, N). var hasProperty = (0, _index2.HasOwnProperty)(realm, globalObject, N); // 5. If hasProperty is true, return true. if (hasProperty) return true; // 6. Return ? IsExtensible(globalObject). return (0, _index2.IsExtensible)(realm, globalObject); } // ECMA262 8.1.1.4.16 }, { key: "CanDeclareGlobalFunction", value: function CanDeclareGlobalFunction(N) { var realm = this.realm; // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 3. Let globalObject be the binding object for ObjRec. var globalObject = ObjRec.object; // 4. Let existingProp be ? globalObject.[[GetOwnProperty]](N). var existingProp = globalObject.$GetOwnProperty(N); // 5. If existingProp is undefined, return ? IsExtensible(globalObject). if (!existingProp) return (0, _index2.IsExtensible)(realm, globalObject); _singletons.Properties.ThrowIfMightHaveBeenDeleted(existingProp.value); // 6. If existingProp.[[Configurable]] is true, return true. if (existingProp.configurable) return true; // 7. If IsDataDescriptor(existingProp) is true and existingProp has attribute values {[[Writable]]: true, [[Enumerable]]: true}, return true. if ((0, _index2.IsDataDescriptor)(realm, existingProp) && existingProp.writable && existingProp.enumerable) { return true; } // 8. Return false. return false; } // ECMA262 8.1.1.4.17 }, { key: "CreateGlobalVarBinding", value: function CreateGlobalVarBinding(N, D) { var realm = this.realm; // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 3. Let globalObject be the binding object for ObjRec. var globalObject = ObjRec.object; // 4. Let hasProperty be ? HasOwnProperty(globalObject, N). var hasProperty = (0, _index2.HasOwnProperty)(realm, globalObject, N); // 5. Let extensible be ? IsExtensible(globalObject). var extensible = (0, _index2.IsExtensible)(realm, globalObject); // 6. If hasProperty is false and extensible is true, then if (!hasProperty && extensible) { // a. Perform ? ObjRec.CreateMutableBinding(N, D). ObjRec.CreateMutableBinding(N, D); // b. Perform ? ObjRec.InitializeBinding(N, undefined). ObjRec.InitializeBinding(N, this.realm.intrinsics.undefined); } // 7. Let varDeclaredNames be envRec.[[VarNames]]. var varDeclaredNames = envRec.$VarNames; // 8. If varDeclaredNames does not contain the value of N, then if (varDeclaredNames.indexOf(N) < 0) { // a. Append N to varDeclaredNames. varDeclaredNames.push(N); } // 9. Return NormalCompletion(empty). } // ECMA262 8.1.1.4.18 }, { key: "CreateGlobalFunctionBinding", value: function CreateGlobalFunctionBinding(N, V, D) { // 1. Let envRec be the global Environment Record for which the method was invoked. var envRec = this; // 2. Let ObjRec be envRec.[[ObjectRecord]]. var ObjRec = envRec.$ObjectRecord; // 3. Let globalObject be the binding object for ObjRec. var globalObject = ObjRec.object; // 4. Let existingProp be ? globalObject.[[GetOwnProperty]](N). var existingProp = globalObject.$GetOwnProperty(N); // 5. If existingProp is undefined or existingProp.[[Configurable]] is true, then var desc = void 0; if (!existingProp || existingProp.configurable) { // a. Let desc be the PropertyDescriptor{[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D}. desc = { value: V, writable: true, enumerable: true, configurable: D }; } else { // 6. Else, _singletons.Properties.ThrowIfMightHaveBeenDeleted(existingProp.value); // a. Let desc be the PropertyDescriptor{[[Value]]: V }. desc = { value: V }; } // 7. Perform ? DefinePropertyOrThrow(globalObject, N, desc). _singletons.Properties.DefinePropertyOrThrow(this.realm, globalObject, N, desc); // 8. Record that the binding for N in ObjRec has been initialized. // 9. Perform ? Set(globalObject, N, V, false). _singletons.Properties.Set(this.realm, globalObject, N, V, false); // 10. Let varDeclaredNames be envRec.[[VarNames]]. var varDeclaredNames = envRec.$VarNames; // 11. If varDeclaredNames does not contain the value of N, then if (varDeclaredNames.indexOf(N) < 0) { // a. Append N to varDeclaredNames. varDeclaredNames.push(N); } // 12. Return NormalCompletion(empty). } }]); return GlobalEnvironmentRecord; }(EnvironmentRecord); // ECMA262 8.1 var uid = 0; var LexicalEnvironment = exports.LexicalEnvironment = function () { function LexicalEnvironment(realm) { _classCallCheck(this, LexicalEnvironment); (0, _invariant2.default)(realm, "expected realm"); this.realm = realm; this.destroyed = false; this._uid = uid++; } // For debugging it is convenient to have an ID for each of these. _createClass(LexicalEnvironment, [{ key: "destroy", value: function destroy() { this.destroyed = true; // Once the containing environment is destroyed, we can no longer add or remove entries from the environmentRecord // (but we can update existing values). if (this.environmentRecord instanceof DeclarativeEnvironmentRecord) { this.environmentRecord.frozen = true; } } }, { key: "assignToGlobal", value: function assignToGlobal(globalAst, rvalue) { var globalValue = this.evaluate(globalAst, false); _singletons.Properties.PutValue(this.realm, globalValue, rvalue); } }, { key: "partiallyEvaluateCompletionDeref", value: function partiallyEvaluateCompletionDeref(ast, strictCode, metadata) { var _partiallyEvaluateCom = this.partiallyEvaluateCompletion(ast, strictCode, metadata), _partiallyEvaluateCom2 = _slicedToArray(_partiallyEvaluateCom, 3), result = _partiallyEvaluateCom2[0], partial_ast = _partiallyEvaluateCom2[1], partial_io = _partiallyEvaluateCom2[2]; if (result instanceof Reference) { result = _singletons.Environment.GetValue(this.realm, result); } return [result, partial_ast, partial_io]; } }, { key: "partiallyEvaluateCompletion", value: function partiallyEvaluateCompletion(ast, strictCode, metadata) { try { return this.partiallyEvaluate(ast, strictCode, metadata); } catch (err) { if (err instanceof _completions.Completion) return [err, ast, []]; if (err instanceof Error) // rethrowing Error should preserve stack trace throw err; // let's wrap into a proper Error to create stack trace throw new _errors.FatalError(err); } } }, { key: "evaluateCompletionDeref", value: function evaluateCompletionDeref(ast, strictCode, metadata) { var result = this.evaluateCompletion(ast, strictCode, metadata); if (result instanceof Reference) result = _singletons.Environment.GetValue(this.realm, result); return result; } }, { key: "evaluateCompletion", value: function evaluateCompletion(ast, strictCode, metadata) { try { return this.evaluate(ast, strictCode, metadata); } catch (err) { if ((err instanceof _completions.JoinedAbruptCompletions || err instanceof _completions.PossiblyNormalCompletion) && err.containsBreakOrContinue()) { _index.AbstractValue.reportIntrospectionError(err.joinCondition); throw new _errors.FatalError(); } if (err instanceof _completions.AbruptCompletion) return err; if (err instanceof Error) // rethrowing Error should preserve stack trace throw err; // let's wrap into a proper Error to create stack trace throw new _errors.FatalError(err); } } }, { key: "evaluateAbstractCompletion", value: function evaluateAbstractCompletion(ast, strictCode, metadata) { try { return this.evaluateAbstract(ast, strictCode, metadata); } catch (err) { if (err instanceof _completions.Completion) return err; if (err instanceof Error) // rethrowing Error should preserve stack trace throw err; // let's wrap into a proper Error to create stack trace if (err instanceof Object) throw new _errors.FatalError(err.constructor.name + ": " + err); throw new _errors.FatalError(err); } } }, { key: "concatenateAndParse", value: function concatenateAndParse(sources) { var sourceType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "script"; var asts = []; var code = {}; var directives = []; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = sources[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var source = _step.value; try { var node = (0, _parse2.default)(this.realm, source.fileContents, source.filePath, sourceType); if (source.sourceMapContents && source.sourceMapContents.length > 0) this.fixup_source_locations(node, source.sourceMapContents); this.fixup_filenames(node); asts = asts.concat(node.program.body); code[source.filePath] = source.fileContents; directives = directives.concat(node.program.directives); } catch (e) { if (e instanceof _completions.ThrowCompletion) { var error = e.value; if (error instanceof _index.ObjectValue) { var message = error.$Get("message", error); message.value = "Syntax error: " + message.value; e.location.source = source.filePath; // the position was not located properly on the // syntax errors happen on one given position, so start position = end position e.location.start = { line: e.location.line, column: e.location.column }; e.location.end = { line: e.location.line, column: e.location.column }; var diagnostic = new _errors.CompilerDiagnostic(message.value, e.location, "PP1004", "FatalError"); this.realm.handleError(diagnostic); throw new _errors.FatalError(message.value); } } throw e; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return [t.file(t.program(asts, directives)), code]; } }, { key: "executeSources", value: function executeSources(sources) { var sourceType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "script"; var onParse = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var context = new _realm.ExecutionContext(); context.lexicalEnvironment = this; context.variableEnvironment = this; context.realm = this.realm; this.realm.pushContext(context); var res = void 0, code = void 0; try { var ast = void 0; var _concatenateAndParse = this.concatenateAndParse(sources, sourceType); var _concatenateAndParse2 = _slicedToArray(_concatenateAndParse, 2); ast = _concatenateAndParse2[0]; code = _concatenateAndParse2[1]; if (onParse) onParse(ast); res = this.evaluateCompletion(ast, false); } finally { this.realm.popContext(context); this.realm.onDestroyScope(context.lexicalEnvironment); if (!this.destroyed) this.realm.onDestroyScope(this); (0, _invariant2.default)(this.realm.activeLexicalEnvironments.size === 0); } if (res instanceof _completions.AbruptCompletion) return [res, code]; return [_singletons.Environment.GetValue(this.realm, res), code]; } }, { key: "executePartialEvaluator", value: function executePartialEvaluator(sources) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _options.defaultOptions; var sourceType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "script"; var _concatenateAndParse3 = this.concatenateAndParse(sources, sourceType), _concatenateAndParse4 = _slicedToArray(_concatenateAndParse3, 2), ast = _concatenateAndParse4[0], code = _concatenateAndParse4[1]; var context = new _realm.ExecutionContext(); context.lexicalEnvironment = this; context.variableEnvironment = this; context.realm = this.realm; this.realm.pushContext(context); var partialAST = void 0; try { var res = void 0; var _partiallyEvaluateCom3 = this.partiallyEvaluateCompletionDeref(ast, false); var _partiallyEvaluateCom4 = _slicedToArray(_partiallyEvaluateCom3, 2); res = _partiallyEvaluateCom4[0]; partialAST = _partiallyEvaluateCom4[1]; if (res instanceof _completions.AbruptCompletion) return res; } finally { this.realm.popContext(context); this.realm.onDestroyScope(context.lexicalEnvironment); if (!this.destroyed) this.realm.onDestroyScope(this); (0, _invariant2.default)(this.realm.activeLexicalEnvironments.size === 0); } (0, _invariant2.default)(partialAST.type === "File"); var fileAst = partialAST; var prog = t.program(fileAst.program.body, ast.program.directives); this.fixup_filenames(prog); return (0, _babelGenerator2.default)(prog, { sourceMaps: options.sourceMaps }, code); } }, { key: "execute", value: function execute(code, filename) { var map = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; var sourceType = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "script"; var onParse = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined; var context = new _realm.ExecutionContext(); context.lexicalEnvironment = this; context.variableEnvironment = this; context.realm = this.realm; this.realm.pushContext(context); var ast = void 0, res = void 0; try { try { ast = (0, _parse2.default)(this.realm, code, filename, sourceType); } catch (e) { if (e instanceof _completions.ThrowCompletion) return e; throw e; } if (onParse) onParse(ast); if (map.length > 0) this.fixup_source_locations(ast, map); this.fixup_filenames(ast); res = this.evaluateCompletion(ast, false); } finally { this.realm.popContext(context); // Avoid destroying "this" scope as execute may be called many times. if (context.lexicalEnvironment !== this) this.realm.onDestroyScope(context.lexicalEnvironment); (0, _invariant2.default)(this.realm.activeLexicalEnvironments.size === 1); } if (res instanceof _completions.AbruptCompletion) return res; return _singletons.Environment.GetValue(this.realm, res); } }, { key: "fixup_source_locations", value: function fixup_source_locations(ast, map) { var smc = new sourceMap.SourceMapConsumer(map); (0, _traverseFast2.default)(ast, function (node) { var loc = node.loc; if (!loc) return false; fixup(loc, loc.start); fixup(loc, loc.end); fixup_comments(node.leadingComments); fixup_comments(node.innerComments); fixup_comments(node.trailingComments); return false; function fixup(new_loc, new_pos) { var old_pos = smc.originalPositionFor({ line: new_pos.line, column: new_pos.column }); if (old_pos.source === null) return; new_pos.line = old_pos.line; new_pos.column = old_pos.column; new_loc.source = old_pos.source; } function fixup_comments(comments) { if (!comments) return; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = comments[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var c = _step2.value; var cloc = c.loc; if (!cloc) continue; fixup(cloc, cloc.start); fixup(cloc, cloc.end); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } }); } }, { key: "fixup_filenames", value: function fixup_filenames(ast) { (0, _traverseFast2.default)(ast, function (node) { var loc = node.loc; if (!loc || !loc.source) { node.leadingComments = null; node.innerComments = null; node.trailingComments = null; node.loc = null; } else { var filename = loc.source; loc.filename = filename; fixup_comments(node.leadingComments, filename); fixup_comments(node.innerComments, filename); fixup_comments(node.trailingComments, filename); } return false; function fixup_comments(comments, filename) { if (!comments) return; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = comments[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var c = _step3.value; if (c.loc) { c.loc.filename = filename; c.loc.source = filename; } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } }); } }, { key: "evaluate", value: function evaluate(ast, strictCode, metadata) { if (this.realm.debuggerInstance) { this.realm.debuggerInstance.checkForActions(ast); } var res = this.evaluateAbstract(ast, strictCode, metadata); (0, _invariant2.default)(res instanceof _index.Value || res instanceof Reference, ast.type); return res; } }, { key: "evaluateAbstract", value: function evaluateAbstract(ast, strictCode, metadata) { this.realm.currentLocation = ast.loc; this.realm.testTimeout(); var evaluator = this.realm.evaluators[ast.type]; if (evaluator) { var result = evaluator(ast, strictCode, this, this.realm, metadata); return result; } throw new TypeError("Unsupported node type " + ast.type); } }, { key: "partiallyEvaluate", value: function partiallyEvaluate(ast, strictCode, metadata) { var partialEvaluator = this.realm.partialEvaluators[ast.type]; if (partialEvaluator) { return partialEvaluator(ast, strictCode, this, this.realm, metadata); } var err = new TypeError("Unsupported node type " + ast.type); throw err; } }]); return LexicalEnvironment; }(); // ECMA262 6.2.3 // A Reference is a resolved name or property binding. A Reference consists of three components, the base value, // the referenced name and the Boolean valued strict reference flag. The base value is either undefined, an Object, // a Boolean, a String, a Symbol, a Number, or an Environment Record. A base value of undefined indicates that the // Reference could not be resolved to a binding. The referenced name is a String or Symbol value. function canBecomeAnObject(base) { var type = base.getType(); return type === _index.BooleanValue || type === _index.StringValue || type === _index.SymbolValue || type === _index.NumberValue; } var Reference = exports.Reference = function Reference(base, refName, strict, thisValue) { _classCallCheck(this, Reference); (0, _invariant2.default)(base instanceof _index.AbstractObjectValue || base === undefined || base instanceof _index.ObjectValue || base instanceof EnvironmentRecord || canBecomeAnObject(base)); this.base = base; this.referencedName = refName; (0, _invariant2.default)(!(refName instanceof _index.AbstractValue) || !(refName.mightNotBeString() && refName.mightNotBeNumber())); this.strict = strict; this.thisValue = thisValue; (0, _invariant2.default)(thisValue === undefined || !(base instanceof EnvironmentRecord)); }; //# sourceMappingURL=environment.js.map