deopt on recursion in path.evaluate - fixes T7397
This commit is contained in:
parent
5a8a2512d0
commit
b2390cca02
@ -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;
|
||||
|
||||
@ -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
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user