"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