From d2e1f002faaac247fb9e5220703e7a770b43ef18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 5 May 2022 10:41:21 -0400 Subject: [PATCH 1/5] improve react-jsx-self typings (#14529) --- .../src/index.ts | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/babel-plugin-transform-react-jsx-self/src/index.ts b/packages/babel-plugin-transform-react-jsx-self/src/index.ts index 70c6baabb0b7..52992f2bc5d0 100644 --- a/packages/babel-plugin-transform-react-jsx-self/src/index.ts +++ b/packages/babel-plugin-transform-react-jsx-self/src/index.ts @@ -14,6 +14,7 @@ */ import { declare } from "@babel/helper-plugin-utils"; import { types as t } from "@babel/core"; +import type { Visitor, NodePath } from "@babel/traverse"; const TRACE_ID = "__self"; @@ -23,14 +24,15 @@ const TRACE_ID = "__self"; * * Derived from `Scope#getFunctionParent` */ -function getThisFunctionParent(path) { +function getThisFunctionParent( + path: NodePath, +): NodePath> | null { let scope = path.scope; do { - if ( - scope.path.isFunctionParent() && - !scope.path.isArrowFunctionExpression() - ) { - return scope.path; + const { path } = scope; + if (path.isFunctionParent() && !path.isArrowFunctionExpression()) { + // @ts-expect-error TS does not exlucde ArrowFunctionExpression from FunctionParent + return path; } } while ((scope = scope.parent)); return null; @@ -39,14 +41,14 @@ function getThisFunctionParent(path) { /** * Returns whether the class has specified a superclass. */ -function isDerivedClass(classPath) { +function isDerivedClass(classPath: NodePath) { return classPath.node.superClass !== null; } /** * Returns whether `this` is allowed at given path. */ -function isThisAllowed(path) { +function isThisAllowed(path: NodePath) { // This specifically skips arrow functions as they do not rewrite `this`. const parentMethodOrFunction = getThisFunctionParent(path); if (parentMethodOrFunction === null) { @@ -63,13 +65,15 @@ function isThisAllowed(path) { return true; } // Now we are in a constructor. If it is a derived class, we do not reference `this`. - return !isDerivedClass(parentMethodOrFunction.parentPath.parentPath); + return !isDerivedClass( + parentMethodOrFunction.parentPath.parentPath as NodePath, + ); } export default declare(api => { api.assertVersion(7); - const visitor = { + const visitor: Visitor = { JSXOpeningElement(path) { if (!isThisAllowed(path)) { return; From fbd065256ca00d68089293ad48ea9aeba5481914 Mon Sep 17 00:00:00 2001 From: Babel Bot Date: Fri, 6 May 2022 14:24:21 +0200 Subject: [PATCH 2/5] chore: update test262 to 2e7cdfbe18eae4309677033673bb4b5ac6b1de40 (#14531) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0e192ecbac7c..f7aa350854ca 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ FLOW_COMMIT = 92bbb5e9dacb8185aa73ea343954d0434b42c40b -TEST262_COMMIT = dcd25e616d1023922c3afb3fe13c792ed134f8f4 +TEST262_COMMIT = 2e7cdfbe18eae4309677033673bb4b5ac6b1de40 TYPESCRIPT_COMMIT = b53073bf66571b4c99f0a93b8f76fb06b36d8991 # Fix color output until TravisCI fixes https://github.com/travis-ci/travis-ci/issues/7967 From 0984a2a0193d2a41f9f2dec318ba80267daee5c8 Mon Sep 17 00:00:00 2001 From: Xia Wenqi Date: Fri, 6 May 2022 20:57:14 +0800 Subject: [PATCH 3/5] Print necessary parentheses for functions in postfix expressions (#14532) fix: isFirstInContext doesn't handle postfix unary operators Co-authored-by: xiawenqi --- packages/babel-generator/src/node/parentheses.ts | 2 ++ .../test/fixtures/parentheses/unary-postfix/input.js | 1 + .../test/fixtures/parentheses/unary-postfix/output.js | 5 +++++ 3 files changed, 8 insertions(+) create mode 100644 packages/babel-generator/test/fixtures/parentheses/unary-postfix/input.js create mode 100644 packages/babel-generator/test/fixtures/parentheses/unary-postfix/output.js diff --git a/packages/babel-generator/src/node/parentheses.ts b/packages/babel-generator/src/node/parentheses.ts index bb651b6d2287..460767d0b638 100644 --- a/packages/babel-generator/src/node/parentheses.ts +++ b/packages/babel-generator/src/node/parentheses.ts @@ -5,6 +5,7 @@ import { isAwaitExpression, isBinary, isBinaryExpression, + isUpdateExpression, isCallExpression, isClassDeclaration, isClassExpression, @@ -414,6 +415,7 @@ function isFirstInContext( if ( (hasPostfixPart(node, parent) && !isNewExpression(parent)) || (isSequenceExpression(parent) && parent.expressions[0] === node) || + (isUpdateExpression(parent) && !parent.prefix) || isConditional(parent, { test: node }) || isBinary(parent, { left: node }) || isAssignmentExpression(parent, { left: node }) diff --git a/packages/babel-generator/test/fixtures/parentheses/unary-postfix/input.js b/packages/babel-generator/test/fixtures/parentheses/unary-postfix/input.js new file mode 100644 index 000000000000..1603497b5d89 --- /dev/null +++ b/packages/babel-generator/test/fixtures/parentheses/unary-postfix/input.js @@ -0,0 +1 @@ +(function () { return {x: 24} }()).x++; diff --git a/packages/babel-generator/test/fixtures/parentheses/unary-postfix/output.js b/packages/babel-generator/test/fixtures/parentheses/unary-postfix/output.js new file mode 100644 index 000000000000..f07a72eed6f8 --- /dev/null +++ b/packages/babel-generator/test/fixtures/parentheses/unary-postfix/output.js @@ -0,0 +1,5 @@ +(function () { + return { + x: 24 + }; +})().x++; \ No newline at end of file From 9c1774a63f080fbf9f0a60d6674e8f220d2d7d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Fri, 6 May 2022 10:18:45 -0400 Subject: [PATCH 4/5] fix: perserve parentheses of lhs id with rhs unamed fn (#14524) * fix: perserve () of lhs id with rhs unamed fn * review comments --- packages/babel-generator/src/node/parentheses.ts | 11 +++++++++++ .../fixtures/parentheses/identifier-lhs/input.js | 7 +++++++ .../fixtures/parentheses/identifier-lhs/output.js | 13 +++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 packages/babel-generator/test/fixtures/parentheses/identifier-lhs/input.js create mode 100644 packages/babel-generator/test/fixtures/parentheses/identifier-lhs/output.js diff --git a/packages/babel-generator/src/node/parentheses.ts b/packages/babel-generator/src/node/parentheses.ts index 460767d0b638..d1cf322ea269 100644 --- a/packages/babel-generator/src/node/parentheses.ts +++ b/packages/babel-generator/src/node/parentheses.ts @@ -18,6 +18,7 @@ import { isForInStatement, isForOfStatement, isForStatement, + isFunctionExpression, isIfStatement, isIndexedAccessType, isIntersectionTypeAnnotation, @@ -345,6 +346,16 @@ export function Identifier( parent: t.Node, printStack: Array, ): boolean { + // 13.15.2 AssignmentExpression RS: Evaluation + // (fn) = function () {}; + if ( + node.extra?.parenthesized && + isAssignmentExpression(parent, { left: node }) && + (isFunctionExpression(parent.right) || isClassExpression(parent.right)) && + parent.right.id == null + ) { + return true; + } // Non-strict code allows the identifier `let`, but it cannot occur as-is in // certain contexts to avoid ambiguity with contextual keyword `let`. if (node.name === "let") { diff --git a/packages/babel-generator/test/fixtures/parentheses/identifier-lhs/input.js b/packages/babel-generator/test/fixtures/parentheses/identifier-lhs/input.js new file mode 100644 index 000000000000..b1c118d215b6 --- /dev/null +++ b/packages/babel-generator/test/fixtures/parentheses/identifier-lhs/input.js @@ -0,0 +1,7 @@ +var f, g, h; +(f) = function () {}; +(f) = class {}; +g = function () {}; +g = class {}; +(h) = function noParen() {}; +(h) = class noParen {} diff --git a/packages/babel-generator/test/fixtures/parentheses/identifier-lhs/output.js b/packages/babel-generator/test/fixtures/parentheses/identifier-lhs/output.js new file mode 100644 index 000000000000..164de06f999a --- /dev/null +++ b/packages/babel-generator/test/fixtures/parentheses/identifier-lhs/output.js @@ -0,0 +1,13 @@ +var f, g, h; + +(f) = function () {}; + +(f) = class {}; + +g = function () {}; + +g = class {}; + +h = function noParen() {}; + +h = class noParen {}; \ No newline at end of file From 871ed897a711a92c9470c481c23fa00bd75f18c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 9 May 2022 15:43:12 +0200 Subject: [PATCH 5/5] Never hoist JSX elts referencing vars from the current scope (#14536) --- .../src/index.ts | 16 ++++++++++++++-- .../constant-elements/regression-14363/input.js | 12 ++++++++++++ .../constant-elements/regression-14363/output.js | 10 ++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/input.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/output.js diff --git a/packages/babel-plugin-transform-react-constant-elements/src/index.ts b/packages/babel-plugin-transform-react-constant-elements/src/index.ts index c025319f26e1..c759d49e6533 100644 --- a/packages/babel-plugin-transform-react-constant-elements/src/index.ts +++ b/packages/babel-plugin-transform-react-constant-elements/src/index.ts @@ -197,7 +197,7 @@ export default declare((api, options: Options) => { current = current.parentPath; jsxScope = HOISTED.get(current.node); } - jsxScope ??= getHoistingScope(path.scope); + jsxScope ??= path.scope; const visitorState: VisitorState = { isImmutable: true, @@ -212,7 +212,19 @@ export default declare((api, options: Options) => { HOISTED.set(path.node, targetScope); // Only hoist if it would give us an advantage. - if (targetScope === jsxScope) return; + for (let currentScope = jsxScope; ; ) { + if (targetScope === currentScope) return; + if (isHoistingScope(currentScope)) break; + + currentScope = currentScope.parent; + if (!currentScope) { + throw new Error( + "Internal @babel/plugin-transform-react-constant-elements error: " + + "targetScope must be an ancestor of jsxScope. " + + "This is a Babel bug, please report it.", + ); + } + } const id = path.scope.generateUidBasedOnNode(name); targetScope.push({ id: t.identifier(id) }); diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/input.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/input.js new file mode 100644 index 000000000000..a8f784c7f912 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/input.js @@ -0,0 +1,12 @@ +function RoutesComponent() { + return ( + + {(c) => { + { + const Component = c; + return ; + } + }} + + ); +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/output.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/output.js new file mode 100644 index 000000000000..1967a7fe7268 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/output.js @@ -0,0 +1,10 @@ +function RoutesComponent() { + return + {c => { + { + const Component = c; + return ; + } + }} + ; +}