prepack
Version:
Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.
266 lines (189 loc) • 10.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _errors = require("../errors.js");
var _index = require("../domains/index.js");
var _index2 = require("../values/index.js");
var _environment = require("../environment.js");
var _invariant = _interopRequireDefault(require("../invariant.js"));
var _index3 = 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.
*/
/* strict-local */
//import { SimpleNormalCompletion } from "../completions.js";
function isInstance(proto, Constructor) {
return proto instanceof Constructor || proto === Constructor.prototype;
}
function evaluateDeleteOperation(expr, realm) {
// ECMA262 12.5.3.2
// 1. Let ref be the result of evaluating UnaryExpression.
let ref = expr; // 2. ReturnIfAbrupt(ref).
// 3. If Type(ref) is not Reference, return true.
if (!(ref instanceof _environment.Reference)) return realm.intrinsics.true; // 4. If IsUnresolvableReference(ref) is true, then
if (_singletons.Environment.IsUnresolvableReference(realm, ref)) {
// a. Assert: IsStrictReference(ref) is false.
(0, _invariant.default)(!_singletons.Environment.IsStrictReference(realm, ref), "did not expect a strict reference"); // b. Return true.
return realm.intrinsics.true;
} // 5. If IsPropertyReference(ref) is true, then
if (_singletons.Environment.IsPropertyReference(realm, ref)) {
// a. If IsSuperReference(ref) is true, throw a ReferenceError exception.
if (_singletons.Environment.IsSuperReference(realm, ref)) {
throw realm.createErrorThrowCompletion(realm.intrinsics.ReferenceError);
} // b. Let baseObj be ! ToObject(GetBase(ref)).
let base = _singletons.Environment.GetBase(realm, ref); // Constructing the reference checks that base is coercible to an object hence
(0, _invariant.default)(base instanceof _index2.ConcreteValue || base instanceof _index2.AbstractObjectValue);
let baseObj = _singletons.To.ToObject(realm, base); // c. Let deleteStatus be ? baseObj.[[Delete]](GetReferencedName(ref)).
let deleteStatus = baseObj.$Delete(_singletons.Environment.GetReferencedName(realm, ref)); // d. If deleteStatus is false and IsStrictReference(ref) is true, throw a TypeError exception.
if (!deleteStatus && _singletons.Environment.IsStrictReference(realm, ref)) {
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
} // e. Return deleteStatus.
return new _index2.BooleanValue(realm, deleteStatus);
} // 6. Else ref is a Reference to an Environment Record binding,
// a. Let bindings be GetBase(ref).
let bindings = _singletons.Environment.GetBase(realm, ref);
(0, _invariant.default)(bindings instanceof _environment.EnvironmentRecord); // b. Return ? bindings.DeleteBinding(GetReferencedName(ref)).
let referencedName = _singletons.Environment.GetReferencedName(realm, ref);
(0, _invariant.default)(typeof referencedName === "string");
return new _index2.BooleanValue(realm, bindings.DeleteBinding(referencedName));
}
function tryToEvaluateOperationOrLeaveAsAbstract(ast, expr, func, strictCode, realm) {
let effects;
try {
effects = realm.evaluateForEffects(() => func(ast, expr, strictCode, realm), undefined, "tryToEvaluateOperationOrLeaveAsAbstract");
} catch (error) {
if (error instanceof _errors.FatalError) {
return realm.evaluateWithPossibleThrowCompletion(() => {
let value = _singletons.Environment.GetValue(realm, expr); // if the value is abstract, then create a unary op for it,
// otherwise we rethrow the error as we don't handle it at this
// point in time
if (value instanceof _index2.AbstractValue) {
return _index2.AbstractValue.createFromUnaryOp(realm, ast.operator, value);
}
throw error;
}, _index.TypesDomain.topVal, _index.ValuesDomain.topVal);
} else {
throw error;
}
}
realm.applyEffects(effects);
return realm.returnOrThrowCompletion(effects.result);
}
function evaluateOperation(ast, expr, strictCode, realm) {
function reportError(value) {
if (value.getType() === _index2.SymbolValue) {
// Symbols never implicitly coerce to primitives.
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
}
let error = new _errors.CompilerDiagnostic("might be a symbol or an object with an unknown valueOf or toString or Symbol.toPrimitive method", ast.argument.loc, "PP0008", "RecoverableError");
if (realm.handleError(error) === "Fail") throw new _errors.FatalError();
}
if (ast.operator === "+") {
// ECMA262 12.5.6.1
// 1. Let expr be the result of evaluating UnaryExpression.
expr; // 2. Return ? ToNumber(? GetValue(expr)).
let value = _singletons.Environment.GetValue(realm, expr);
if (value instanceof _index2.AbstractValue) {
if (!_singletons.To.IsToNumberPure(realm, value)) reportError(value);
return _index2.AbstractValue.createFromUnaryOp(realm, "+", value);
}
(0, _invariant.default)(value instanceof _index2.ConcreteValue);
return _index2.IntegralValue.createFromNumberValue(realm, _singletons.To.ToNumber(realm, value));
} else if (ast.operator === "-") {
// ECMA262 12.5.7.1
// 1. Let expr be the result of evaluating UnaryExpression.
expr; // 2. Let oldValue be ? ToNumber(? GetValue(expr)).
let value = _singletons.Environment.GetValue(realm, expr);
if (value instanceof _index2.AbstractValue) {
if (!_singletons.To.IsToNumberPure(realm, value)) reportError(value);
return _index2.AbstractValue.createFromUnaryOp(realm, "-", value);
}
(0, _invariant.default)(value instanceof _index2.ConcreteValue);
let oldValue = _singletons.To.ToNumber(realm, value); // 3. If oldValue is NaN, return NaN.
if (isNaN(oldValue)) {
return realm.intrinsics.NaN;
} // 4. Return the result of negating oldValue; that is, compute a Number with the same magnitude but opposite sign.
return _index2.IntegralValue.createFromNumberValue(realm, -oldValue);
} else if (ast.operator === "~") {
// ECMA262 12.5.8
// 1. Let expr be the result of evaluating UnaryExpression.
expr; // 2. Let oldValue be ? ToInt32(? GetValue(expr)).
let value = _singletons.Environment.GetValue(realm, expr);
if (value instanceof _index2.AbstractValue) {
if (!_singletons.To.IsToNumberPure(realm, value)) reportError(value);
return _index2.AbstractValue.createFromUnaryOp(realm, "~", value);
}
(0, _invariant.default)(value instanceof _index2.ConcreteValue);
let oldValue = _singletons.To.ToInt32(realm, value); // 3. Return the result of applying bitwise complement to oldValue. The result is a signed 32-bit integer.
return _index2.IntegralValue.createFromNumberValue(realm, ~oldValue);
} else if (ast.operator === "!") {
// ECMA262 12.6.9
// 1. Let expr be the result of evaluating UnaryExpression.
expr; // 2. Let oldValue be ToBoolean(? GetValue(expr)).
let value = _singletons.Environment.GetConditionValue(realm, expr);
if (value instanceof _index2.AbstractValue) return _index2.AbstractValue.createFromUnaryOp(realm, "!", value);
(0, _invariant.default)(value instanceof _index2.ConcreteValue);
let oldValue = _singletons.To.ToBoolean(realm, value); // 3. If oldValue is true, return false.
if (oldValue === true) return realm.intrinsics.false; // 4. Return true.
return realm.intrinsics.true;
} else if (ast.operator === "void") {
// 1. Let expr be the result of evaluating UnaryExpression.
expr; // 2. Perform ? GetValue(expr).
_singletons.Environment.GetValue(realm, expr); // 3. Return undefined.
return realm.intrinsics.undefined;
} else {
(0, _invariant.default)(ast.operator === "typeof"); // ECMA262 12.6.5
// 1. Let val be the result of evaluating UnaryExpression.
let val = expr; // 2. If Type(val) is Reference, then
if (val instanceof _environment.Reference) {
// a. If IsUnresolvableReference(val) is true, return "undefined".
if (_singletons.Environment.IsUnresolvableReference(realm, val)) {
return new _index2.StringValue(realm, "undefined");
}
} // 3. Let val be ? GetValue(val).
val = _singletons.Environment.GetValue(realm, val); // 4. Return a String according to Table 35.
let proto = val.getType().prototype;
if (isInstance(proto, _index2.UndefinedValue)) {
return new _index2.StringValue(realm, "undefined");
} else if (isInstance(proto, _index2.NullValue)) {
return new _index2.StringValue(realm, "object");
} else if (isInstance(proto, _index2.StringValue)) {
return new _index2.StringValue(realm, "string");
} else if (isInstance(proto, _index2.BooleanValue)) {
return new _index2.StringValue(realm, "boolean");
} else if (isInstance(proto, _index2.NumberValue)) {
return new _index2.StringValue(realm, "number");
} else if (isInstance(proto, _index2.SymbolValue)) {
return new _index2.StringValue(realm, "symbol");
} else if (isInstance(proto, _index2.ObjectValue)) {
if ((0, _index3.IsCallable)(realm, val)) {
return new _index2.StringValue(realm, "function");
}
return new _index2.StringValue(realm, "object");
} else {
(0, _invariant.default)(val instanceof _index2.AbstractValue);
return _index2.AbstractValue.createFromUnaryOp(realm, "typeof", val);
}
}
}
function _default(ast, strictCode, env, realm) {
let expr = env.evaluate(ast.argument, strictCode);
if (ast.operator === "delete") {
return evaluateDeleteOperation(expr, realm);
}
if (realm.isInPureScope()) {
return tryToEvaluateOperationOrLeaveAsAbstract(ast, expr, evaluateOperation, strictCode, realm);
} else {
return evaluateOperation(ast, expr, strictCode, realm);
}
}
//# sourceMappingURL=UnaryExpression.js.map