UNPKG

prepack

Version:

Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.

228 lines (176 loc) 10.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _default; 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 = _interopRequireDefault(require("../invariant.js")); var t = _interopRequireWildcard(require("@babel/types")); 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)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } 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. */ // helper func to report error function reportError(realm, loc) { let 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 _default(ast, strictCode, env, realm, labelSet) { let { left, right, body } = ast; 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). let 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, _invariant.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). let keyResult = (0, _ForOfStatement.ForInOfHeadEvaluation)(realm, env, _singletons.Environment.BoundNames(realm, left), right, "enumerate", strictCode); reportErrorAndThrowIfNotConcrete(keyResult, right.loc); (0, _invariant.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). let keyResult = (0, _ForOfStatement.ForInOfHeadEvaluation)(realm, env, [], right, "enumerate", strictCode); reportErrorAndThrowIfNotConcrete(keyResult, right.loc); (0, _invariant.default)(keyResult instanceof _index2.ObjectValue); // 2. Return ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, assignment, labelSet). return (0, _ForOfStatement.ForInOfBodyEvaluation)(realm, env, left, body, keyResult, "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; } } function emitResidualLoopIfSafe(ast, strictCode, env, realm, lh, obexpr, ob, body) { (0, _invariant.default)(ob.isSimpleObject()); let oldEnv = realm.getRunningContext().lexicalEnvironment; let blockEnv = _singletons.Environment.NewDeclarativeEnvironment(realm, oldEnv); realm.getRunningContext().lexicalEnvironment = blockEnv; try { let envRec = blockEnv.environmentRecord; (0, _invariant.default)(envRec instanceof _environment.DeclarativeEnvironmentRecord, "expected declarative environment record"); let absStr = _index2.AbstractValue.createFromType(realm, _index2.StringValue); let boundName; for (let n of _singletons.Environment.BoundNames(realm, lh)) { (0, _invariant.default)(boundName === undefined); boundName = t.identifier(n); envRec.CreateMutableBinding(n, false); envRec.InitializeBinding(n, absStr); } let { result, generator: gen, modifiedBindings, modifiedProperties, createdObjects } = realm.evaluateNodeForEffects(body, strictCode, blockEnv); if (result instanceof _completions.SimpleNormalCompletion && gen.empty() && modifiedBindings.size === 0 && modifiedProperties.size === 1) { (0, _invariant.default)(createdObjects.size === 0); // or there will be more than one property let targetObject; let sourceObject; modifiedProperties.forEach((desc, key, map) => { if (key.object.unknownProperty === key) { targetObject = key.object; (0, _invariant.default)(desc !== undefined); let sourceValue = desc.throwIfNotConcrete(realm).value; if (sourceValue instanceof _index2.AbstractValue) { // because sourceValue was written to key.object.unknownProperty it must be that let cond = sourceValue.args[0]; // and because the write always creates a value of this shape (0, _invariant.default)(cond instanceof _index2.AbstractValue && cond.kind === "template for property name condition"); let falseVal = sourceValue.args[2]; if (falseVal instanceof _index2.AbstractValue && falseVal.kind === "template for prototype member expression") { // check that the value that was assigned itself came from // an expression of the form sourceObject[absStr]. let 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]. let 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) { let 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. for (let oe of ob.values.getElements()) { (0, _invariant.default)(oe instanceof _index2.ObjectValue); o = oe; } } let generator = realm.generator; (0, _invariant.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, _invariant.default)(sourceObject.isPartialObject()); // EnumerableOwnProperties is sufficient because sourceObject is simple let keyValPairs = (0, _index.EnumerableOwnProperties)(realm, sourceObject, "key+value", true); for (let keyVal of keyValPairs) { (0, _invariant.default)(keyVal instanceof _index2.ArrayValue); let key = keyVal.$Get("0", keyVal); let val = keyVal.$Get("1", keyVal); (0, _invariant.default)(key instanceof _index2.StringValue); // sourceObject is simple targetObject.$Set(key, val, targetObject); } } // add loop to generator (0, _invariant.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, _invariant.default)(false); } //# sourceMappingURL=ForInStatement.js.map