prepack
Version:
Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.
179 lines (139 loc) • 5.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _invariant = _interopRequireDefault(require("../invariant.js"));
var _index = require("../values/index.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 */
/* An abstract domain for the type of value a variable might have. */
class TypesDomain {
constructor(type) {
(0, _invariant.default)(type !== _index.ConcreteValue, "Concrete values must be specific");
this._type = type === _index.Value ? undefined : type;
}
isBottom() {
return this._type instanceof _index.EmptyValue;
}
isTop() {
return this._type === undefined;
}
getType() {
return this._type || _index.Value;
} // return the type of the result in the case where there is no exception
static binaryOp(op, left, right) {
if (left.isBottom() || right.isBottom()) return TypesDomain.bottomVal;
let lType = left._type;
let rType = right._type;
let resultType = _index.Value;
switch (op) {
case "+":
if (lType === undefined || rType === undefined) return TypesDomain.topVal;
if (_index.Value.isTypeCompatibleWith(lType, _index.StringValue) || _index.Value.isTypeCompatibleWith(rType, _index.StringValue)) {
resultType = _index.StringValue;
break;
}
// eslint-disable-line no-fallthrough
case "-":
if (lType === undefined || rType === undefined) return TypesDomain.topVal;
if (lType === _index.IntegralValue && rType === _index.IntegralValue) resultType = _index.IntegralValue;else if (_index.Value.isTypeCompatibleWith(lType, _index.NumberValue) && _index.Value.isTypeCompatibleWith(rType, _index.NumberValue)) resultType = _index.NumberValue;
break;
case "<":
case ">":
case ">=":
case "<=":
case "!=":
case "==":
case "!==":
case "===":
case "in":
case "instanceof":
resultType = _index.BooleanValue;
break;
case ">>>":
case "<<":
case ">>":
case "&":
case "|":
case "^":
resultType = _index.IntegralValue;
break;
case "**":
case "%":
case "/":
case "*":
resultType = _index.NumberValue;
break;
default:
(0, _invariant.default)(false);
}
return new TypesDomain(resultType);
}
static joinValues(v1, v2) {
if (v1 === undefined && v2 === undefined) return new TypesDomain(_index.UndefinedValue);
if (v1 === undefined || v2 === undefined) return TypesDomain.topVal;
if (v1 instanceof _index.AbstractValue) return v1.types.joinWith(v2.getType());
if (v2 instanceof _index.AbstractValue) return v2.types.joinWith(v1.getType());
return new TypesDomain(v1.getType()).joinWith(v2.getType());
}
joinWith(t) {
if (this.isBottom()) return t === _index.EmptyValue ? TypesDomain.bottomVal : new TypesDomain(t);
let type = this.getType();
if (type === t || t instanceof _index.EmptyValue) return this;
if (_index.Value.isTypeCompatibleWith(type, _index.NumberValue) && _index.Value.isTypeCompatibleWith(t, _index.NumberValue)) {
return new TypesDomain(_index.NumberValue);
}
if (_index.Value.isTypeCompatibleWith(type, _index.FunctionValue) && _index.Value.isTypeCompatibleWith(t, _index.FunctionValue)) {
return new TypesDomain(_index.FunctionValue);
}
if (_index.Value.isTypeCompatibleWith(type, _index.ObjectValue) && _index.Value.isTypeCompatibleWith(t, _index.ObjectValue)) {
return new TypesDomain(_index.ObjectValue);
}
if (_index.Value.isTypeCompatibleWith(type, _index.PrimitiveValue) && _index.Value.isTypeCompatibleWith(t, _index.PrimitiveValue)) {
return new TypesDomain(_index.PrimitiveValue);
}
return TypesDomain.topVal;
}
static logicalOp(op, left, right) {
return left.joinWith(right.getType());
} // return the type of the result in the case where there is no exception
// note that the type of the operand has no influence on the type of the non exceptional result
static unaryOp(op, operand) {
if (operand.isBottom()) return TypesDomain.bottomVal;
const type = operand._type;
let resultType = _index.Value;
switch (op) {
case "-":
case "+":
resultType = type === _index.IntegralValue ? _index.IntegralValue : _index.NumberValue;
break;
case "~":
resultType = _index.IntegralValue;
break;
case "!":
case "delete":
resultType = _index.BooleanValue;
break;
case "typeof":
resultType = _index.StringValue;
break;
case "void":
resultType = _index.UndefinedValue;
break;
default:
(0, _invariant.default)(false);
}
return new TypesDomain(resultType);
}
}
exports.default = TypesDomain;
//# sourceMappingURL=TypesDomain.js.map