From c8146432c14986f30fac42fbe019bf0b4d642ff5 Mon Sep 17 00:00:00 2001 From: Jonathan Browne <12983479+JBYoshi@users.noreply.github.com> Date: Mon, 2 Jan 2023 08:09:24 -0600 Subject: [PATCH] Implement support for evaluating computed properties. (#15313) --- .../babel-traverse/src/path/evaluation.ts | 20 +++++++++++++++---- packages/babel-traverse/test/evaluation.js | 10 ++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 6c7c16163c21..6b35af8e6903 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 (path.node.computed) { + key = evaluateCached(property, state); + if (!state.confident) return; + } else if (property.isIdentifier()) { + key = property.node.name; + } + 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..07897748e71c 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -114,6 +114,16 @@ 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"); + expect( + getPath("var length = 1; var x = 'abc'[length];") + .get("body.1.declarations.0.init") + .evaluate().value, + ).toBe("b"); const member_expr = getPath( "var x = Math.min(2,Math.max(3,4));var y = Math.random();", );