411 lines
16 KiB
JavaScript
411 lines
16 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.InternalGetResultValue = InternalGetResultValue;
|
|
exports.LoopContinues = LoopContinues;
|
|
exports.ForInOfHeadEvaluation = ForInOfHeadEvaluation;
|
|
exports.ForInOfBodyEvaluation = ForInOfBodyEvaluation;
|
|
|
|
exports.default = function (ast, strictCode, env, realm, labelSet) {
|
|
var left = ast.left,
|
|
right = ast.right,
|
|
body = ast.body;
|
|
|
|
|
|
try {
|
|
if (left.type === "VariableDeclaration") {
|
|
if (left.kind === "var") {
|
|
// for (var ForBinding o fAssignmentExpression) Statement
|
|
// 1. Let keyResult be the result of performing ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate).
|
|
var keyResult = ForInOfHeadEvaluation(realm, env, [], right, "iterate", strictCode);
|
|
(0, _invariant2.default)(keyResult instanceof _index.ObjectValue);
|
|
|
|
// 2. Return ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, varBinding, labelSet).
|
|
return ForInOfBodyEvaluation(realm, env, left.declarations[0].id, body, keyResult, "varBinding", labelSet, strictCode);
|
|
} else {
|
|
// for (ForDeclaration of AssignmentExpression) Statement
|
|
// 1. Let keyResult be the result of performing ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, AssignmentExpression, iterate).
|
|
var _keyResult = ForInOfHeadEvaluation(realm, env, _singletons.Environment.BoundNames(realm, left), right, "iterate", strictCode);
|
|
(0, _invariant2.default)(_keyResult instanceof _index.ObjectValue);
|
|
|
|
// 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, lexicalBinding, labelSet).
|
|
return ForInOfBodyEvaluation(realm, env, left, body, _keyResult, "lexicalBinding", labelSet, strictCode);
|
|
}
|
|
} else {
|
|
// for (LeftHandSideExpression of AssignmentExpression) Statement
|
|
// 1. Let keyResult be the result of performing ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate).
|
|
var _keyResult2 = ForInOfHeadEvaluation(realm, env, [], right, "iterate", strictCode);
|
|
(0, _invariant2.default)(_keyResult2 instanceof _index.ObjectValue);
|
|
|
|
// 2. Return ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, assignment, labelSet).
|
|
return ForInOfBodyEvaluation(realm, env, left, body, _keyResult2, "assignment", labelSet, strictCode);
|
|
}
|
|
} catch (e) {
|
|
if (e instanceof _completions.BreakCompletion) {
|
|
if (!e.target) return (0, _index2.UpdateEmpty)(realm, e, realm.intrinsics.undefined).value;
|
|
}
|
|
throw e;
|
|
}
|
|
};
|
|
|
|
var _errors = require("../errors.js");
|
|
|
|
var _environment = require("../environment.js");
|
|
|
|
var _completions = require("../completions.js");
|
|
|
|
var _index = require("../values/index.js");
|
|
|
|
var _invariant = require("../invariant.js");
|
|
|
|
var _invariant2 = _interopRequireDefault(_invariant);
|
|
|
|
var _index2 = require("../methods/index.js");
|
|
|
|
var _singletons = require("../singletons.js");
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
|
|
function InternalGetResultValue(realm, result) {
|
|
if (result instanceof _completions.AbruptCompletion) {
|
|
return result.value;
|
|
} else {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// ECMA262 13.7.1.2
|
|
function LoopContinues(realm, completion, labelSet) {
|
|
// 1. If completion.[[Type]] is normal, return true.
|
|
if (completion instanceof _index.Value) return true;
|
|
(0, _invariant2.default)(completion instanceof _completions.AbruptCompletion);
|
|
|
|
// 2. If completion.[[Type]] is not continue, return false.
|
|
if (!(completion instanceof _completions.ContinueCompletion)) return false;
|
|
|
|
// 3. If completion.[[Target]] is empty, return true.
|
|
if (!completion.target) return true;
|
|
|
|
// 4. If completion.[[Target]] is an element of labelSet, return true.
|
|
if (labelSet != null && labelSet.indexOf(completion.target) >= 0) return true;
|
|
|
|
// 5. Return false.
|
|
return false;
|
|
}
|
|
|
|
// ECMA262 13.7.5.10
|
|
function BindingInstantiation(realm, ast, env) {
|
|
// ast = ForDeclaration : LetOrConst ForBinding
|
|
|
|
// 1. Let envRec be environment's EnvironmentRecord.
|
|
var envRec = env.environmentRecord;
|
|
|
|
// 2. Assert: envRec is a declarative Environment Record.
|
|
(0, _invariant2.default)(envRec instanceof _environment.DeclarativeEnvironmentRecord);
|
|
|
|
// 3. For each element name of the BoundNames of ForBinding do
|
|
var _iteratorNormalCompletion = true;
|
|
var _didIteratorError = false;
|
|
var _iteratorError = undefined;
|
|
|
|
try {
|
|
for (var _iterator = _singletons.Environment.BoundNames(realm, ast)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
var name = _step.value;
|
|
|
|
// a. If IsConstantDeclaration of LetOrConst is true, then
|
|
if (ast.kind === "const") {
|
|
// i. Perform ! envRec.CreateImmutableBinding(name, true).
|
|
envRec.CreateImmutableBinding(name, true);
|
|
} else {
|
|
// b.
|
|
// i. Perform ! envRec.CreateMutableBinding(name, false).
|
|
envRec.CreateMutableBinding(name, false);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError = true;
|
|
_iteratorError = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
|
_iterator.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError) {
|
|
throw _iteratorError;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ECMA262 13.7.5.12
|
|
function ForInOfHeadEvaluation(realm, env, TDZnames, expr, iterationKind, strictCode) {
|
|
// 1. Let oldEnv be the running execution context's LexicalEnvironment.
|
|
var oldEnv = realm.getRunningContext().lexicalEnvironment;
|
|
|
|
// 2. If TDZnames is not an empty List, then
|
|
if (TDZnames.length) {
|
|
// a. Assert: TDZnames has no duplicate entries.
|
|
|
|
// b. Let TDZ be NewDeclarativeEnvironment(oldEnv).
|
|
var TDZ = _singletons.Environment.NewDeclarativeEnvironment(realm, oldEnv);
|
|
|
|
// c. Let TDZEnvRec be TDZ's EnvironmentRecord.
|
|
var TDZEnvRec = TDZ.environmentRecord;
|
|
|
|
// d. For each string name in TDZnames, do
|
|
var _iteratorNormalCompletion2 = true;
|
|
var _didIteratorError2 = false;
|
|
var _iteratorError2 = undefined;
|
|
|
|
try {
|
|
for (var _iterator2 = TDZnames[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
|
var name = _step2.value;
|
|
|
|
// i. Perform ! TDZEnvRec.CreateMutableBinding(name, false).
|
|
TDZEnvRec.CreateMutableBinding(name, false);
|
|
}
|
|
|
|
// e. Set the running execution context's LexicalEnvironment to TDZ.
|
|
} catch (err) {
|
|
_didIteratorError2 = true;
|
|
_iteratorError2 = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
|
_iterator2.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError2) {
|
|
throw _iteratorError2;
|
|
}
|
|
}
|
|
}
|
|
|
|
realm.getRunningContext().lexicalEnvironment = TDZ;
|
|
env = TDZ;
|
|
}
|
|
|
|
var exprRef = void 0;
|
|
try {
|
|
// 3. Let exprRef be the result of evaluating expr.
|
|
exprRef = env.evaluate(expr, strictCode);
|
|
} finally {
|
|
// 4. Set the running execution context's LexicalEnvironment to oldEnv.
|
|
var lexEnv = realm.getRunningContext().lexicalEnvironment;
|
|
if (lexEnv !== oldEnv) realm.onDestroyScope(lexEnv);
|
|
realm.getRunningContext().lexicalEnvironment = oldEnv;
|
|
}
|
|
env = oldEnv;
|
|
|
|
// 5. Let exprValue be ? GetValue(exprRef).
|
|
var exprValue = _singletons.Environment.GetValue(realm, exprRef);
|
|
|
|
// 6. If iterationKind is enumerate, then
|
|
if (iterationKind === "enumerate") {
|
|
// a. If exprValue.[[Value]] is null or undefined, then
|
|
if (exprValue instanceof _index.NullValue || exprValue instanceof _index.UndefinedValue) {
|
|
// i. Return Completion{[[Type]]: break, [[Value]]: empty, [[Target]]: empty}.
|
|
throw new _completions.BreakCompletion(realm.intrinsics.empty, expr.loc, undefined);
|
|
}
|
|
|
|
// b. Let obj be ToObject(exprValue).
|
|
var obj = _singletons.To.ToObjectPartial(realm, exprValue);
|
|
|
|
// c. Return ? EnumerateObjectProperties(obj).
|
|
if (obj.isPartialObject() || obj instanceof _index.AbstractObjectValue) {
|
|
return obj;
|
|
} else {
|
|
return _singletons.Properties.EnumerateObjectProperties(realm, obj);
|
|
}
|
|
} else {
|
|
// 8. Else,
|
|
// 1. Assert: iterationKind is iterate.
|
|
(0, _invariant2.default)(iterationKind === "iterate", "expected iterationKind to be iterate");
|
|
|
|
if (exprValue instanceof _index.AbstractValue) {
|
|
var error = new _errors.CompilerDiagnostic("for of loops over unknown collections are not yet supported", expr.loc, "PP0014", "FatalError");
|
|
realm.handleError(error);
|
|
throw new _errors.FatalError();
|
|
}
|
|
|
|
// 1. Return ? GetIterator(exprValue).
|
|
return (0, _index2.GetIterator)(realm, exprValue);
|
|
}
|
|
}
|
|
|
|
// ECMA262 13.7.5.13
|
|
function ForInOfBodyEvaluation(realm, env, lhs, stmt, iterator, lhsKind, labelSet, strictCode) {
|
|
// 1. Let oldEnv be the running execution context's LexicalEnvironment.
|
|
var oldEnv = realm.getRunningContext().lexicalEnvironment;
|
|
|
|
// 2. Let V be undefined.
|
|
var V = realm.intrinsics.undefined;
|
|
|
|
// 3. Let destructuring be IsDestructuring of lhs.
|
|
var destructuring = _singletons.Environment.IsDestructuring(lhs);
|
|
|
|
// 4. If destructuring is true and if lhsKind is assignment, then
|
|
if (destructuring && lhsKind === "assignment") {
|
|
// a. Assert: lhs is a LeftHandSideExpression.
|
|
(0, _invariant2.default)(lhs.type !== "VariableDeclaration");
|
|
|
|
// b. Let assignmentPattern be the parse of the source text corresponding to lhs using AssignmentPattern as the goal symbol.
|
|
}
|
|
|
|
// 5. Repeat
|
|
while (true) {
|
|
// a. Let nextResult be ? IteratorStep(iterator).
|
|
var nextResult = (0, _index2.IteratorStep)(realm, iterator);
|
|
|
|
// b. If nextResult is false, return NormalCompletion(V).
|
|
if (!nextResult) return V;
|
|
|
|
// c. Let nextValue be ? IteratorValue(nextResult).
|
|
var nextValue = (0, _index2.IteratorValue)(realm, nextResult);
|
|
|
|
// d. If lhsKind is either assignment or varBinding, then
|
|
var iterationEnv = void 0;
|
|
var lhsRef = void 0;
|
|
if (lhsKind === "assignment" || lhsKind === "varBinding") {
|
|
// i. If destructuring is false, then
|
|
if (!destructuring) {
|
|
// 1. Let lhsRef be the result of evaluating lhs. (It may be evaluated repeatedly.)
|
|
lhsRef = env.evaluateCompletion(lhs, strictCode);
|
|
}
|
|
} else {
|
|
// e. Else,
|
|
// i. Assert: lhsKind is lexicalBinding.
|
|
(0, _invariant2.default)(lhsKind === "lexicalBinding", "expected lhsKind to be lexicalBinding");
|
|
(0, _invariant2.default)(lhs.type === "VariableDeclaration");
|
|
|
|
// ii. Assert: lhs is a ForDeclaration.
|
|
|
|
// iii. Let iterationEnv be NewDeclarativeEnvironment(oldEnv).
|
|
iterationEnv = _singletons.Environment.NewDeclarativeEnvironment(realm, oldEnv);
|
|
|
|
// iv. Perform BindingInstantiation for lhs passing iterationEnv as the argument.
|
|
BindingInstantiation(realm, lhs, iterationEnv);
|
|
|
|
// v. Set the running execution context's LexicalEnvironment to iterationEnv.
|
|
realm.getRunningContext().lexicalEnvironment = iterationEnv;
|
|
env = iterationEnv;
|
|
|
|
// vi. If destructuring is false, then
|
|
if (!destructuring) {
|
|
var names = _singletons.Environment.BoundNames(realm, lhs);
|
|
|
|
// 1. Assert: lhs binds a single name.
|
|
(0, _invariant2.default)(names.length === 1, "expected single name");
|
|
|
|
// 2. Let lhsName be the sole element of BoundNames of lhs.
|
|
var lhsName = names[0];
|
|
|
|
// 3. Let lhsRef be ! ResolveBinding(lhsName).
|
|
lhsRef = _singletons.Environment.ResolveBinding(realm, lhsName, strictCode);
|
|
}
|
|
}
|
|
|
|
// f. If destructuring is false, then
|
|
var status = void 0;
|
|
try {
|
|
if (!destructuring) {
|
|
// i. If lhsRef is an abrupt completion, then
|
|
if (lhsRef instanceof _completions.AbruptCompletion) {
|
|
// 1. Let status be lhsRef.
|
|
status = lhsRef;
|
|
} else if (lhsKind === "lexicalBinding") {
|
|
// ii. Else if lhsKind is lexicalBinding, then
|
|
// 1. Let status be InitializeReferencedBinding(lhsRef, nextValue).
|
|
(0, _invariant2.default)(lhsRef instanceof _environment.Reference);
|
|
status = _singletons.Environment.InitializeReferencedBinding(realm, lhsRef, nextValue);
|
|
} else {
|
|
// iii. Else,
|
|
// 1. Let status be PutValue(lhsRef, nextValue).
|
|
(0, _invariant2.default)(lhsRef !== undefined);
|
|
status = _singletons.Properties.PutValue(realm, lhsRef, nextValue);
|
|
}
|
|
} else {
|
|
// g. Else,
|
|
// i. If lhsKind is assignment, then
|
|
if (lhsKind === "assignment") {
|
|
(0, _invariant2.default)(lhs.type === "ArrayPattern" || lhs.type === "ObjectPattern");
|
|
|
|
// 1. Let status be the result of performing DestructuringAssignmentEvaluation of assignmentPattern using nextValue as the argument.
|
|
status = (0, _index2.DestructuringAssignmentEvaluation)(realm, lhs, nextValue, strictCode, iterationEnv || env);
|
|
} else if (lhsKind === "varBinding") {
|
|
// ii. Else if lhsKind is varBinding, then
|
|
// 1. Assert: lhs is a ForBinding.
|
|
|
|
// 2. Let status be the result of performing BindingInitialization for lhs passing nextValue and undefined as the arguments.
|
|
status = _singletons.Environment.BindingInitialization(realm, lhs, nextValue, strictCode, undefined);
|
|
} else {
|
|
// iii. Else,
|
|
// 1. Assert: lhsKind is lexicalBinding.
|
|
(0, _invariant2.default)(lhsKind === "lexicalBinding");
|
|
|
|
// 2. Assert: lhs is a ForDeclaration.
|
|
|
|
// 3. Let status be the result of performing BindingInitialization for lhs passing nextValue and iterationEnv as arguments.
|
|
(0, _invariant2.default)(iterationEnv !== undefined);
|
|
status = _singletons.Environment.BindingInitialization(realm, lhs, nextValue, strictCode, iterationEnv);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
if (e instanceof _completions.AbruptCompletion) {
|
|
status = e;
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
// h. If status is an abrupt completion, then
|
|
if (status instanceof _completions.AbruptCompletion) {
|
|
// i. Set the running execution context's LexicalEnvironment to oldEnv.
|
|
realm.getRunningContext().lexicalEnvironment = oldEnv;
|
|
|
|
// ii. Return ? IteratorClose(iterator, status).
|
|
throw (0, _index2.IteratorClose)(realm, iterator, status);
|
|
}
|
|
|
|
// i. Let result be the result of evaluating stmt.
|
|
var result = env.evaluateCompletion(stmt, strictCode);
|
|
(0, _invariant2.default)(result instanceof _index.Value || result instanceof _completions.AbruptCompletion);
|
|
|
|
// j. Set the running execution context's LexicalEnvironment to oldEnv.
|
|
|
|
var lexEnv = realm.getRunningContext().lexicalEnvironment;
|
|
if (lexEnv !== oldEnv) realm.onDestroyScope(lexEnv);
|
|
realm.getRunningContext().lexicalEnvironment = oldEnv;
|
|
env = oldEnv;
|
|
|
|
// k. If LoopContinues(result, labelSet) is false, return ? IteratorClose(iterator, UpdateEmpty(result, V)).
|
|
if (!LoopContinues(realm, result, labelSet)) {
|
|
(0, _invariant2.default)(result instanceof _completions.AbruptCompletion);
|
|
result = (0, _index2.UpdateEmpty)(realm, result, V);
|
|
(0, _invariant2.default)(result instanceof _completions.AbruptCompletion);
|
|
throw (0, _index2.IteratorClose)(realm, iterator, result);
|
|
}
|
|
|
|
// l. If result.[[Value]] is not empty, let V be result.[[Value]].
|
|
var resultValue = InternalGetResultValue(realm, result);
|
|
if (!(resultValue instanceof _index.EmptyValue)) V = resultValue;
|
|
}
|
|
|
|
/* istanbul ignore next */
|
|
(0, _invariant2.default)(false); // can't get here but there is no other way to make Flow happy
|
|
}
|
|
|
|
// ECMA262 13.7.5.11
|
|
//# sourceMappingURL=ForOfStatement.js.map
|