Files
2023-08-01 13:49:46 +02:00

137 lines
6.4 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = function (ast, strictCode, env, realm) {
// evaluate left
var lref = env.evaluate(ast.left, strictCode);
var lval = _singletons.Environment.GetValue(realm, lref);
// evaluate right
var rref = env.evaluate(ast.right, strictCode);
var rval = _singletons.Environment.GetValue(realm, rref);
return computeBinary(realm, ast.operator, lval, rval, ast.left.loc, ast.right.loc, ast.loc);
};
exports.getPureBinaryOperationResultType = getPureBinaryOperationResultType;
exports.computeBinary = computeBinary;
var _index = require("../domains/index.js");
var _errors = require("../errors.js");
var _index2 = require("../values/index.js");
var _singletons = require("../singletons.js");
var _invariant = require("../invariant.js");
var _invariant2 = _interopRequireDefault(_invariant);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var unknownValueOfOrToString = "might be an object with an unknown valueOf or toString or Symbol.toPrimitive method";
// Returns result type if binary operation is pure (terminates, does not throw exception, does not read or write heap), otherwise undefined.
/**
* 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 getPureBinaryOperationResultType(realm, op, lval, rval, lloc, rloc) {
function reportErrorIfNotPure(purityTest, typeIfPure) {
var leftPure = purityTest(realm, lval);
var rightPure = purityTest(realm, rval);
if (leftPure && rightPure) return typeIfPure;
var loc = !leftPure ? lloc : rloc;
var error = new _errors.CompilerDiagnostic(unknownValueOfOrToString, loc, "PP0002", "RecoverableError");
if (realm.handleError(error) === "Recover") {
// Assume that an unknown value is actually a primitive or otherwise a well behaved object.
return typeIfPure;
}
throw new _errors.FatalError();
}
if (op === "+") {
var ltype = _singletons.To.GetToPrimitivePureResultType(realm, lval);
var rtype = _singletons.To.GetToPrimitivePureResultType(realm, rval);
if (ltype === undefined || rtype === undefined) {
var loc = ltype === undefined ? lloc : rloc;
var error = new _errors.CompilerDiagnostic(unknownValueOfOrToString, loc, "PP0002", "RecoverableError");
if (realm.handleError(error) === "Recover") {
// Assume that the unknown value is actually a primitive or otherwise a well behaved object.
ltype = lval.getType();
rtype = rval.getType();
if (ltype === _index2.StringValue || rtype === _index2.StringValue) return _index2.StringValue;
if (ltype === _index2.NumberValue && rtype === _index2.NumberValue) return _index2.NumberValue;
return _index2.Value;
}
throw new _errors.FatalError();
}
if (ltype === _index2.StringValue || rtype === _index2.StringValue) return _index2.StringValue;
return _index2.NumberValue;
} else if (op === "<" || op === ">" || op === ">=" || op === "<=") {
return reportErrorIfNotPure(_singletons.To.IsToPrimitivePure.bind(_singletons.To), _index2.BooleanValue);
} else if (op === "!=" || op === "==") {
var _ltype = lval.getType();
var _rtype = rval.getType();
if (_ltype === _index2.NullValue || _ltype === _index2.UndefinedValue || _rtype === _index2.NullValue || _rtype === _index2.UndefinedValue) return _index2.BooleanValue;
return reportErrorIfNotPure(_singletons.To.IsToPrimitivePure.bind(_singletons.To), _index2.BooleanValue);
} else if (op === "===" || op === "!==") {
return _index2.BooleanValue;
} else if (op === ">>>" || op === "<<" || op === ">>" || op === "&" || op === "|" || op === "^" || op === "**" || op === "%" || op === "/" || op === "*" || op === "-") {
return reportErrorIfNotPure(_singletons.To.IsToNumberPure.bind(_singletons.To), _index2.NumberValue);
} else if (op === "in" || op === "instanceof") {
if (rval.mightNotBeObject()) {
var _error2 = new _errors.CompilerDiagnostic("might not be an object, hence the " + op + " operator might throw a TypeError", rloc, "PP0003", "RecoverableError");
if (realm.handleError(_error2) === "Recover") {
// Assume that the object is actually a well behaved object.
return _index2.BooleanValue;
}
throw new _errors.FatalError();
}
if (!rval.mightNotBeObject()) {
// Simple object won't throw here, aren't proxy objects or typed arrays and do not have @@hasInstance properties.
if (rval.isSimpleObject()) return _index2.BooleanValue;
}
var _error = new _errors.CompilerDiagnostic("might be an object that behaves badly for the " + op + " operator", rloc, "PP0004", "RecoverableError");
if (realm.handleError(_error) === "Recover") {
// Assume that the object is actually a well behaved object.
return _index2.BooleanValue;
}
throw new _errors.FatalError();
}
(0, _invariant2.default)(false, "unimplemented " + op);
}
function computeBinary(realm, op, lval, rval, lloc, rloc, loc) {
// partial evaluation shortcut for a particular pattern
if (realm.useAbstractInterpretation && (op === "==" || op === "===" || op === "!=" || op === "!==")) {
if (!lval.mightNotBeObject() && (rval instanceof _index2.NullValue || rval instanceof _index2.UndefinedValue) || (lval instanceof _index2.NullValue || lval instanceof _index2.UndefinedValue) && !rval.mightNotBeObject()) {
return new _index2.BooleanValue(realm, op[0] !== "=");
}
}
if (lval instanceof _index2.AbstractValue || rval instanceof _index2.AbstractValue) {
// generate error if binary operation might throw or have side effects
getPureBinaryOperationResultType(realm, op, lval, rval, lloc, rloc);
return _index2.AbstractValue.createFromBinaryOp(realm, op, lval, rval, loc);
}
// ECMA262 12.10.3
// 5. If Type(rval) is not Object, throw a TypeError exception.
if (op === "in" && !(rval instanceof _index2.ObjectValue)) {
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
}
(0, _invariant2.default)(lval instanceof _index2.ConcreteValue);
(0, _invariant2.default)(rval instanceof _index2.ConcreteValue);
return _index.ValuesDomain.computeBinary(realm, op, lval, rval);
}
//# sourceMappingURL=BinaryExpression.js.map