From f9212742fed5f1ab8bb2236cd108ebde5520a4fa Mon Sep 17 00:00:00 2001 From: Johan Holmerin Date: Mon, 13 Jul 2020 19:46:08 +0200 Subject: [PATCH 1/3] Forward deopt node path --- packages/babel-core/test/evaluation.js | 23 +++++++++++++++++++ .../babel-traverse/src/path/evaluation.js | 6 ++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/babel-core/test/evaluation.js b/packages/babel-core/test/evaluation.js index ffe9b5a3a2de..360c49a451bd 100644 --- a/packages/babel-core/test/evaluation.js +++ b/packages/babel-core/test/evaluation.js @@ -21,6 +21,25 @@ describe("evaluation", function () { }); } + 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, + ); + }); + } + addTest("void 0", "UnaryExpression", undefined); addTest("!true", "UnaryExpression", false); addTest("+'2'", "UnaryExpression", 2); @@ -93,4 +112,8 @@ describe("evaluation", function () { ab: 200, z: [1, 2, 3], }); + + addDeoptTest("({a:{b}})", "ObjectExpression", "Identifier"); + addDeoptTest("({[a + 'b']: 1})", "ObjectExpression", "Identifier"); + addDeoptTest("[{a}]", "ArrayExpression", "Identifier"); }); diff --git a/packages/babel-traverse/src/path/evaluation.js b/packages/babel-traverse/src/path/evaluation.js index 01d00fb78890..08979bd2a1d3 100644 --- a/packages/babel-traverse/src/path/evaluation.js +++ b/packages/babel-traverse/src/path/evaluation.js @@ -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; From cf7cb157499eee71d2fb7377c9831f5d454e9a0b Mon Sep 17 00:00:00 2001 From: Johan Holmerin Date: Wed, 15 Jul 2020 19:17:35 +0200 Subject: [PATCH 2/3] Move deopt evaluation tests --- packages/babel-core/test/evaluation.js | 23 ---------------------- packages/babel-traverse/test/evaluation.js | 23 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/babel-core/test/evaluation.js b/packages/babel-core/test/evaluation.js index 360c49a451bd..ffe9b5a3a2de 100644 --- a/packages/babel-core/test/evaluation.js +++ b/packages/babel-core/test/evaluation.js @@ -21,25 +21,6 @@ describe("evaluation", function () { }); } - 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, - ); - }); - } - addTest("void 0", "UnaryExpression", undefined); addTest("!true", "UnaryExpression", false); addTest("+'2'", "UnaryExpression", 2); @@ -112,8 +93,4 @@ describe("evaluation", function () { ab: 200, z: [1, 2, 3], }); - - addDeoptTest("({a:{b}})", "ObjectExpression", "Identifier"); - addDeoptTest("({[a + 'b']: 1})", "ObjectExpression", "Identifier"); - addDeoptTest("[{a}]", "ArrayExpression", "Identifier"); }); diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index f988bb1184cd..d90ab87ff0d3 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -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"); }); From c3065e8a16a82363bdc32f579e25f33938a17cce Mon Sep 17 00:00:00 2001 From: Johan Holmerin Date: Wed, 15 Jul 2020 19:37:23 +0200 Subject: [PATCH 3/3] Document evaluate deopt property --- packages/babel-traverse/src/path/evaluation.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.js b/packages/babel-traverse/src/path/evaluation.js index 08979bd2a1d3..ca6d6dc50d82 100644 --- a/packages/babel-traverse/src/path/evaluation.js +++ b/packages/babel-traverse/src/path/evaluation.js @@ -407,19 +407,24 @@ function evaluateQuasis(path, quasis: Array, 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,