1301 lines
52 KiB
JavaScript
1301 lines
52 KiB
JavaScript
"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
|