Forward deopt node path in NodePath#evaludate (#11832)
* Forward deopt node path * Move deopt evaluation tests * Document evaluate deopt property
This commit is contained in:
parent
bd07cda4a5
commit
b9407d7660
@ -219,7 +219,7 @@ function _evaluate(path, state) {
|
||||
if (elemValue.confident) {
|
||||
arr.push(elemValue.value);
|
||||
} else {
|
||||
return deopt(elem, state);
|
||||
return deopt(elemValue.deopt, state);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
@ -237,7 +237,7 @@ function _evaluate(path, state) {
|
||||
if (prop.node.computed) {
|
||||
key = key.evaluate();
|
||||
if (!key.confident) {
|
||||
return deopt(keyPath, state);
|
||||
return deopt(key.deopt, state);
|
||||
}
|
||||
key = key.value;
|
||||
} else if (key.isIdentifier()) {
|
||||
@ -248,7 +248,7 @@ function _evaluate(path, state) {
|
||||
const valuePath = prop.get("value");
|
||||
let value = valuePath.evaluate();
|
||||
if (!value.confident) {
|
||||
return deopt(valuePath, state);
|
||||
return deopt(value.deopt, state);
|
||||
}
|
||||
value = value.value;
|
||||
obj[key] = value;
|
||||
@ -407,19 +407,24 @@ function evaluateQuasis(path, quasis: Array<Object>, state, raw = false) {
|
||||
/**
|
||||
* Walk the input `node` and statically evaluate it.
|
||||
*
|
||||
* Returns an object in the form `{ confident, value }`. `confident` indicates
|
||||
* whether or not we had to drop out of evaluating the expression because of
|
||||
* hitting an unknown node that we couldn't confidently find the value of.
|
||||
* Returns an object in the form `{ confident, value, deopt }`. `confident`
|
||||
* indicates whether or not we had to drop out of evaluating the expression
|
||||
* because of hitting an unknown node that we couldn't confidently find the
|
||||
* value of, in which case `deopt` is the path of said node.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* t.evaluate(parse("5 + 5")) // { confident: true, value: 10 }
|
||||
* t.evaluate(parse("!true")) // { confident: true, value: false }
|
||||
* t.evaluate(parse("foo + foo")) // { confident: false, value: undefined }
|
||||
* t.evaluate(parse("foo + foo")) // { confident: false, value: undefined, deopt: NodePath }
|
||||
*
|
||||
*/
|
||||
|
||||
export function evaluate(): { confident: boolean, value: any } {
|
||||
export function evaluate(): {
|
||||
confident: boolean,
|
||||
value: any,
|
||||
deopt?: NodePath,
|
||||
} {
|
||||
const state = {
|
||||
confident: true,
|
||||
deoptPath: null,
|
||||
|
||||
@ -13,6 +13,25 @@ function getPath(code) {
|
||||
return path;
|
||||
}
|
||||
|
||||
function addDeoptTest(code, type, expectedType) {
|
||||
it(type + " deopt: " + code, function () {
|
||||
const visitor = {};
|
||||
|
||||
visitor[type] = function (path) {
|
||||
const evaluate = path.evaluate();
|
||||
expect(evaluate.confident).toBeFalsy();
|
||||
expect(evaluate.deopt.type).toEqual(expectedType);
|
||||
};
|
||||
|
||||
traverse(
|
||||
parse(code, {
|
||||
plugins: ["*"],
|
||||
}),
|
||||
visitor,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
describe("evaluation", function () {
|
||||
describe("evaluateTruthy", function () {
|
||||
it("it should work with null", function () {
|
||||
@ -228,4 +247,8 @@ describe("evaluation", function () {
|
||||
expect(result.deopt).toBeNull();
|
||||
expect(result.value).toEqual(["foo", "bar"]);
|
||||
});
|
||||
|
||||
addDeoptTest("({a:{b}})", "ObjectExpression", "Identifier");
|
||||
addDeoptTest("({[a + 'b']: 1})", "ObjectExpression", "Identifier");
|
||||
addDeoptTest("[{a}]", "ArrayExpression", "Identifier");
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user