"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PathImplementation = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** * 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. */ var _index = require("../values/index.js"); var _invariant = require("../invariant.js"); var _invariant2 = _interopRequireDefault(_invariant); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var PathImplementation = exports.PathImplementation = function () { function PathImplementation() { _classCallCheck(this, PathImplementation); } _createClass(PathImplementation, [{ key: "implies", value: function implies(condition) { if (!condition.mightNotBeTrue()) return true; // any path implies true var path = condition.$Realm.pathConditions; for (var i = path.length - 1; i >= 0; i--) { var pathCondition = path[i]; if (pathCondition.implies(condition)) return true; } return false; } }, { key: "impliesNot", value: function impliesNot(condition) { if (!condition.mightNotBeFalse()) return true; // any path implies !false var path = condition.$Realm.pathConditions; for (var i = path.length - 1; i >= 0; i--) { var pathCondition = path[i]; if (pathCondition.impliesNot(condition)) return true; } return false; } }, { key: "withCondition", value: function withCondition(condition, evaluate) { var realm = condition.$Realm; var savedPath = realm.pathConditions; realm.pathConditions = []; try { pushPathCondition(condition); pushRefinedConditions(savedPath); return evaluate(); } finally { realm.pathConditions = savedPath; } } }, { key: "withInverseCondition", value: function withInverseCondition(condition, evaluate) { var realm = condition.$Realm; var savedPath = realm.pathConditions; realm.pathConditions = []; try { pushInversePathCondition(condition); pushRefinedConditions(savedPath); return evaluate(); } finally { realm.pathConditions = savedPath; } } }, { key: "pushAndRefine", value: function pushAndRefine(condition) { var realm = condition.$Realm; var savedPath = realm.pathConditions; realm.pathConditions = []; pushPathCondition(condition); pushRefinedConditions(savedPath); } }, { key: "pushInverseAndRefine", value: function pushInverseAndRefine(condition) { var realm = condition.$Realm; var savedPath = realm.pathConditions; realm.pathConditions = []; pushInversePathCondition(condition); pushRefinedConditions(savedPath); } }]); return PathImplementation; }(); // A path condition is an abstract value that is known to be true in a particular code path function pushPathCondition(condition) { (0, _invariant2.default)(condition.mightNotBeFalse(), "pushing false"); // it is mistake to assert that false is true if (condition instanceof _index.ConcreteValue) return; if (!condition.mightNotBeTrue()) return; (0, _invariant2.default)(condition instanceof _index.AbstractValue); var realm = condition.$Realm; if (condition.kind === "&&") { var left = condition.args[0]; var right = condition.args[1]; (0, _invariant2.default)(left instanceof _index.AbstractValue); // it is a mistake to create an abstract value when concrete value will do pushPathCondition(left); pushPathCondition(right); } else { if (condition.kind === "!=" || condition.kind === "==") { var _left = condition.args[0]; var _right = condition.args[1]; if (_left instanceof _index.ConcreteValue && _right instanceof _index.AbstractValue) { ; var _ref = [_right, _left]; _left = _ref[0]; _right = _ref[1]; }if (_left instanceof _index.AbstractValue && (_right instanceof _index.UndefinedValue || _right instanceof _index.NullValue)) { var op = condition.kind === "!=" ? "!==" : "==="; if (op === "!==") pushPathCondition(_left);else pushInversePathCondition(_left); var leftNeNull = _index.AbstractValue.createFromBinaryOp(realm, op, _left, realm.intrinsics.null); if (leftNeNull.mightNotBeFalse()) pushPathCondition(leftNeNull); var leftNeUndefined = _index.AbstractValue.createFromBinaryOp(realm, op, _left, realm.intrinsics.undefined); if (leftNeUndefined.mightNotBeFalse()) pushPathCondition(leftNeUndefined); return; } } realm.pathConditions.push(condition); } } // An inverse path condition is an abstract value that is known to be false in a particular code path function pushInversePathCondition(condition) { // it is mistake to assert that true is false. (0, _invariant2.default)(condition.mightNotBeTrue()); if (condition instanceof _index.ConcreteValue) return; (0, _invariant2.default)(condition instanceof _index.AbstractValue); if (condition.kind === "||") { var left = condition.args[0]; var right = condition.args[1]; (0, _invariant2.default)(left instanceof _index.AbstractValue); // it is a mistake to create an abstract value when concrete value will do pushInversePathCondition(left); if (right.mightNotBeTrue()) pushInversePathCondition(right); } else { var realm = condition.$Realm; if (condition.kind === "!=" || condition.kind === "==") { var _left2 = condition.args[0]; var _right2 = condition.args[1]; if (_left2 instanceof _index.ConcreteValue && _right2 instanceof _index.AbstractValue) { ; var _ref2 = [_right2, _left2]; _left2 = _ref2[0]; _right2 = _ref2[1]; }if (_left2 instanceof _index.AbstractValue && (_right2 instanceof _index.UndefinedValue || _right2 instanceof _index.NullValue)) { var op = condition.kind === "!=" ? "===" : "!=="; if (op === "!==") pushInversePathCondition(_left2);else pushPathCondition(_left2); var leftEqNull = _index.AbstractValue.createFromBinaryOp(realm, op, _left2, realm.intrinsics.null); if (leftEqNull.mightNotBeFalse()) pushPathCondition(leftEqNull); var leftEqUndefined = _index.AbstractValue.createFromBinaryOp(realm, op, _left2, realm.intrinsics.undefined); if (leftEqUndefined.mightNotBeFalse()) pushPathCondition(leftEqUndefined); return; } } var inverseCondition = _index.AbstractValue.createFromUnaryOp(realm, "!", condition); pushPathCondition(inverseCondition); if (inverseCondition instanceof _index.AbstractValue) { var simplifiedInverseCondition = realm.simplifyAndRefineAbstractCondition(inverseCondition); if (!simplifiedInverseCondition.equals(inverseCondition)) pushPathCondition(simplifiedInverseCondition); } } } function pushRefinedConditions(unrefinedConditions) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = unrefinedConditions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var unrefinedCond = _step.value; pushPathCondition(unrefinedCond.$Realm.simplifyAndRefineAbstractCondition(unrefinedCond)); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } //# sourceMappingURL=paths.js.map