diff --git a/packages/babel-plugin-transform-parameters/src/params.ts b/packages/babel-plugin-transform-parameters/src/params.ts index 0eb544cbcef6..b93351baf100 100644 --- a/packages/babel-plugin-transform-parameters/src/params.ts +++ b/packages/babel-plugin-transform-parameters/src/params.ts @@ -47,11 +47,6 @@ export default function convertFunctionParams( const { node, scope } = path; - const state = { - needsOuterBinding: false, - scope, - }; - const body = []; const shadowedParams = new Set(); @@ -59,6 +54,10 @@ export default function convertFunctionParams( collectShadowedParamsNames(param, scope, shadowedParams); } + const state = { + needsOuterBinding: false, + scope, + }; if (shadowedParams.size === 0) { for (const param of params) { if (!param.isIdentifier()) param.traverse(iifeVisitor, state); @@ -156,12 +155,7 @@ export default function convertFunctionParams( path.ensureBlock(); if (state.needsOuterBinding || shadowedParams.size > 0) { - body.push( - buildScopeIIFE( - shadowedParams, - (path.get("body") as NodePath).node, - ), - ); + body.push(buildScopeIIFE(shadowedParams, path.node.body)); path.set("body", t.blockStatement(body as t.Statement[])); diff --git a/packages/babel-plugin-transform-parameters/src/rest.ts b/packages/babel-plugin-transform-parameters/src/rest.ts index 70a6cffeaebb..6abd1abc4c7c 100644 --- a/packages/babel-plugin-transform-parameters/src/rest.ts +++ b/packages/babel-plugin-transform-parameters/src/rest.ts @@ -1,6 +1,12 @@ import { template, types as t } from "@babel/core"; import type { NodePath, Visitor } from "@babel/traverse"; +import { + iifeVisitor, + collectShadowedParamsNames, + buildScopeIIFE, +} from "./shadow-utils"; + const buildRest = template.statement(` for (var LEN = ARGUMENTS.length, ARRAY = new Array(ARRAY_LEN), @@ -292,6 +298,33 @@ export default function convertFunctionRest(path: NodePath) { const { node, scope } = path; if (!hasRest(node)) return false; + const restPath = path.get( + `params.${node.params.length - 1}.argument`, + ) as NodePath; + + if (!restPath.isIdentifier()) { + const shadowedParams = new Set(); + collectShadowedParamsNames(restPath, path.scope, shadowedParams); + + let needsIIFE = shadowedParams.size > 0; + if (!needsIIFE) { + const state = { + needsOuterBinding: false, + scope, + }; + restPath.traverse(iifeVisitor, state); + needsIIFE = state.needsOuterBinding; + } + + if (needsIIFE) { + path.ensureBlock(); + path.set( + "body", + t.blockStatement([buildScopeIIFE(shadowedParams, path.node.body)]), + ); + } + } + let rest = (node.params.pop() as t.RestElement).argument as | t.Pattern | t.Identifier; diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/parameters/.var-same-name-as-nested-in-rest-param-2/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/.var-same-name-as-nested-in-rest-param-2/input.js deleted file mode 100644 index 8c1179a8a914..000000000000 --- a/packages/babel-plugin-transform-parameters/test/fixtures/parameters/.var-same-name-as-nested-in-rest-param-2/input.js +++ /dev/null @@ -1,9 +0,0 @@ -function f(...{ length: x = 0 }) { - var x; - return x; -} - -function g(...{ length: x = 0 }) { - var x = 1; - return x; -} diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/parameters/.var-same-name-as-nested-in-rest-param/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/.var-same-name-as-nested-in-rest-param/input.js deleted file mode 100644 index 578486d8f368..000000000000 --- a/packages/babel-plugin-transform-parameters/test/fixtures/parameters/.var-same-name-as-nested-in-rest-param/input.js +++ /dev/null @@ -1,9 +0,0 @@ -function f(...[x]) { - var x; - return x; -} - -function g(...[x]) { - var x = 1; - return x; -} diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param-2/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param-2/input.js new file mode 100644 index 000000000000..bc58981bda4d --- /dev/null +++ b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param-2/input.js @@ -0,0 +1,9 @@ +function f(...{ length: x = 0, y = x }) { + var x; + return x; +} + +function g(...{ length: x = 0, y = x }) { + var x = 1; + return x; +} diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param-2/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param-2/output.js new file mode 100644 index 000000000000..eae5090a3040 --- /dev/null +++ b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param-2/output.js @@ -0,0 +1,26 @@ +function f() { + for (var _len = arguments.length, _ref = new Array(_len), _key = 0; _key < _len; _key++) { + _ref[_key] = arguments[_key]; + } + + var _ref$length = _ref.length, + x = _ref$length === void 0 ? 0 : _ref$length, + _ref$y = _ref.y, + y = _ref$y === void 0 ? x : _ref$y; + return x; +} + +function g() { + for (var _len2 = arguments.length, _ref2 = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + _ref2[_key2] = arguments[_key2]; + } + + var _ref2$length = _ref2.length, + x = _ref2$length === void 0 ? 0 : _ref2$length, + _ref2$y = _ref2.y, + y = _ref2$y === void 0 ? x : _ref2$y; + return function (x) { + var x = 1; + return x; + }(x); +} diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param/input.js new file mode 100644 index 000000000000..fbecdb6dc1c4 --- /dev/null +++ b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param/input.js @@ -0,0 +1,9 @@ +function f(...[x, y = x]) { + var x; + return x; +} + +function g(...[x, y = x]) { + var x = 1; + return x; +} diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param/output.js new file mode 100644 index 000000000000..92ade92006ac --- /dev/null +++ b/packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-name-as-nested-in-rest-param/output.js @@ -0,0 +1,24 @@ +function f() { + for (var _len = arguments.length, _ref = new Array(_len), _key = 0; _key < _len; _key++) { + _ref[_key] = arguments[_key]; + } + + var x = _ref[0], + _ref$ = _ref[1], + y = _ref$ === void 0 ? x : _ref$; + return x; +} + +function g() { + for (var _len2 = arguments.length, _ref2 = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + _ref2[_key2] = arguments[_key2]; + } + + var x = _ref2[0], + _ref2$ = _ref2[1], + y = _ref2$ === void 0 ? x : _ref2$; + return function (x) { + var x = 1; + return x; + }(x); +}