"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /** * 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. */ exports.default = function (ast, strictCode, env, realm, labelSet) { var left = ast.left, right = ast.right, body = ast.body; function reportErrorAndThrowIfNotConcrete(val, loc) { if (val instanceof _index2.AbstractValue) reportError(realm, loc); } try { if (left.type === "VariableDeclaration") { if (left.kind === "var") { // for (var ForBinding in Expression) Statement // 1. Let keyResult be ? ForIn/OfHeadEvaluation(« », Expression, enumerate). var keyResult = (0, _ForOfStatement.ForInOfHeadEvaluation)(realm, env, [], right, "enumerate", strictCode); if (keyResult.isPartialObject() && keyResult.isSimpleObject()) { return emitResidualLoopIfSafe(ast, strictCode, env, realm, left, right, keyResult, body); } reportErrorAndThrowIfNotConcrete(keyResult, right.loc); (0, _invariant2.default)(keyResult instanceof _index2.ObjectValue); // 2. Return ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, varBinding, labelSet). return (0, _ForOfStatement.ForInOfBodyEvaluation)(realm, env, left.declarations[0].id, body, keyResult, "varBinding", labelSet, strictCode); } else { // for (ForDeclaration in Expression) Statement // 1. Let keyResult be the result of performing ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, Expression, enumerate). var _keyResult = (0, _ForOfStatement.ForInOfHeadEvaluation)(realm, env, _singletons.Environment.BoundNames(realm, left), right, "enumerate", strictCode); reportErrorAndThrowIfNotConcrete(_keyResult, right.loc); (0, _invariant2.default)(_keyResult instanceof _index2.ObjectValue); // 2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, lexicalBinding, labelSet). return (0, _ForOfStatement.ForInOfBodyEvaluation)(realm, env, left, body, _keyResult, "lexicalBinding", labelSet, strictCode); } } else { // for (LeftHandSideExpression in Expression) Statement // 1. Let keyResult be ? ForIn/OfHeadEvaluation(« », Expression, enumerate). var _keyResult2 = (0, _ForOfStatement.ForInOfHeadEvaluation)(realm, env, [], right, "enumerate", strictCode); reportErrorAndThrowIfNotConcrete(_keyResult2, right.loc); (0, _invariant2.default)(_keyResult2 instanceof _index2.ObjectValue); // 2. Return ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, assignment, labelSet). return (0, _ForOfStatement.ForInOfBodyEvaluation)(realm, env, left, body, _keyResult2, "assignment", labelSet, strictCode); } } catch (e) { if (e instanceof _completions.BreakCompletion) { if (!e.target) return (0, _index.UpdateEmpty)(realm, e, realm.intrinsics.undefined).value; } throw e; } }; var _completions = require("../completions.js"); var _environment = require("../environment.js"); var _errors = require("../errors.js"); var _ForOfStatement = require("./ForOfStatement.js"); var _index = require("../methods/index.js"); var _singletons = require("../singletons.js"); var _index2 = require("../values/index.js"); var _invariant = require("../invariant.js"); var _invariant2 = _interopRequireDefault(_invariant); var _babelTypes = require("babel-types"); var t = _interopRequireWildcard(_babelTypes); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // helper func to report error function reportError(realm, loc) { var error = new _errors.CompilerDiagnostic("for in loops over unknown objects are not yet supported", loc, "PP0013", "FatalError"); realm.handleError(error); throw new _errors.FatalError(); } // ECMA262 13.7.5.11 function emitResidualLoopIfSafe(ast, strictCode, env, realm, lh, obexpr, ob, body) { (0, _invariant2.default)(ob.isSimpleObject()); var oldEnv = realm.getRunningContext().lexicalEnvironment; var blockEnv = _singletons.Environment.NewDeclarativeEnvironment(realm, oldEnv); realm.getRunningContext().lexicalEnvironment = blockEnv; try { var envRec = blockEnv.environmentRecord; (0, _invariant2.default)(envRec instanceof _environment.DeclarativeEnvironmentRecord, "expected declarative environment record"); var absStr = _index2.AbstractValue.createFromType(realm, _index2.StringValue); var boundName = void 0; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = _singletons.Environment.BoundNames(realm, lh)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var n = _step.value; (0, _invariant2.default)(boundName === undefined); boundName = t.identifier(n); envRec.CreateMutableBinding(n, false); envRec.InitializeBinding(n, absStr); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } var _realm$evaluateNodeFo = realm.evaluateNodeForEffects(body, strictCode, blockEnv), _realm$evaluateNodeFo2 = _slicedToArray(_realm$evaluateNodeFo, 5), compl = _realm$evaluateNodeFo2[0], gen = _realm$evaluateNodeFo2[1], bindings = _realm$evaluateNodeFo2[2], properties = _realm$evaluateNodeFo2[3], createdObj = _realm$evaluateNodeFo2[4]; if (compl instanceof _index2.Value && gen.empty() && bindings.size === 0 && properties.size === 1) { (0, _invariant2.default)(createdObj.size === 0); // or there will be more than one property var targetObject = void 0; var sourceObject = void 0; properties.forEach(function (desc, key, map) { if (key.object.unknownProperty === key) { targetObject = key.object; (0, _invariant2.default)(desc !== undefined); var sourceValue = desc.value; if (sourceValue instanceof _index2.AbstractValue) { // because sourceValue was written to key.object.unknownProperty it must be that var cond = sourceValue.args[0]; // and because the write always creates a value of this shape (0, _invariant2.default)(cond instanceof _index2.AbstractValue && cond.kind === "template for property name condition"); if (sourceValue.args[2] instanceof _index2.UndefinedValue) { // check that the value that was assigned itself came from // an expression of the form sourceObject[absStr]. var mem = sourceValue.args[1]; while (mem instanceof _index2.AbstractValue) { if (mem.kind === "sentinel member expression" && mem.args[0] instanceof _index2.ObjectValue && mem.args[1] === absStr) { sourceObject = mem.args[0]; break; } // check if mem is a test for absStr being equal to a known property // if so skip over it until we get to the expression of the form sourceObject[absStr]. var condition = mem.args[0]; if (condition instanceof _index2.AbstractValue && condition.kind === "check for known property") { if (condition.args[0] === absStr) { mem = mem.args[2]; continue; } } break; } } } } }); if (targetObject instanceof _index2.ObjectValue && sourceObject !== undefined) { var o = ob; if (ob instanceof _index2.AbstractObjectValue && !ob.values.isTop() && ob.values.getElements().size === 1) { // Note that it is not safe, in general, to extract a concrete object from the values domain of // an abstract object. We can get away with it here only because the concrete object does not // escape the code below and is thus never referenced directly in generated code because of this logic. var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = ob.values.getElements()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var oe = _step2.value; o = oe; } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } var generator = realm.generator; (0, _invariant2.default)(generator !== undefined); // make target object simple and partial, so that it returns a fully // abstract value for every property it is queried for. targetObject.makeSimple(); targetObject.makePartial(); if (sourceObject === o) { // Known enumerable properties of sourceObject can become known properties of targetObject. (0, _invariant2.default)(sourceObject.isPartialObject()); sourceObject.makeNotPartial(); // EnumerableOwnProperties is sufficient because sourceObject is simple var keyValPairs = (0, _index.EnumerableOwnProperties)(realm, sourceObject, "key+value"); sourceObject.makePartial(); var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = keyValPairs[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var keyVal = _step3.value; (0, _invariant2.default)(keyVal instanceof _index2.ArrayValue); var key = keyVal.$Get("0", keyVal); var val = keyVal.$Get("1", keyVal); (0, _invariant2.default)(key instanceof _index2.StringValue); // sourceObject is simple targetObject.$Set(key, val, targetObject); } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } // add loop to generator (0, _invariant2.default)(boundName != null); generator.emitForInStatement(o, lh, sourceObject, targetObject, boundName); return realm.intrinsics.undefined; } } } finally { // 6. Set the running execution context's LexicalEnvironment to oldEnv. realm.getRunningContext().lexicalEnvironment = oldEnv; realm.onDestroyScope(blockEnv); } reportError(realm, obexpr.loc); (0, _invariant2.default)(false); } //# sourceMappingURL=ForInStatement.js.map