Skip to content

Commit

Permalink
Fix const violations in ESM imports when transformed to CJS (#13258)
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Jun 22, 2021
1 parent 47ad54a commit 5ac5e35
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 23 deletions.
Expand Up @@ -350,31 +350,33 @@ const rewriteReferencesVisitor: Visitor<RewriteReferencesVisitorState> = {
) {
const { scope, node } = path;
const { left } = node;
const { exported, scope: programScope } = this;
const { exported, imported, scope: programScope } = this;

if (!t.isVariableDeclaration(left)) {
let didTransform = false;
const bodyPath = path.get("body");
const loopBodyScope = bodyPath.scope;
let didTransformExport = false,
importConstViolationName;
const loopBodyScope = path.get("body").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 (programScope.getBinding(name) === scope.getBinding(name)) {
if (exported.has(name)) {
didTransformExport = true;
if (loopBodyScope.hasOwnBinding(name)) {
loopBodyScope.rename(name);
}
}
if (imported.has(name) && !importConstViolationName) {
importConstViolationName = name;
}
}
}
if (!didTransform) {
if (!didTransformExport && !importConstViolationName) {
return;
}

path.ensureBlock();
const bodyPath = path.get("body");

const newLoopId = scope.generateUidIdentifierBasedOnNode(left);
bodyPath.unshiftContainer(
"body",
t.expressionStatement(t.assignmentExpression("=", left, newLoopId)),
);
path
.get("left")
.replaceWith(
Expand All @@ -383,6 +385,19 @@ const rewriteReferencesVisitor: Visitor<RewriteReferencesVisitorState> = {
]),
);
scope.registerDeclaration(path.get("left"));

if (didTransformExport) {
bodyPath.unshiftContainer(
"body",
t.expressionStatement(t.assignmentExpression("=", left, newLoopId)),
);
}
if (importConstViolationName) {
bodyPath.unshiftContainer(
"body",
t.expressionStatement(buildImportThrow(importConstViolationName)),
);
}
}
},
};
30 changes: 24 additions & 6 deletions packages/babel-helper-simple-access/src/index.ts
Expand Up @@ -100,12 +100,30 @@ const simpleAssignmentVisitor = {
return;
}

path.node.right = t.binaryExpression(
path.node.operator.slice(0, -1),
t.cloneNode(path.node.left),
path.node.right,
);
path.node.operator = "=";
const operator = path.node.operator.slice(0, -1);
if (t.LOGICAL_OPERATORS.includes(operator)) {
// &&, ||, ??
// (foo &&= bar) => (foo && foo = bar)
path.replaceWith(
t.logicalExpression(
operator,
path.node.left,
t.assignmentExpression(
"=",
t.cloneNode(path.node.left),
path.node.right,
),
),
);
} else {
// (foo += bar) => (foo = foo + bar)
path.node.right = t.binaryExpression(
operator,
t.cloneNode(path.node.left),
path.node.right,
);
path.node.operator = "=";
}
},
},
};
Expand Up @@ -16,7 +16,9 @@ for ([foo, [...foo]] of []) {
let foo;
}

for (foo of []) ;

{
let foo;
for(foo of []) {}
}
}
Expand Up @@ -58,6 +58,11 @@ for (let _ref2 of []) {
let _foo8;
}

for (let _foo9 of []) {
exports.bar = exports.foo = foo = _foo9;
;
}

{
let foo;

Expand Down
Expand Up @@ -15,3 +15,33 @@ Baz = 44;
({prop: Foo} = {});
({prop: Bar} = {});
({prop: Baz} = {});

Foo += 2;
Bar += 2;
Baz += 2;

Foo >>>= 3;
Bar >>>= 3;
Baz >>>= 3;

Foo &&= 4;
Bar &&= 4;
Baz &&= 4;

--Foo;
--Bar;
--Baz;

Foo++;
Bar++;
Baz++;

for (Foo in {}) ;
for (Bar in {}) {}
for (Baz of []) {
let Baz;
}

for ({Foo} in {}) {}
for ([Bar] in {}) {}
for ([...Baz] in {}) {}
Expand Up @@ -47,3 +47,88 @@ _baz.Baz = (44, function () {
} = ({}, function () {
throw new Error('"' + "Baz" + '" is read-only.');
}()));
_foo.default = (_foo.default + 2, function () {
throw new Error('"' + "Foo" + '" is read-only.');
}());
Bar = (Bar + 2, function () {
throw new Error('"' + "Bar" + '" is read-only.');
}());
_baz.Baz = (_baz.Baz + 2, function () {
throw new Error('"' + "Baz" + '" is read-only.');
}());
_foo.default = (_foo.default >>> 3, function () {
throw new Error('"' + "Foo" + '" is read-only.');
}());
Bar = (Bar >>> 3, function () {
throw new Error('"' + "Bar" + '" is read-only.');
}());
_baz.Baz = (_baz.Baz >>> 3, function () {
throw new Error('"' + "Baz" + '" is read-only.');
}());
_foo.default && (_foo.default = (4, function () {
throw new Error('"' + "Foo" + '" is read-only.');
}()));
Bar && (Bar = (4, function () {
throw new Error('"' + "Bar" + '" is read-only.');
}()));
_baz.Baz && (_baz.Baz = (4, function () {
throw new Error('"' + "Baz" + '" is read-only.');
}()));
_foo.default = (_foo.default - 1, function () {
throw new Error('"' + "Foo" + '" is read-only.');
}());
Bar = (Bar - 1, function () {
throw new Error('"' + "Bar" + '" is read-only.');
}());
_baz.Baz = (_baz.Baz - 1, function () {
throw new Error('"' + "Baz" + '" is read-only.');
}());
_foo.default = (_foo.default + 1, function () {
throw new Error('"' + "Foo" + '" is read-only.');
}());
Bar = (Bar + 1, function () {
throw new Error('"' + "Bar" + '" is read-only.');
}());
_baz.Baz = (_baz.Baz + 1, function () {
throw new Error('"' + "Baz" + '" is read-only.');
}());

for (let _Foo in {}) {
(function () {
throw new Error('"' + "Foo" + '" is read-only.');
})();

;
}

for (let _Bar in {}) {
(function () {
throw new Error('"' + "Bar" + '" is read-only.');
})();
}

for (let _Baz of []) {
(function () {
throw new Error('"' + "Baz" + '" is read-only.');
})();

let Baz;
}

for (let _Foo2 in {}) {
(function () {
throw new Error('"' + "Foo" + '" is read-only.');
})();
}

for (let _ref in {}) {
(function () {
throw new Error('"' + "Bar" + '" is read-only.');
})();
}

for (let _ref2 in {}) {
(function () {
throw new Error('"' + "Baz" + '" is read-only.');
})();
}

0 comments on commit 5ac5e35

Please sign in to comment.