From 79a729abf1e50147d16b2d96738b29d677394f8d Mon Sep 17 00:00:00 2001 From: JBYoshi <12983479+JBYoshi@users.noreply.github.com> Date: Mon, 26 Dec 2022 19:49:08 -0600 Subject: [PATCH] Implement support for evaluating computed properties. This allows expressions like "hello world"[6] to be evaluated. --- .../babel-traverse/src/path/evaluation.ts | 20 +++++++++++++++---- packages/babel-traverse/test/evaluation.js | 5 +++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 6c7c16163c21..87e93655034b 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -158,7 +158,7 @@ function _evaluate(path: NodePath, state: State): any { return evaluateCached(path.get("expression"), state); } - // "foo".length + // "foo".length, "foo"[0] if ( path.isMemberExpression() && !path.parentPath.isCallExpression({ callee: path.node }) @@ -166,12 +166,24 @@ function _evaluate(path: NodePath, state: State): any { const property = path.get("property"); const object = path.get("object"); - if (object.isLiteral() && property.isIdentifier()) { + if (object.isLiteral()) { // @ts-expect-error todo(flow->ts): instead of typeof - would it be better to check type of ast node? const value = object.node.value; const type = typeof value; - if (type === "number" || type === "string") { - return value[property.node.name]; + + let key = null; + if (property.isIdentifier()) { + key = property.node.name; + } else if (path.node.computed) { + key = evaluateCached(property, state); + if (!state.confident) return; + } + if ( + (type === "number" || type === "string") && + key != null && + (typeof key === "number" || typeof key === "string") + ) { + return value[key]; } } } diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index 29a8372f7f69..bd21be347521 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -114,6 +114,11 @@ describe("evaluation", function () { .get("body.0.declarations.0.init") .evaluate().value, ).toBe(3); + expect( + getPath("var x = 'hello world'[6]") + .get("body.0.declarations.0.init") + .evaluate().value, + ).toBe("w"); const member_expr = getPath( "var x = Math.min(2,Math.max(3,4));var y = Math.random();", );