Skip to content

Commit

Permalink
Fix holes handling in optimized array destructuring
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Sep 29, 2022
1 parent abb26aa commit cd8c44f
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 17 deletions.
25 changes: 20 additions & 5 deletions packages/babel-plugin-transform-destructuring/src/util.ts
Expand Up @@ -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<t.ForXStatement>,
newStatements: t.Statement[],
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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]));
}
}
}
Expand Down
Expand Up @@ -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;
Expand Down
Expand Up @@ -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;

Expand All @@ -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] = [,];
Expand Down
Expand Up @@ -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;

Expand All @@ -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] = [,];
Expand Down
Expand Up @@ -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;) {
Expand All @@ -31,19 +31,19 @@ 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;

try {
thrown = false;
babelHelpers.objectDestructuringEmpty();
babelHelpers.objectDestructuringEmpty(void 0);
} catch (e) {
thrown = true;
}
Expand All @@ -52,7 +52,8 @@ expect(thrown).toEqual(true);

try {
thrown = false;
babelHelpers.objectDestructuringEmpty();

var _ = babelHelpers.toArray(void 0);
} catch (e) {
thrown = true;
}
Expand Down

0 comments on commit cd8c44f

Please sign in to comment.