From 6b4d4661dda4f1ebeec781a5b10d462ba8451bbe Mon Sep 17 00:00:00 2001 From: magic-akari Date: Sat, 12 Feb 2022 02:26:03 +0800 Subject: [PATCH] Fix destructuring with holes in assign pattern (#14240) --- .../src/index.ts | 18 +++++++- .../fixtures/destructuring/init-hole/exec.js | 45 +++++++++++++++++++ .../fixtures/destructuring/init-hole/input.js | 45 +++++++++++++++++++ .../destructuring/init-hole/options.json | 3 ++ .../destructuring/init-hole/output.js | 41 +++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/exec.js create mode 100644 packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/input.js create mode 100644 packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/options.json create mode 100644 packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/output.js diff --git a/packages/babel-plugin-transform-destructuring/src/index.ts b/packages/babel-plugin-transform-destructuring/src/index.ts index 959e8fbf2ec8..dc401a04ab96 100644 --- a/packages/babel-plugin-transform-destructuring/src/index.ts +++ b/packages/babel-plugin-transform-destructuring/src/index.ts @@ -114,8 +114,16 @@ export default declare((api, options) => { ), ); } else { + let nodeInit: t.Expression; + + if (this.kind === "const" && init === null) { + nodeInit = this.scope.buildUndefinedNode(); + } else { + nodeInit = t.cloneNode(init); + } + node = t.variableDeclaration(this.kind, [ - t.variableDeclarator(id, t.cloneNode(init)), + t.variableDeclarator(id, nodeInit), ]); } @@ -158,6 +166,14 @@ export default declare((api, options) => { } pushAssignmentPattern({ left, right }, valueRef) { + // handle array init hole + // const [x = 42] = [,]; + // -> const x = 42; + if (valueRef === null) { + this.nodes.push(this.buildVariableAssignment(left, right)); + return; + } + // we need to assign the current value of the assignment to avoid evaluating // it more than once const tempId = this.scope.generateUidIdentifierBasedOnNode(valueRef); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/exec.js b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/exec.js new file mode 100644 index 000000000000..05623e2c91d2 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/exec.js @@ -0,0 +1,45 @@ +let [x = 23] = [,]; +expect(x).toEqual(23); + +const [y = 24, z] = [, 42]; +expect(y).toEqual(24); +expect(z).toEqual(42); + +function* foo() { + yield 1; + yield 2; +} + +let bar = foo(); + +const [a = bar.next().value, b] = [, bar.next().value]; + +expect(a).toEqual(2); +expect(b).toEqual(1); + +const arr = [c = 42] = [,]; +expect(c).toEqual(42); +expect(arr).toEqual([,]); + +var iterCount = 0; + +for (const [x = 23] = [,]; iterCount < 1; ) { + expect(x).toEqual(23); + // another statement + + iterCount += 1; +} + +expect(iterCount).toEqual(1); + +const [...d] = [,]; +const [...{ 0: e }] = [,]; + +expect(d).toEqual([,]); +expect(e).toEqual(undefined); + +const [f] = [,]; +expect(f).toEqual(undefined); + +let [g] = [,]; +expect(g).toEqual(undefined); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/input.js b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/input.js new file mode 100644 index 000000000000..05623e2c91d2 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/input.js @@ -0,0 +1,45 @@ +let [x = 23] = [,]; +expect(x).toEqual(23); + +const [y = 24, z] = [, 42]; +expect(y).toEqual(24); +expect(z).toEqual(42); + +function* foo() { + yield 1; + yield 2; +} + +let bar = foo(); + +const [a = bar.next().value, b] = [, bar.next().value]; + +expect(a).toEqual(2); +expect(b).toEqual(1); + +const arr = [c = 42] = [,]; +expect(c).toEqual(42); +expect(arr).toEqual([,]); + +var iterCount = 0; + +for (const [x = 23] = [,]; iterCount < 1; ) { + expect(x).toEqual(23); + // another statement + + iterCount += 1; +} + +expect(iterCount).toEqual(1); + +const [...d] = [,]; +const [...{ 0: e }] = [,]; + +expect(d).toEqual([,]); +expect(e).toEqual(undefined); + +const [f] = [,]; +expect(f).toEqual(undefined); + +let [g] = [,]; +expect(g).toEqual(undefined); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/options.json b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/options.json new file mode 100644 index 000000000000..84e28c07f51e --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["transform-destructuring"] +} diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/output.js new file mode 100644 index 000000000000..b965fc9fd613 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/init-hole/output.js @@ -0,0 +1,41 @@ +var _ref2, _ref2$; + +let x = 23; +expect(x).toEqual(23); +const y = 24, + z = 42; +expect(y).toEqual(24); +expect(z).toEqual(42); + +function* foo() { + yield 1; + yield 2; +} + +let bar = foo(); +const _ref = [, bar.next().value], + _ref$ = _ref[0], + a = _ref$ === void 0 ? bar.next().value : _ref$, + b = _ref[1]; +expect(a).toEqual(2); +expect(b).toEqual(1); +const arr = (_ref2 = [,], _ref2$ = _ref2[0], c = _ref2$ === void 0 ? 42 : _ref2$, _ref2); +expect(c).toEqual(42); +expect(arr).toEqual([,]); +var iterCount = 0; + +for (const x = 23; iterCount < 1;) { + expect(x).toEqual(23); // another statement + + iterCount += 1; +} + +expect(iterCount).toEqual(1); +const d = [,]; +const e = [,][0]; +expect(d).toEqual([,]); +expect(e).toEqual(undefined); +const f = void 0; +expect(f).toEqual(undefined); +let g; +expect(g).toEqual(undefined);