Skip to content

Commit

Permalink
fix: Babel should not crash when destructring arrray hole
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed Feb 11, 2022
1 parent ac44748 commit 57535de
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 13 deletions.
36 changes: 23 additions & 13 deletions packages/babel-plugin-transform-destructuring/src/util.ts
Expand Up @@ -19,8 +19,8 @@ function hasObjectRest(pattern: t.ObjectPattern) {
return pattern.properties.some(prop => t.isRestElement(prop));
}

interface Unpackable {
elements: Array<null | t.Expression>;
interface UnpackableArrayExpression extends t.ArrayExpression {
elements: (null | t.Expression)[];
}

const STOP_TRAVERSAL = {};
Expand Down Expand Up @@ -150,7 +150,7 @@ export class DestructuringTransformer {
return declar;
}

push(id: t.LVal, _init: t.Expression) {
push(id: t.LVal, _init: t.Expression | null) {
const init = t.cloneNode(_init);
if (t.isObjectPattern(id)) {
this.pushObjectPattern(id, init);
Expand All @@ -176,13 +176,13 @@ export class DestructuringTransformer {

pushAssignmentPattern(
{ left, right }: t.AssignmentPattern,
valueRef: t.Expression,
valueRef: t.Expression | null,
) {
// handle array init hole
// const [x = 42] = [,];
// -> const x = 42;
if (valueRef === null) {
this.nodes.push(this.buildVariableAssignment(left, right));
this.push(left, right);
return;
}

Expand Down Expand Up @@ -317,17 +317,19 @@ export class DestructuringTransformer {
}
}

pushObjectPattern(pattern: t.ObjectPattern, objRef: t.Expression) {
pushObjectPattern(pattern: t.ObjectPattern, objRef: t.Expression | null) {
// https://github.com/babel/babel/issues/681

if (!pattern.properties.length) {
if (!pattern.properties.length || objRef === null) {
this.nodes.push(
t.expressionStatement(
t.callExpression(this.addHelper("objectDestructuringEmpty"), [
objRef,
]),
t.callExpression(
this.addHelper("objectDestructuringEmpty"),
objRef !== null ? [objRef] : [],
),
),
);
return;
}

// if we have more than one properties in this pattern and the objectRef is a
Expand Down Expand Up @@ -380,7 +382,7 @@ export class DestructuringTransformer {
canUnpackArrayPattern(
pattern: t.ArrayPattern,
arr: t.Expression,
): arr is t.ArrayExpression & Unpackable {
): arr is UnpackableArrayExpression {
// not an array so there's no way we can deal with this
if (!t.isArrayExpression(arr)) return false;

Expand Down Expand Up @@ -428,7 +430,7 @@ export class DestructuringTransformer {

pushUnpackedArrayPattern(
pattern: t.ArrayPattern,
arr: t.ArrayExpression & Unpackable,
arr: UnpackableArrayExpression,
) {
for (let i = 0; i < pattern.elements.length; i++) {
const elem = pattern.elements[i];
Expand All @@ -440,7 +442,15 @@ export class DestructuringTransformer {
}
}

pushArrayPattern(pattern: t.ArrayPattern, arrayRef: t.Expression) {
pushArrayPattern(pattern: t.ArrayPattern, arrayRef: t.Expression | null) {
if (arrayRef === null) {
this.nodes.push(
t.expressionStatement(
t.callExpression(this.addHelper("objectDestructuringEmpty"), []),
),
);
return;
}
if (!pattern.elements) return;

// optimise basic array destructuring of an array expression
Expand Down
Expand Up @@ -43,3 +43,20 @@ expect(f).toEqual(undefined);

let [g] = [,];
expect(g).toEqual(undefined);

let thrown;
try {
thrown = false;
[{}] = [,];
} catch {
thrown = true;
}
expect(thrown).toEqual(true);

try {
thrown = false;
[[]] = [,];
} catch {
thrown = true;
}
expect(thrown).toEqual(true);
Expand Up @@ -43,3 +43,20 @@ expect(f).toEqual(undefined);

let [g] = [,];
expect(g).toEqual(undefined);

let thrown;
try {
thrown = false;
[{}] = [,];
} catch {
thrown = true;
}
expect(thrown).toEqual(true);

try {
thrown = false;
[[]] = [,];
} catch {
thrown = true;
}
expect(thrown).toEqual(true);
Expand Up @@ -39,3 +39,22 @@ const f = void 0;
expect(f).toEqual(undefined);
let g;
expect(g).toEqual(undefined);
let thrown;

try {
thrown = false;
babelHelpers.objectDestructuringEmpty();
} catch {
thrown = true;
}

expect(thrown).toEqual(true);

try {
thrown = false;
babelHelpers.objectDestructuringEmpty();
} catch {
thrown = true;
}

expect(thrown).toEqual(true);

0 comments on commit 57535de

Please sign in to comment.