Fix export bindings not updated by 'for...in' and 'for...of' (#11074)

* Correctly transpile export bindings for some for-of loops

* Correctly transform non-destructured for of loops to update exported variables

* Add tests

* Don't replace entire for of loop

* Correctly transform destructured for-of/for-in exports

* Update exported variables in array pattern and more fixes

* Refresh test output

* Update tests and rebase on master

* Refactor ForOf|ForIn visitor

* Don't transform re-declared exported vars

* Generate better name for loop id

Co-Authored-By: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>

* Idiomatically generate UidIdentifier

* Update scope after replacing loop declaration

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
Vedant Roy
2020-02-09 05:40:52 -05:00
committed by Nicolò Ribaudo
parent 5aa368cec1
commit dadba01249
3 changed files with 123 additions and 0 deletions

View File

@@ -306,4 +306,40 @@ const rewriteReferencesVisitor = {
}
},
},
"ForOfStatement|ForInStatement"(path) {
const { scope, node } = path;
const { left } = node;
const { exported, scope: programScope } = this;
if (!t.isVariableDeclaration(left)) {
let didTransform = false;
const bodyPath = path.get("body");
const loopBodyScope = bodyPath.scope;
for (const name of Object.keys(t.getOuterBindingIdentifiers(left))) {
if (
exported.get(name) &&
programScope.getBinding(name) === scope.getBinding(name)
) {
didTransform = true;
if (loopBodyScope.hasOwnBinding(name)) {
loopBodyScope.rename(name);
}
}
}
if (!didTransform) {
return;
}
const newLoopId = scope.generateUidIdentifierBasedOnNode(left);
bodyPath.unshiftContainer(
"body",
t.expressionStatement(t.assignmentExpression("=", left, newLoopId)),
);
path
.get("left")
.replaceWith(
t.variableDeclaration("let", [t.variableDeclarator(newLoopId)]),
);
scope.registerDeclaration(path.get("left"));
}
},
};