diff --git a/packages/babel-plugin-transform-destructuring/src/util.ts b/packages/babel-plugin-transform-destructuring/src/util.ts index 9fde09a6897d..2451599857c2 100644 --- a/packages/babel-plugin-transform-destructuring/src/util.ts +++ b/packages/babel-plugin-transform-destructuring/src/util.ts @@ -3,6 +3,14 @@ import type { File } from "@babel/core"; import type { Scope, NodePath } from "@babel/traverse"; import type { TraversalAncestors } from "@babel/types"; +function isPureVoid(node: t.Node) { + return ( + t.isUnaryExpression(node) && + node.operator === "void" && + t.isPureish(node.argument) + ); +} + export function unshiftForXStatementBody( statementPath: NodePath, newStatements: t.Statement[], @@ -194,10 +202,11 @@ export class DestructuringTransformer { { left, right }: t.AssignmentPattern, valueRef: t.Expression | null, ) { - // handle array init hole - // const [x = 42] = [,]; + // handle array init with void 0. This also happens when + // the value was originally a hole. + // const [x = 42] = [void 0,]; // -> const x = 42; - if (valueRef === null) { + if (isPureVoid(valueRef)) { this.push(left, right); return; } @@ -274,15 +283,15 @@ export class DestructuringTransformer { } } - pushObjectPattern(pattern: t.ObjectPattern, objRef: t.Expression | null) { + pushObjectPattern(pattern: t.ObjectPattern, objRef: t.Expression) { // https://github.com/babel/babel/issues/681 - if (!pattern.properties.length || objRef === null) { + if (!pattern.properties.length) { this.nodes.push( t.expressionStatement( t.callExpression( this.addHelper("objectDestructuringEmpty"), - objRef !== null ? [objRef] : [], + isPureVoid(objRef) ? [] : [objRef], ), ), ); @@ -391,12 +400,18 @@ export class DestructuringTransformer { pattern: t.ArrayPattern, arr: UnpackableArrayExpression, ) { + const holeToUndefined = (el: t.Expression) => + el ?? this.scope.buildUndefinedNode(); + for (let i = 0; i < pattern.elements.length; i++) { const elem = pattern.elements[i]; if (t.isRestElement(elem)) { - this.push(elem.argument, t.arrayExpression(arr.elements.slice(i))); + this.push( + elem.argument, + t.arrayExpression(arr.elements.slice(i).map(holeToUndefined)), + ); } else { - this.push(elem, arr.elements[i]); + this.push(elem, holeToUndefined(arr.elements[i])); } } } diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/array-unpack-optimisation/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/array-unpack-optimisation/output.js index 7de1af1261e7..194bcd85727a 100644 --- a/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/array-unpack-optimisation/output.js +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/array-unpack-optimisation/output.js @@ -34,7 +34,7 @@ var _ref7 = [clazz.foo(), bar], var _ref8 = [clazz.foo, bar], a = _ref8[0], b = _ref8[1]; -var a, +var a = void 0, b = 2; a = 1; b = 2; 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 index 4ee0994ece01..acbcb430bc56 100644 --- 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 @@ -19,7 +19,7 @@ expect(b).toEqual(1); const arr = [c = 42] = [,]; expect(c).toEqual(42); -expect(arr).toEqual([,]); +expect(arr).toStrictEqual([,]); var iterCount = 0; @@ -35,7 +35,7 @@ expect(iterCount).toEqual(1); const [...d] = [,]; const [...{ 0: e }] = [,]; -expect(d).toEqual([,]); +expect(d).toStrictEqual([undefined,]); expect(e).toEqual(undefined); const [f] = [,]; 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 index 4ee0994ece01..1d7ec2eb3f78 100644 --- 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 @@ -19,7 +19,7 @@ expect(b).toEqual(1); const arr = [c = 42] = [,]; expect(c).toEqual(42); -expect(arr).toEqual([,]); +expect(arr).toStrictEqual([,]); var iterCount = 0; @@ -35,7 +35,7 @@ expect(iterCount).toEqual(1); const [...d] = [,]; const [...{ 0: e }] = [,]; -expect(d).toEqual([,]); +expect(d).toStrictEqual([,]); expect(e).toEqual(undefined); const [f] = [,]; 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 index c29f6208ef72..1240200ac2e5 100644 --- 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 @@ -21,7 +21,7 @@ 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([,]); +expect(arr).toStrictEqual([,]); var iterCount = 0; for (const x = 23; iterCount < 1;) { @@ -31,13 +31,13 @@ for (const x = 23; iterCount < 1;) { } expect(iterCount).toEqual(1); -const d = [,]; -const e = [,][0]; -expect(d).toEqual([,]); +const d = [void 0]; +const e = [void 0][0]; +expect(d).toStrictEqual([,]); expect(e).toEqual(undefined); const f = void 0; expect(f).toEqual(undefined); -let g; +let g = void 0; expect(g).toEqual(undefined); let thrown; @@ -52,7 +52,8 @@ expect(thrown).toEqual(true); try { thrown = false; - babelHelpers.objectDestructuringEmpty(); + + var _ = babelHelpers.toArray(void 0); } catch (e) { thrown = true; }