"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnvironmentImplementation = undefined; 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 _babelTypes = require("babel-types"); var t = _interopRequireWildcard(_babelTypes); var _invariant = require("../invariant.js"); var _invariant2 = _interopRequireDefault(_invariant); var _index = require("../values/index.js"); var _environment = require("../environment.js"); var _completions = require("../completions.js"); var _errors = require("../errors.js"); var _ObjectExpression = require("../evaluators/ObjectExpression.js"); var _index2 = require("./index.js"); var _singletons = require("../singletons.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var EnvironmentImplementation = exports.EnvironmentImplementation = function () { function EnvironmentImplementation() { _classCallCheck(this, EnvironmentImplementation); } _createClass(EnvironmentImplementation, [{ key: "IsSuperReference", // ECMA262 6.2.3 // IsSuperReference(V). Returns true if this reference has a thisValue component. value: function IsSuperReference(realm, V) { return V.thisValue !== undefined; } // ECMA262 6.2.3 // HasPrimitiveBase(V). Returns true if Type(base) is Boolean, String, Symbol, or Number. }, { key: "HasPrimitiveBase", value: function HasPrimitiveBase(realm, V) { var base = this.GetBase(realm, V); // void | ObjectValue | BooleanValue | StringValue | SymbolValue | NumberValue | EnvironmentRecord | AbstractValue; if (!base || base instanceof _environment.EnvironmentRecord) return false; var type = base.getType(); return type === _index.BooleanValue || type === _index.StringValue || type === _index.SymbolValue || type === _index.NumberValue; } // ECMA262 6.2.3 // GetReferencedName(V). Returns the referenced name component of the reference V. }, { key: "GetReferencedName", value: function GetReferencedName(realm, V) { if (V.referencedName instanceof _index.AbstractValue) { _index.AbstractValue.reportIntrospectionError(V.referencedName); throw new _errors.FatalError(); } return V.referencedName; } }, { key: "GetReferencedNamePartial", value: function GetReferencedNamePartial(realm, V) { return V.referencedName; } // ECMA262 6.2.3.1 }, { key: "GetValue", value: function GetValue(realm, V) { var val = this._dereference(realm, V); if (val instanceof _index.AbstractValue) return realm.simplifyAndRefineAbstractValue(val); return val; } }, { key: "GetConditionValue", value: function GetConditionValue(realm, V) { var val = this._dereference(realm, V); if (val instanceof _index.AbstractValue) return realm.simplifyAndRefineAbstractCondition(val); return val; } }, { key: "_dereference", value: function _dereference(realm, V) { // This step is not necessary as we propagate completions with exceptions. // 1. ReturnIfAbrupt(V). // 2. If Type(V) is not Reference, return V. if (!(V instanceof _environment.Reference)) return V; // 3. Let base be GetBase(V). var base = this.GetBase(realm, V); // 4. If IsUnresolvableReference(V) is true, throw a ReferenceError exception. if (this.IsUnresolvableReference(realm, V)) { throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError, V.referencedName.toString() + " is not defined"); } // 5. If IsPropertyReference(V) is true, then if (this.IsPropertyReference(realm, V)) { // a. If HasPrimitiveBase(V) is true, then if (this.HasPrimitiveBase(realm, V)) { // i. Assert: In this case, base will never be null or undefined. (0, _invariant2.default)(base instanceof _index.Value && !(0, _index2.HasSomeCompatibleType)(base, _index.UndefinedValue, _index.NullValue)); // ii. Let base be To.ToObject(base). base = _singletons.To.ToObjectPartial(realm, base); } (0, _invariant2.default)(base instanceof _index.ObjectValue || base instanceof _index.AbstractObjectValue); // b. Return ? base.[[Get]](GetReferencedName(V), GetThisValue(V)). return base.$GetPartial(this.GetReferencedNamePartial(realm, V), (0, _index2.GetThisValue)(realm, V)); } // 6. Else base must be an Environment Record, if (base instanceof _environment.EnvironmentRecord) { // a. Return ? base.GetBindingValue(GetReferencedName(V), IsStrictReference(V)) (see 8.1.1). var referencedName = this.GetReferencedName(realm, V); (0, _invariant2.default)(typeof referencedName === "string"); return base.GetBindingValue(referencedName, this.IsStrictReference(realm, V)); } (0, _invariant2.default)(false); } // ECMA262 6.2.3 // IsStrictReference(V). Returns the strict reference flag component of the reference V. }, { key: "IsStrictReference", value: function IsStrictReference(realm, V) { return V.strict; } // ECMA262 6.2.3 // IsPropertyReference(V). Returns true if either the base value is an object or HasPrimitiveBase(V) is true; otherwise returns false. }, { key: "IsPropertyReference", value: function IsPropertyReference(realm, V) { // V.base is AbstractValue | void | ObjectValue | BooleanValue | StringValue | SymbolValue | NumberValue | EnvironmentRecord; return V.base instanceof _index.AbstractValue || V.base instanceof _index.ObjectValue || this.HasPrimitiveBase(realm, V); } // ECMA262 6.2.3 // GetBase(V). Returns the base value component of the reference V. }, { key: "GetBase", value: function GetBase(realm, V) { return V.base; } // ECMA262 6.2.3 // IsUnresolvableReference(V). Returns true if the base value is undefined and false otherwise. }, { key: "IsUnresolvableReference", value: function IsUnresolvableReference(realm, V) { return !V.base; } // ECMA262 8.1.2.2 }, { key: "NewDeclarativeEnvironment", value: function NewDeclarativeEnvironment(realm, E) { var active = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; // 1. Let env be a new Lexical Environment. var env = new _environment.LexicalEnvironment(realm); if (active) realm.activeLexicalEnvironments.add(env); // 2. Let envRec be a new declarative Environment Record containing no bindings. var envRec = new _environment.DeclarativeEnvironmentRecord(realm); // 3. Set env's EnvironmentRecord to envRec. env.environmentRecord = envRec; // 4. Set the outer lexical environment reference of env to E. env.parent = E; // 5. Return env. return env; } }, { key: "BoundNames", value: function BoundNames(realm, node) { return Object.keys(t.getOuterBindingIdentifiers(node)); } // ECMA262 13.3.3.2 }, { key: "ContainsExpression", value: function ContainsExpression(realm, node) { if (!node) { return false; } switch (node.type) { case "ObjectPattern": var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = node.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var prop = _step.value; if (this.ContainsExpression(realm, prop)) return true; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return false; case "ArrayPattern": var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = node.elements[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var elem = _step2.value; if (this.ContainsExpression(realm, elem)) return true; } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return false; case "RestElement": return this.ContainsExpression(realm, node.argument); case "AssignmentPattern": return true; default: return false; } } // ECMA262 8.3.2 }, { key: "ResolveBinding", value: function ResolveBinding(realm, name, strict, env) { // 1. If env was not passed or if env is undefined, then if (!env) { // a. Let env be the running execution context's LexicalEnvironment. env = realm.getRunningContext().lexicalEnvironment; } // 2. Assert: env is a Lexical Environment. (0, _invariant2.default)(env instanceof _environment.LexicalEnvironment, "expected lexical environment"); // 3. If the code matching the syntactic production that is being evaluated is contained in strict mode code, let strict be true, else let strict be false. // 4. Return ? GetIdentifierReference(env, name, strict). return this.GetIdentifierReference(realm, env, name, strict); } // ECMA262 8.1.2.1 }, { key: "GetIdentifierReference", value: function GetIdentifierReference(realm, lex, name, strict) { // 1. If lex is the value null, then if (!lex) { // a. Return a value of type Reference whose base value is undefined, whose referenced name is name, and whose strict reference flag is strict. return new _environment.Reference(undefined, name, strict); } // 2. Let envRec be lex's EnvironmentRecord. var envRec = lex.environmentRecord; // 3. Let exists be ? envRec.HasBinding(name). var exists = envRec.HasBinding(name); // 4. If exists is true, then if (exists) { // a. Return a value of type Reference whose base value is envRec, whose referenced name is name, and whose strict reference flag is strict. return new _environment.Reference(envRec, name, strict); } else { // 5. Else, // a. Let outer be the value of lex's outer environment reference. var outer = lex.parent; // b. Return ? GetIdentifierReference(outer, name, strict). return this.GetIdentifierReference(realm, outer, name, strict); } } // ECMA262 6.2.3.4 }, { key: "InitializeReferencedBinding", value: function InitializeReferencedBinding(realm, V, W) { // 1. ReturnIfAbrupt(V). // 2. ReturnIfAbrupt(W). // 3. Assert: Type(V) is Reference. (0, _invariant2.default)(V instanceof _environment.Reference, "expected reference"); // 4. Assert: IsUnresolvableReference(V) is false. (0, _invariant2.default)(!this.IsUnresolvableReference(realm, V), "expected resolvable reference"); // 5. Let base be GetBase(V). var base = this.GetBase(realm, V); // 6. Assert: base is an Environment Record. (0, _invariant2.default)(base instanceof _environment.EnvironmentRecord, "expected environment record"); // 7. Return base.InitializeBinding(GetReferencedName(V), W). var referencedName = this.GetReferencedName(realm, V); (0, _invariant2.default)(typeof referencedName === "string"); return base.InitializeBinding(referencedName, W); } // ECMA262 13.2.14 }, { key: "BlockDeclarationInstantiation", value: function BlockDeclarationInstantiation(realm, strictCode, body, env) { // 1. Let envRec be env's EnvironmentRecord. var envRec = env.environmentRecord; // 2. Assert: envRec is a declarative Environment Record. (0, _invariant2.default)(envRec instanceof _environment.DeclarativeEnvironmentRecord, "expected declarative environment record"); // 3. Let declarations be the LexicallyScopedDeclarations of code. var declarations = []; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = body[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var node = _step3.value; if (node.type === "ClassDeclaration" || node.type === "FunctionDeclaration" || node.type === "VariableDeclaration" && node.kind !== "var") { declarations.push(node); } } // 4. For each element d in declarations do } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = declarations[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var d = _step4.value; // a. For each element dn of the BoundNames of d do var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = this.BoundNames(realm, d)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var dn = _step5.value; if (envRec.HasBinding(dn)) { //ECMA262 13.2.1 throw realm.createErrorThrowCompletion(realm.intrinsics.SyntaxError, dn + " already declared"); } // i. If IsConstantDeclaration of d is true, then if (d.type === "VariableDeclaration" && d.kind === "const") { // 1. Perform ! envRec.CreateImmutableBinding(dn, true). envRec.CreateImmutableBinding(dn, true); } else { // ii. Else, // 1. Perform ! envRec.CreateMutableBinding(dn, false). envRec.CreateMutableBinding(dn, false); } } // b. If d is a GeneratorDeclaration production or a FunctionDeclaration production, then } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } if (d.type === "FunctionDeclaration") { // i. Let fn be the sole element of the BoundNames of d. var fn = this.BoundNames(realm, d)[0]; // ii. Let fo be the result of performing InstantiateFunctionObject for d with argument env. var fo = env.evaluate(d, strictCode); (0, _invariant2.default)(fo instanceof _index.Value); // iii. Perform envRec.InitializeBinding(fn, fo). envRec.InitializeBinding(fn, fo); } } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } } // ECMA262 8.1.2.5 }, { key: "NewGlobalEnvironment", value: function NewGlobalEnvironment(realm, G, thisValue) { // 1. Let env be a new Lexical Environment. var env = new _environment.LexicalEnvironment(realm); // 2. Let objRec be a new object Environment Record containing G as the binding object. var objRec = new _environment.ObjectEnvironmentRecord(realm, G); // 3. Let dclRec be a new declarative Environment Record containing no bindings. var dclRec = new _environment.DeclarativeEnvironmentRecord(realm); // 4. Let globalRec be a new global Environment Record. var globalRec = new _environment.GlobalEnvironmentRecord(realm); // 5. Set globalRec.[[ObjectRecord]] to objRec. globalRec.$ObjectRecord = objRec; // 6. Set globalRec.[[GlobalThisValue]] to thisValue. globalRec.$GlobalThisValue = thisValue; // 7. Set globalRec.[[DeclarativeRecord]] to dclRec. globalRec.$DeclarativeRecord = dclRec; // 8. Set globalRec.[[VarNames]] to a new empty List. globalRec.$VarNames = []; // 9. Set env's EnvironmentRecord to globalRec. env.environmentRecord = globalRec; realm.activeLexicalEnvironments.add(env); // 10. Set the outer lexical environment reference of env to null. env.parent = null; // 11. Return env. return env; } // ECMA262 8.1.2.3 }, { key: "NewObjectEnvironment", value: function NewObjectEnvironment(realm, O, E) { // 1. Let env be a new Lexical Environment. var env = new _environment.LexicalEnvironment(realm); realm.activeLexicalEnvironments.add(env); // 2. Let envRec be a new object Environment Record containing O as the binding object. var envRec = new _environment.ObjectEnvironmentRecord(realm, O); // 3. Set env's EnvironmentRecord to envRec. env.environmentRecord = envRec; // 4. Set the outer lexical environment reference of env to E. env.parent = E; // 5. Return env. return env; } // ECMA262 8.1.2.4 }, { key: "NewFunctionEnvironment", value: function NewFunctionEnvironment(realm, F, newTarget) { // 1. Assert: F is an ECMAScript function. (0, _invariant2.default)(F instanceof _index.ECMAScriptFunctionValue, "expected a function"); // 2. Assert: Type(newTarget) is Undefined or Object. (0, _invariant2.default)(newTarget === undefined || newTarget instanceof _index.ObjectValue, "expected undefined or object value for new target"); // 3. Let env be a new Lexical Environment. var env = new _environment.LexicalEnvironment(realm); realm.activeLexicalEnvironments.add(env); // 4. Let envRec be a new function Environment Record containing no bindings. var envRec = new _environment.FunctionEnvironmentRecord(realm); // 5. Set envRec.[[FunctionObject]] to F. envRec.$FunctionObject = F; // 6. If F's [[ThisMode]] internal slot is lexical, set envRec.[[ThisBindingStatus]] to "lexical". if (F.$ThisMode === "lexical") { envRec.$ThisBindingStatus = "lexical"; } else { // 7. Else, set envRec.[[ThisBindingStatus]] to "uninitialized". envRec.$ThisBindingStatus = "uninitialized"; } // 8. Let home be the value of F's [[HomeObject]] internal slot. var home = F.$HomeObject; // 9. Set envRec.[[HomeObject]] to home. envRec.$HomeObject = home; // 10. Set envRec.[[NewTarget]] to newTarget. envRec.$NewTarget = newTarget; // 11. Set env's EnvironmentRecord to envRec. env.environmentRecord = envRec; // 12. Set the outer lexical environment reference of env to the value of F's [[Environment]] internal slot. env.parent = F.$Environment; // 13. Return env. return env; } // ECMA262 8.3.1 }, { key: "GetActiveScriptOrModule", value: function GetActiveScriptOrModule(realm) { // The GetActiveScriptOrModule abstract operation is used to determine the running script or module, based on the active function object. // GetActiveScriptOrModule performs the following steps: // // If the execution context stack is empty, return null. if (realm.contextStack.length === 0) return null; // Let ec be the topmost execution context on the execution context stack whose Function component's [[ScriptOrModule]] component is not null. // If such an execution context exists, return ec's Function component's [[ScriptOrModule]] slot's value. var ec = void 0; for (var i = realm.contextStack.length - 1; i >= 0; i--) { ec = realm.contextStack[i]; var F = ec.function; if (F == null) continue; if (F.$ScriptOrModule instanceof Object) { return F.$ScriptOrModule; } } // Otherwise, let ec be the running execution context. ec = realm.getRunningContext(); // Assert: ec's ScriptOrModule component is not null. (0, _invariant2.default)(ec.ScriptOrModule !== null); // Return ec's ScriptOrModule component. return ec.ScriptOrModule; } // ECMA262 8.3.3 }, { key: "GetThisEnvironment", value: function GetThisEnvironment(realm) { // 1. Let lex be the running execution context's LexicalEnvironment. var lex = realm.getRunningContext().lexicalEnvironment; // 2. Repeat while (true) { // a. Let envRec be lex's EnvironmentRecord. var envRec = lex.environmentRecord; // b. Let exists be envRec.HasThisBinding(). var exists = envRec.HasThisBinding(); // c. If exists is true, return envRec. if (exists) return envRec; // d. Let outer be the value of lex's outer environment reference. var outer = lex.parent; (0, _invariant2.default)(outer); // e. Let lex be outer. lex = outer; } (0, _invariant2.default)(false); } // ECMA262 8.3.4 }, { key: "ResolveThisBinding", value: function ResolveThisBinding(realm) { // 1. Let envRec be GetThisEnvironment( ). var envRec = this.GetThisEnvironment(realm); // 2. Return ? envRec.GetThisBinding(). return envRec.GetThisBinding(); } }, { key: "BindingInitialization", value: function BindingInitialization(realm, node, value, strictCode, environment) { if (node.type === "ArrayPattern") { // ECMA262 13.3.3.5 // 1. Let iterator be ? GetIterator(value). var iterator = (0, _index2.GetIterator)(realm, value); // 2. Let iteratorRecord be Record {[[Iterator]]: iterator, [[Done]]: false}. var iteratorRecord = { $Iterator: iterator, $Done: false }; var result = void 0; // 3. Let result be IteratorBindingInitialization for ArrayBindingPattern using iteratorRecord and environment as arguments. try { result = this.IteratorBindingInitialization(realm, node.elements, iteratorRecord, strictCode, environment); } catch (error) { // 4. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iterator, result). if (iteratorRecord.$Done === false && error instanceof _completions.AbruptCompletion) { throw (0, _index2.IteratorClose)(realm, iterator, error); } throw error; } // 4. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iterator, result). if (iteratorRecord.$Done === false) { var completion = (0, _index2.IteratorClose)(realm, iterator, new _completions.NormalCompletion(realm.intrinsics.undefined)); if (completion instanceof _completions.AbruptCompletion) { throw completion; } } // 5. Return result. return result; } else if (node.type === "ObjectPattern") { // ECMA262 13.3.3.5 // BindingPattern : ObjectBindingPattern // 1. Perform ? RequireObjectCoercible(value). (0, _index2.RequireObjectCoercible)(realm, value); // 2. Return the result of performing BindingInitialization for ObjectBindingPattern using value and environment as arguments. var _iteratorNormalCompletion6 = true; var _didIteratorError6 = false; var _iteratorError6 = undefined; try { for (var _iterator6 = node.properties[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { var property = _step6.value; var env = environment ? environment : realm.getRunningContext().lexicalEnvironment; // 1. Let P be the result of evaluating PropertyName. var P = (0, _ObjectExpression.EvalPropertyName)(property, env, realm, strictCode); // 2. ReturnIfAbrupt(P). // 3. Return the result of performing KeyedBindingInitialization for BindingElement using value, environment, and P as arguments. this.KeyedBindingInitialization(realm, property.value, value, strictCode, environment, P); } } catch (err) { _didIteratorError6 = true; _iteratorError6 = err; } finally { try { if (!_iteratorNormalCompletion6 && _iterator6.return) { _iterator6.return(); } } finally { if (_didIteratorError6) { throw _iteratorError6; } } } } else if (node.type === "Identifier") { // ECMA262 12.1.5 // 1. Let name be StringValue of Identifier. var name = node.name; // 2. Return ? InitializeBoundName(name, value, environment). return this.InitializeBoundName(realm, name, value, environment); } else { (0, _invariant2.default)(node.type === "VariableDeclaration"); // ECMA262 13.7.5.9 var _iteratorNormalCompletion7 = true; var _didIteratorError7 = false; var _iteratorError7 = undefined; try { for (var _iterator7 = node.declarations[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { var decl = _step7.value; this.BindingInitialization(realm, decl.id, value, strictCode, environment); } } catch (err) { _didIteratorError7 = true; _iteratorError7 = err; } finally { try { if (!_iteratorNormalCompletion7 && _iterator7.return) { _iterator7.return(); } } finally { if (_didIteratorError7) { throw _iteratorError7; } } } } } // ECMA262 13.3.3.6 // ECMA262 14.1.19 }, { key: "IteratorBindingInitialization", value: function IteratorBindingInitialization(realm, formals, iteratorRecord, strictCode, environment) { var env = environment ? environment : realm.getRunningContext().lexicalEnvironment; // Check if the last formal is a rest element. If so then we want to save the // element and handle it separately after we iterate through the other // formals. This also enforces that a rest element may only ever be in the // last position. var restEl = void 0; if (formals.length > 0) { var lastFormal = formals[formals.length - 1]; if (lastFormal !== null && lastFormal.type === "RestElement") { restEl = lastFormal; formals = formals.slice(0, -1); } } var _iteratorNormalCompletion8 = true; var _didIteratorError8 = false; var _iteratorError8 = undefined; try { for (var _iterator8 = formals[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { var param = _step8.value; if (param === null) { // Elision handling in IteratorDestructuringAssignmentEvaluation // 1. If iteratorRecord.[[Done]] is false, then if (iteratorRecord.$Done === false) { // a. Let next be IteratorStep(iteratorRecord.[[Iterator]]). var _next2 = void 0; try { _next2 = (0, _index2.IteratorStep)(realm, iteratorRecord.$Iterator); } catch (e) { // b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // c. ReturnIfAbrupt(next). throw e; } // d. If next is false, set iteratorRecord.[[Done]] to true. if (_next2 === false) { iteratorRecord.$Done = true; } } // 2. Return NormalCompletion(empty). continue; } var Initializer = void 0; if (param.type === "AssignmentPattern") { Initializer = param.right; param = param.left; } if (param.type === "Identifier") { // SingleNameBinding : BindingIdentifier Initializer // 1. Let bindingId be StringValue of BindingIdentifier. var bindingId = param.name; // 2. Let lhs be ? ResolveBinding(bindingId, environment). var _lhs = this.ResolveBinding(realm, param.name, strictCode, environment); // Initialized later in the algorithm. var v = void 0; // 3. If iteratorRecord.[[Done]] is false, then if (iteratorRecord.$Done === false) { // a. Let next be IteratorStep(iteratorRecord.[[Iterator]]). var _next3 = void 0; try { _next3 = (0, _index2.IteratorStep)(realm, iteratorRecord.$Iterator); } catch (e) { // b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // c. ReturnIfAbrupt(next). throw e; } // d. If next is false, set iteratorRecord.[[Done]] to true. if (_next3 === false) { iteratorRecord.$Done = true; // Normally this assignment would be done in step 4, but we do it // here so that Flow knows `v` will always be initialized by step 5. v = realm.intrinsics.undefined; } else { // e. Else, // i. Let v be IteratorValue(next). try { v = (0, _index2.IteratorValue)(realm, _next3); } catch (e) { // ii. If v is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // iii. ReturnIfAbrupt(v). throw e; } } } else { // 4. If iteratorRecord.[[Done]] is true, let v be undefined. v = realm.intrinsics.undefined; } // 5. If Initializer is present and v is undefined, then if (Initializer && v instanceof _index.UndefinedValue) { // a. Let defaultValue be the result of evaluating Initializer. var defaultValue = env.evaluate(Initializer, strictCode); // b. Let v be ? GetValue(defaultValue). v = this.GetValue(realm, defaultValue); // c. If IsAnonymousFunctionDefinition(Initializer) is true, then if ((0, _index2.IsAnonymousFunctionDefinition)(realm, Initializer) && v instanceof _index.ObjectValue) { // i. Let hasNameProperty be ? HasOwnProperty(v, "name"). var hasNameProperty = (0, _index2.HasOwnProperty)(realm, v, "name"); // ii. If hasNameProperty is false, perform SetFunctionName(v, bindingId). if (hasNameProperty === false) { _singletons.Functions.SetFunctionName(realm, v, bindingId); } } } // 6. If environment is undefined, return ? PutValue(lhs, v). if (!environment) { _singletons.Properties.PutValue(realm, _lhs, v); continue; } // 7. Return InitializeReferencedBinding(lhs, v). this.InitializeReferencedBinding(realm, _lhs, v); continue; } else { (0, _invariant2.default)(param.type === "ObjectPattern" || param.type === "ArrayPattern"); // BindingElement : BindingPatternInitializer // Initialized later in the algorithm. var _v = void 0; // 1. If iteratorRecord.[[Done]] is false, then if (iteratorRecord.$Done === false) { // a. Let next be IteratorStep(iteratorRecord.[[Iterator]]). var _next4 = void 0; try { _next4 = (0, _index2.IteratorStep)(realm, iteratorRecord.$Iterator); } catch (e) { // b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // c. ReturnIfAbrupt(next). throw e; } // d. If next is false, set iteratorRecord.[[Done]] to true. if (_next4 === false) { iteratorRecord.$Done = true; // Normally this assignment would be done in step 2, but we do it // here so that Flow knows `v` will always be initialized by step 3. _v = realm.intrinsics.undefined; } else { // e. Else, // i. Let v be IteratorValue(next). try { _v = (0, _index2.IteratorValue)(realm, _next4); } catch (e) { // ii. If v is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // iii. ReturnIfAbrupt(v). throw e; } } } else { // 2. If iteratorRecord.[[Done]] is true, let v be undefined. _v = realm.intrinsics.undefined; } // 3. If Initializer is present and v is undefined, then if (Initializer && _v instanceof _index.UndefinedValue) { // a. Let defaultValue be the result of evaluating Initializer. var _defaultValue = env.evaluate(Initializer, strictCode); // b. Let v be ? GetValue(defaultValue). _v = this.GetValue(realm, _defaultValue); } // 4. Return the result of performing BindingInitialization of BindingPattern with v and environment as the arguments. this.BindingInitialization(realm, param, _v, strictCode, environment); continue; } } // Handle the rest element if we have one. } catch (err) { _didIteratorError8 = true; _iteratorError8 = err; } finally { try { if (!_iteratorNormalCompletion8 && _iterator8.return) { _iterator8.return(); } } finally { if (_didIteratorError8) { throw _iteratorError8; } } } if (restEl && restEl.argument.type === "Identifier") { // BindingRestElement : ...BindingIdentifier // 1. Let lhs be ? ResolveBinding(StringValue of BindingIdentifier, environment). var lhs = this.ResolveBinding(realm, restEl.argument.name, strictCode, environment); // 2. Let A be ArrayCreate(0). var A = _singletons.Create.ArrayCreate(realm, 0); // 3. Let n be 0. var n = 0; // 4. Repeat, while (true) { // Initialized later in the algorithm. var next = void 0; // a. If iteratorRecord.[[Done]] is false, then if (iteratorRecord.$Done === false) { // i. Let next be IteratorStep(iteratorRecord.[[Iterator]]). try { next = (0, _index2.IteratorStep)(realm, iteratorRecord.$Iterator); } catch (e) { // ii. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // iii. ReturnIfAbrupt(next). throw e; } // iv. If next is false, set iteratorRecord.[[Done]] to true. if (next === false) { iteratorRecord.$Done = true; } } // b. If iteratorRecord.[[Done]] is true, then if (iteratorRecord.$Done === true) { // i. If environment is undefined, return ? PutValue(lhs, A). if (!environment) { _singletons.Properties.PutValue(realm, lhs, A); break; } // ii. Return InitializeReferencedBinding(lhs, A). this.InitializeReferencedBinding(realm, lhs, A); break; } // Given the nature of the algorithm this should always be true, however // it is difficult to arrange the code in such a way where Flow's control // flow analysis will pick that up, so we add an invariant here. (0, _invariant2.default)(next instanceof _index.ObjectValue); // c. Let nextValue be IteratorValue(next). var nextValue = void 0; try { nextValue = (0, _index2.IteratorValue)(realm, next); } catch (e) { // d. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // e. ReturnIfAbrupt(nextValue). throw e; } // f. Let status be CreateDataProperty(A, ! To.ToString(n), nextValue). var status = _singletons.Create.CreateDataProperty(realm, A, n.toString(), nextValue); // g. Assert: status is true. (0, _invariant2.default)(status, "expected to create data property"); // h. Increment n by 1. n += 1; } } else if (restEl) { (0, _invariant2.default)(restEl.argument.type === "ArrayPattern" || restEl.argument.type === "ObjectPattern"); // 1. Let A be ArrayCreate(0). var _A = _singletons.Create.ArrayCreate(realm, 0); // 2. Let n be 0. var _n = 0; // 3. Repeat, while (true) { // Initialized later in the algorithm. var _next = void 0; // a. If iteratorRecord.[[Done]] is false, then if (iteratorRecord.$Done === false) { // i. Let next be IteratorStep(iteratorRecord.[[Iterator]]). try { _next = (0, _index2.IteratorStep)(realm, iteratorRecord.$Iterator); } catch (e) { // ii. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // iii. ReturnIfAbrupt(next). throw e; } // iv. If next is false, set iteratorRecord.[[Done]] to true. if (_next === false) { iteratorRecord.$Done = true; } } // b. If iteratorRecord.[[Done]] is true, then if (iteratorRecord.$Done === true) { // i. Return the result of performing BindingInitialization of BindingPattern with A and environment as the arguments. this.BindingInitialization(realm, restEl.argument, _A, strictCode, environment); break; } // Given the nature of the algorithm this should always be true, however // it is difficult to arrange the code in such a way where Flow's control // flow analysis will pick that up, so we add an invariant here. (0, _invariant2.default)(_next instanceof _index.ObjectValue); // c. Let nextValue be IteratorValue(next). var _nextValue = void 0; try { _nextValue = (0, _index2.IteratorValue)(realm, _next); } catch (e) { // d. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. if (e instanceof _completions.AbruptCompletion) { iteratorRecord.$Done = true; } // e. ReturnIfAbrupt(nextValue). throw e; } // f. Let status be CreateDataProperty(A, ! To.ToString(n), nextValue). var _status = _singletons.Create.CreateDataProperty(realm, _A, _n.toString(), _nextValue); // g. Assert: status is true. (0, _invariant2.default)(_status, "expected to create data property"); // h. Increment n by 1. _n += 1; } } } // ECMA262 12.1.5.1 }, { key: "InitializeBoundName", value: function InitializeBoundName(realm, name, value, environment) { // 1. Assert: Type(name) is String. (0, _invariant2.default)(typeof name === "string", "expected name to be a string"); // 2. If environment is not undefined, then if (environment) { // a. Let env be the EnvironmentRecord component of environment. var env = environment.environmentRecord; // b. Perform env.InitializeBinding(name, value). env.InitializeBinding(name, value); // c. Return NormalCompletion(undefined). return realm.intrinsics.undefined; } else { // 3. Else, // a. Let lhs be ResolveBinding(name). // Note that the undefined environment implies non-strict. var lhs = this.ResolveBinding(realm, name, false); // b. Return ? PutValue(lhs, value). return _singletons.Properties.PutValue(realm, lhs, value); } } // ECMA262 12.3.1.3 and 13.7.5.6 }, { key: "IsDestructuring", value: function IsDestructuring(ast) { switch (ast.type) { case "VariableDeclaration": var _iteratorNormalCompletion9 = true; var _didIteratorError9 = false; var _iteratorError9 = undefined; try { for (var _iterator9 = ast.declarations[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) { var decl = _step9.value; switch (decl.type) { case "VariableDeclarator": switch (decl.id.type) { case "ArrayPattern": case "AssignmentPattern": case "ObjectPattern": return true; default: break; } break; default: break; } } } catch (err) { _didIteratorError9 = true; _iteratorError9 = err; } finally { try { if (!_iteratorNormalCompletion9 && _iterator9.return) { _iterator9.return(); } } finally { if (_didIteratorError9) { throw _iteratorError9; } } } return false; case "ArrayLiteral": case "ObjectLiteral": return true; case "ArrayPattern": case "ObjectPattern": return true; default: return false; } } // ECMA262 13.3.3.7 }, { key: "KeyedBindingInitialization", value: function KeyedBindingInitialization(realm, node, value, strictCode, environment, propertyName) { var env = environment ? environment : realm.getRunningContext().lexicalEnvironment; var Initializer = void 0; if (node.type === "AssignmentPattern") { Initializer = node.right; node = node.left; } if (node.type === "Identifier") { // SingleNameBinding : BindingIdentifier Initializer // 1. Let bindingId be StringValue of BindingIdentifier. var bindingId = node.name; // 2. Let lhs be ? ResolveBinding(bindingId, environment). var lhs = this.ResolveBinding(realm, bindingId, strictCode, environment); // 3. Let v be ? GetV(value, propertyName). var v = (0, _index2.GetV)(realm, value, propertyName); // 4. If Initializer is present and v is undefined, then if (Initializer && v instanceof _index.UndefinedValue) { // a. Let defaultValue be the result of evaluating Initializer. var defaultValue = env.evaluate(Initializer, strictCode); // b. Let v be ? GetValue(defaultValue). v = this.GetValue(realm, defaultValue); // c. If IsAnonymousFunctionDefinition(Initializer) is true, then if ((0, _index2.IsAnonymousFunctionDefinition)(realm, Initializer) && v instanceof _index.ObjectValue) { // i. Let hasNameProperty be ? HasOwnProperty(v, "name"). var hasNameProperty = (0, _index2.HasOwnProperty)(realm, v, "name"); // ii. If hasNameProperty is false, perform SetFunctionName(v, bindingId). if (hasNameProperty === false) { _singletons.Functions.SetFunctionName(realm, v, bindingId); } } } // 5. If environment is undefined, return ? PutValue(lhs, v). if (!environment) return _singletons.Properties.PutValue(realm, lhs, v); // 6. Return InitializeReferencedBinding(lhs, v). return this.InitializeReferencedBinding(realm, lhs, v); } else if (node.type === "ObjectPattern" || node.type === "ArrayPattern") { // BindingElement : BindingPattern Initializer // 1. Let v be ? GetV(value, propertyName). var _v2 = (0, _index2.GetV)(realm, value, propertyName); // 2. If Initializer is present and v is undefined, then if (Initializer && _v2 instanceof _index.UndefinedValue) { // a. Let defaultValue be the result of evaluating Initializer. var _defaultValue2 = env.evaluate(Initializer, strictCode); // b. Let v be ? GetValue(defaultValue). _v2 = this.GetValue(realm, _defaultValue2); } // 3. Return the result of performing BindingInitialization for BindingPattern passing v and environment as arguments. return this.BindingInitialization(realm, node, _v2, strictCode, env); } } }]); return EnvironmentImplementation; }(); //# sourceMappingURL=environment.js.map