Skip to content

Commit

Permalink
fix: Duplicate declaration in transformed for...of (#14564)
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu committed May 19, 2022
1 parent cc2de3b commit 44362f4
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 29 deletions.
60 changes: 31 additions & 29 deletions packages/babel-plugin-transform-for-of/src/index.ts
@@ -1,5 +1,6 @@
import { declare } from "@babel/helper-plugin-utils";
import { template, types as t } from "@babel/core";
import type { NodePath } from "@babel/traverse";

import transformWithoutHelper from "./no-helper-implementation";

Expand All @@ -9,6 +10,28 @@ export interface Options {
loose?: boolean;
}

function buildLoopBody(
path: NodePath<t.ForXStatement>,
declar: t.Statement,
newBody?: t.Statement | t.Expression,
) {
let block;
const bodyPath = path.get("body");
const body = newBody ?? bodyPath.node;
if (
t.isBlockStatement(body) &&
Object.keys(path.getBindingIdentifiers()).some(id =>
bodyPath.scope.hasOwnBinding(id),
)
) {
block = t.blockStatement([declar, body]);
} else {
block = t.toBlock(body);
block.body.unshift(declar);
}
return block;
}

export default declare((api, options: Options) => {
api.assertVersion(7);

Expand Down Expand Up @@ -90,20 +113,6 @@ export default declare((api, options: Options) => {
);
}

let blockBody;
const body = path.get("body");
if (
body.isBlockStatement() &&
Object.keys(path.getBindingIdentifiers()).some(id =>
body.scope.hasOwnBinding(id),
)
) {
blockBody = t.blockStatement([assignment, body.node]);
} else {
blockBody = t.toBlock(body.node);
blockBody.body.unshift(assignment);
}

path.replaceWith(
t.forStatement(
t.variableDeclaration("let", inits),
Expand All @@ -113,7 +122,7 @@ export default declare((api, options: Options) => {
t.memberExpression(t.cloneNode(array), t.identifier("length")),
),
t.updateExpression("++", t.cloneNode(i)),
blockBody,
buildLoopBody(path, assignment),
),
);
},
Expand Down Expand Up @@ -167,28 +176,26 @@ export default declare((api, options: Options) => {
}) as t.For;

t.inherits(loop, node);
t.ensureBlock(loop);

const iterationValue = t.memberExpression(
t.cloneNode(right),
t.cloneNode(iterationKey),
true,
);

let declar;
const left = node.left;
if (t.isVariableDeclaration(left)) {
left.declarations[0].init = iterationValue;
// @ts-expect-error todo(flow->ts):
loop.body.body.unshift(left);
declar = left;
} else {
// @ts-expect-error todo(flow->ts):
loop.body.body.unshift(
t.expressionStatement(
t.assignmentExpression("=", left, iterationValue),
),
declar = t.expressionStatement(
t.assignmentExpression("=", left, iterationValue),
);
}

loop.body = buildLoopBody(path, declar, loop.body);

return loop;
}

Expand Down Expand Up @@ -234,11 +241,6 @@ export default declare((api, options: Options) => {
);
}

// ensure that it's a block so we can take all its statements
path.ensureBlock();

(node.body as t.BlockStatement).body.unshift(declar);

const nodes = builder.build({
CREATE_ITERATOR_HELPER: state.addHelper(builder.helper),
ITERATOR_HELPER: scope.generateUidIdentifier("iterator"),
Expand All @@ -247,7 +249,7 @@ export default declare((api, options: Options) => {
: null,
STEP_KEY: t.identifier(stepKey),
OBJECT: node.right,
BODY: node.body,
BODY: buildLoopBody(path, declar),
});
const container = builder.getContainer(nodes);

Expand Down
@@ -1,3 +1,7 @@
for (const elm of array) {
const elm = 2;
}

for (let x of []) {
let x = 1;
}
Expand Up @@ -4,3 +4,10 @@ for (let _i = 0, _array = array; _i < _array.length; _i++) {
const elm = 2;
}
}

for (let _i2 = 0, _ref = []; _i2 < _ref.length; _i2++) {
let x = _ref[_i2];
{
let x = 1;
}
}
@@ -0,0 +1,9 @@
for (let x of y) {
let x = 1;
let y = 2;
}

for (let x of []) {
let x = 1;
let y = 2;
}
@@ -0,0 +1,15 @@
for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(y), _step; !(_step = _iterator()).done;) {
let x = _step.value;
{
let x = 1;
let y = 2;
}
}

for (var _i = 0, _arr = []; _i < _arr.length; _i++) {
let x = _arr[_i];
{
let x = 1;
let y = 2;
}
}

0 comments on commit 44362f4

Please sign in to comment.