From fad47596a64a8d33aadacb7695dbf1aa60a528ae Mon Sep 17 00:00:00 2001 From: Mickey Rose Date: Thu, 5 Aug 2021 12:01:45 +0200 Subject: [PATCH] overload `skipTransparentExprWrappers` * fixes isSimpleMemberExpression in @babel/plugin-proposal-optional-chaining * use skipTransparentExprWrappers instead of the NodePath overload where possible in @babel/plugin-proposal-optional-chaining --- .../src/index.ts | 26 ++++++++++++++----- .../src/transform.js | 15 +++-------- .../ts-as-function-call-loose/output.js | 4 +-- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/packages/babel-helper-skip-transparent-expression-wrappers/src/index.ts b/packages/babel-helper-skip-transparent-expression-wrappers/src/index.ts index edc336543dda..80c6e358cf1e 100644 --- a/packages/babel-helper-skip-transparent-expression-wrappers/src/index.ts +++ b/packages/babel-helper-skip-transparent-expression-wrappers/src/index.ts @@ -1,3 +1,4 @@ +import { NodePath } from "@babel/traverse"; import { isParenthesizedExpression, isTSAsExpression, @@ -7,7 +8,6 @@ import { } from "@babel/types"; import type * as t from "@babel/types"; -import type { NodePath } from "@babel/traverse"; export type TransparentExprWrapper = | t.TSAsExpression @@ -33,11 +33,25 @@ export function isTransparentExprWrapper( ); } +type ExprNodeOrPath = t.Expression | NodePath; + +export function skipTransparentExprWrappers(expr: t.Expression): t.Expression; + +export function skipTransparentExprWrappers( + expr: NodePath, +): NodePath; + export function skipTransparentExprWrappers( - path: NodePath, -): NodePath { - while (isTransparentExprWrapper(path.node)) { - path = path.get("expression"); + expr: ExprNodeOrPath, +): ExprNodeOrPath { + if (expr instanceof NodePath) { + while (isTransparentExprWrapper(expr.node)) { + expr = expr.get("expression"); + } + } else { + while (isTransparentExprWrapper(expr)) { + expr = expr.expression; + } } - return path; + return expr; } diff --git a/packages/babel-plugin-proposal-optional-chaining/src/transform.js b/packages/babel-plugin-proposal-optional-chaining/src/transform.js index 656b4ea09e6c..9bdbbf87f09d 100644 --- a/packages/babel-plugin-proposal-optional-chaining/src/transform.js +++ b/packages/babel-plugin-proposal-optional-chaining/src/transform.js @@ -1,8 +1,5 @@ import { types as t, template } from "@babel/core"; -import { - isTransparentExprWrapper, - skipTransparentExprWrappers, -} from "@babel/helper-skip-transparent-expression-wrappers"; +import { skipTransparentExprWrappers } from "@babel/helper-skip-transparent-expression-wrappers"; import { willPathCastToBoolean, findOutermostTransparentParent } from "./util"; const { ast } = template.expression; @@ -103,11 +100,7 @@ export function transform( const replaceKey = isCall ? "callee" : "object"; const chainWithTypes = node[replaceKey]; - let chain = chainWithTypes; - - while (isTransparentExprWrapper(chain)) { - chain = chain.expression; - } + const chain = skipTransparentExprWrappers(chainWithTypes); let ref; let check; @@ -169,9 +162,7 @@ export function transform( // i.e. `?.b` in `(a?.b.c)()` if (i === 0 && parentIsCall) { // `(a?.b)()` to `(a == null ? undefined : a.b.bind(a))()` - const object = skipTransparentExprWrappers( - replacementPath.get("object"), - ).node; + const object = skipTransparentExprWrappers(replacement.object); let baseRef; if (!pureGetters || !isSimpleMemberExpression(object)) { // memoize the context object when getters are not always pure diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js index 93a8b5c45d88..6638d5a0908e 100644 --- a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js @@ -1,3 +1 @@ -var _bar, _ref; - -(_bar = ((_ref = (foo as A)).bar as B)) == null ? void 0 : _bar.call(_ref, foo.bar, false); +((foo as A).bar as B) == null ? void 0 : ((foo as A).bar as B)(foo.bar, false);