deopt on recursion in path.evaluate - fixes T7397

This commit is contained in:
Sebastian McKenzie 2016-06-19 22:08:39 +01:00
parent 5a8a2512d0
commit b2390cca02
2 changed files with 37 additions and 0 deletions

View File

@ -51,6 +51,7 @@ export function evaluateTruthy(): boolean {
export function evaluate(): { confident: boolean; value: any } {
let confident = true;
let deoptPath: ?NodePath;
let seen = new Map;
function deopt(path) {
if (!confident) return;
@ -66,7 +67,36 @@ export function evaluate(): { confident: boolean; value: any } {
value: value
};
// we wrap the _evaluate method so we can track `seen` nodes, we push an item
// to the map before we actually evaluate it so we can deopt on self recursive
// nodes such as:
//
// var g = a ? 1 : 2,
// a = g * this.foo
//
function evaluate(path) {
let { node } = path;
if (seen.has(node)) {
let existing = seen.get(node);
if (existing.resolved) {
return existing.value;
} else {
deopt(path);
return;
}
} else {
let item = { resolved: false };
seen.set(node, item);
let val = _evaluate(path);
item.resolved = true;
item.value = value;
return val;
}
}
function _evaluate(path) {
if (!confident) return;
let { node } = path;

View File

@ -30,4 +30,11 @@ suite("evaluation", function () {
);
});
});
test("should bail out on recursive evaluation", function () {
assert.strictEqual(
getPath("function fn(a) { var g = a ? 1 : 2, a = g * this.foo; }").get("body.0.body.body.0.declarations.1.init").evaluate().confident,
false
);
});
});