diff --git a/packages/babel-helper-module-transforms/src/rewrite-live-references.ts b/packages/babel-helper-module-transforms/src/rewrite-live-references.ts index 84a0a8da90d9..8cd814cc7c24 100644 --- a/packages/babel-helper-module-transforms/src/rewrite-live-references.ts +++ b/packages/babel-helper-module-transforms/src/rewrite-live-references.ts @@ -350,31 +350,33 @@ const rewriteReferencesVisitor: Visitor = { ) { 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( @@ -383,6 +385,19 @@ const rewriteReferencesVisitor: Visitor = { ]), ); 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)), + ); + } } }, }; diff --git a/packages/babel-helper-simple-access/src/index.ts b/packages/babel-helper-simple-access/src/index.ts index c812f195bacc..27304a32ee0d 100644 --- a/packages/babel-helper-simple-access/src/index.ts +++ b/packages/babel-helper-simple-access/src/index.ts @@ -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 = "="; + } }, }, }; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/for-of-in-export/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/for-of-in-export/input.mjs index fe09208eea2c..8b11f890a175 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/for-of-in-export/input.mjs +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/for-of-in-export/input.mjs @@ -16,7 +16,9 @@ for ([foo, [...foo]] of []) { let foo; } +for (foo of []) ; + { let foo; for(foo of []) {} -} \ No newline at end of file +} diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/for-of-in-export/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/for-of-in-export/output.js index bb8330350160..6375528d7646 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/for-of-in-export/output.js +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/for-of-in-export/output.js @@ -58,6 +58,11 @@ for (let _ref2 of []) { let _foo8; } +for (let _foo9 of []) { + exports.bar = exports.foo = foo = _foo9; + ; +} + { let foo; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/import-const-throw/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/import-const-throw/input.mjs index 899f1394bbb1..650e21b272d8 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/import-const-throw/input.mjs +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/import-const-throw/input.mjs @@ -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 {}) {} diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/import-const-throw/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/import-const-throw/output.js index 01984ae47f96..79d37c0932bf 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/import-const-throw/output.js +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/import-const-throw/output.js @@ -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.'); + })(); +}