From 8a8c1a2692ac1158cb5a24048e1c2944c08eb62d Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 10 Mar 2022 02:00:15 +0800 Subject: [PATCH 1/6] Fix update expression for bigints --- .../src/rewrite-live-references.ts | 75 +++++++++++++++++++ .../babel-helper-simple-access/src/index.ts | 71 ------------------ .../test/fixtures/amd/remap/output.js | 5 +- .../test/fixtures/loose/remap/output.js | 5 +- .../src/index.ts | 23 +++++- .../fixtures/interop-loose/remap/output.js | 5 +- .../test/fixtures/interop/remap/output.js | 5 +- .../misc/import-const-throw/output.js | 30 +++++--- .../fixtures/misc/module-exports/output.js | 8 +- .../fixtures/regression/4462-T7565/output.js | 2 +- .../update-expression/bigint/exec.mjs | 16 ++++ .../update-expression/bigint/input.mjs | 16 ++++ .../update-expression/bigint/options.json | 4 + .../update-expression/bigint/output.js | 21 ++++++ .../negative-suffix/output.js | 2 +- .../positive-suffix/output.js | 2 +- .../test/fixtures/loose/remap/output.js | 5 +- .../test/fixtures/umd/remap/output.js | 5 +- 18 files changed, 203 insertions(+), 97 deletions(-) create mode 100644 packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/exec.mjs create mode 100644 packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/input.mjs create mode 100644 packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/options.json create mode 100644 packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/output.js 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 ca7b3e36e531..4bb8722b8a45 100644 --- a/packages/babel-helper-module-transforms/src/rewrite-live-references.ts +++ b/packages/babel-helper-module-transforms/src/rewrite-live-references.ts @@ -290,6 +290,81 @@ const rewriteReferencesVisitor: Visitor = { } }, + UpdateExpression(path) { + const { + scope, + seen, + imported, + exported, + requeueInParent, + buildImportReference, + } = this; + + if (seen.has(path.node)) return; + + seen.add(path.node); + + const arg = path.get("argument"); + + // No change needed + if (arg.isMemberExpression()) return; + + const update = path.node; + + if (arg.isIdentifier()) { + const localName = arg.node.name; + + // redeclared in this scope + if (scope.getBinding(localName) !== path.scope.getBinding(localName)) { + return; + } + + const exportedNames = exported.get(localName); + const importData = imported.get(localName); + + if (exportedNames?.length > 0 || importData) { + if (importData) { + path.replaceWith( + assignmentExpression( + update.operator[0] + "=", + buildImportReference(importData, arg.node), + buildImportThrow(localName), + ), + ); + } else if (update.prefix) { + // ++foo + // => exports.foo = ++foo + path.replaceWith( + buildBindingExportAssignmentExpression( + this.metadata, + exportedNames, + cloneNode(update), + ), + ); + } else { + // foo++ + // => (ref = i++, exports.i = i, ref) + const ref = scope.generateDeclaredUidIdentifier(localName); + + path.replaceWith( + sequenceExpression([ + assignmentExpression("=", cloneNode(ref), cloneNode(update)), + buildBindingExportAssignmentExpression( + this.metadata, + exportedNames, + identifier(localName), + ), + cloneNode(ref), + ]), + ); + } + } + } + + requeueInParent(path); + path.skip(); + }, + AssignmentExpression: { exit(path) { const { diff --git a/packages/babel-helper-simple-access/src/index.ts b/packages/babel-helper-simple-access/src/index.ts index 8b812002934d..23b720e9e477 100644 --- a/packages/babel-helper-simple-access/src/index.ts +++ b/packages/babel-helper-simple-access/src/index.ts @@ -3,11 +3,7 @@ import { assignmentExpression, binaryExpression, cloneNode, - identifier, logicalExpression, - numericLiteral, - sequenceExpression, - unaryExpression, } from "@babel/types"; import type { NodePath } from "@babel/traverse"; @@ -20,73 +16,6 @@ export default function simplifyAccess(path: NodePath, bindingNames) { } const simpleAssignmentVisitor = { - UpdateExpression: { - exit(path) { - const { scope, bindingNames } = this; - - const arg = path.get("argument"); - if (!arg.isIdentifier()) return; - const localName = arg.node.name; - - if (!bindingNames.has(localName)) return; - - // redeclared in this scope - if (scope.getBinding(localName) !== path.scope.getBinding(localName)) { - return; - } - - if ( - path.parentPath.isExpressionStatement() && - !path.isCompletionRecord() - ) { - // ++i => (i += 1); - const operator = path.node.operator == "++" ? "+=" : "-="; - path.replaceWith( - assignmentExpression(operator, arg.node, numericLiteral(1)), - ); - } else if (path.node.prefix) { - // ++i => (i = (+i) + 1); - path.replaceWith( - assignmentExpression( - "=", - identifier(localName), - binaryExpression( - path.node.operator[0], - unaryExpression("+", arg.node), - numericLiteral(1), - ), - ), - ); - } else { - const old = path.scope.generateUidIdentifierBasedOnNode( - arg.node, - "old", - ); - const varName = old.name; - path.scope.push({ id: old }); - - const binary = binaryExpression( - path.node.operator[0], - identifier(varName), - numericLiteral(1), - ); - - // i++ => (_old = (+i), i = _old + 1, _old) - path.replaceWith( - sequenceExpression([ - assignmentExpression( - "=", - identifier(varName), - unaryExpression("+", arg.node), - ), - assignmentExpression("=", cloneNode(arg.node), binary), - identifier(varName), - ]), - ); - } - }, - }, - AssignmentExpression: { exit(path) { const { scope, seen, bindingNames } = this; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/amd/remap/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/amd/remap/output.js index ed299cfcd574..c42f3be2f9ca 100644 --- a/packages/babel-plugin-transform-modules-amd/test/fixtures/amd/remap/output.js +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/amd/remap/output.js @@ -5,10 +5,13 @@ define(["exports"], function (_exports) { value: true }); _exports.test = _exports.f = _exports.e = _exports.c = _exports.a = void 0; + + var _test; + var test = 2; _exports.test = test; _exports.test = test = 5; - _exports.test = test = test + 1; + _test = test++, _exports.test = test, _test; (function () { var test = 2; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/loose/remap/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/loose/remap/output.js index 7da7e38d4ac4..11f2791703d0 100644 --- a/packages/babel-plugin-transform-modules-amd/test/fixtures/loose/remap/output.js +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/loose/remap/output.js @@ -3,10 +3,13 @@ define(["exports"], function (_exports) { _exports.__esModule = true; _exports.test = _exports.f = _exports.e = _exports.c = _exports.a = void 0; + + var _test; + var test = 2; _exports.test = test; _exports.test = test = 5; - _exports.test = test = test + 1; + _test = test++, _exports.test = test, _test; (function () { var test = 2; diff --git a/packages/babel-plugin-transform-modules-commonjs/src/index.ts b/packages/babel-plugin-transform-modules-commonjs/src/index.ts index e9a2c78ca52e..ded511bba2ad 100644 --- a/packages/babel-plugin-transform-modules-commonjs/src/index.ts +++ b/packages/babel-plugin-transform-modules-commonjs/src/index.ts @@ -81,7 +81,8 @@ export default declare((api, options) => { (path.parentPath.isObjectProperty({ value: path.node }) && path.parentPath.parentPath.isObjectPattern()) || path.parentPath.isAssignmentExpression({ left: path.node }) || - path.isAssignmentExpression({ left: path.node }) + path.isAssignmentExpression({ left: path.node }) || + path.parentPath.isUpdateExpression() ) { return; } @@ -89,6 +90,26 @@ export default declare((api, options) => { path.replaceWith(getAssertion(localName)); }, + UpdateExpression(path) { + const arg = path.get("argument"); + const localName = arg.node.name; + if (localName !== "module" && localName !== "exports") return; + + const localBinding = path.scope.getBinding(localName); + const rootBinding = this.scope.getBinding(localName); + + // redeclared in this scope + if (rootBinding !== localBinding) return; + + path.replaceWith( + t.assignmentExpression( + path.node.operator[0] + "=", + arg.node, + getAssertion(localName), + ), + ); + }, + AssignmentExpression(path) { const left = path.get("left"); if (left.isIdentifier()) { diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/interop-loose/remap/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/interop-loose/remap/output.js index f313009c0a55..3c6fd2c99137 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/interop-loose/remap/output.js +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/interop-loose/remap/output.js @@ -2,10 +2,13 @@ exports.__esModule = true; exports.test = exports.f = exports.e = exports.c = exports.a = void 0; + +var _test; + var test = 2; exports.test = test; exports.test = test = 5; -exports.test = test = test + 1; +_test = test++, exports.test = test, _test; (function () { var test = 2; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/interop/remap/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/interop/remap/output.js index f091718ee4ee..dae3c0498d0d 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/interop/remap/output.js +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/interop/remap/output.js @@ -4,10 +4,13 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.test = exports.f = exports.e = exports.c = exports.a = void 0; + +var _test; + var test = 2; exports.test = test; exports.test = test = 5; -exports.test = test = test + 1; +_test = test++, exports.test = test, _test; (function () { var test = 2; 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 79d37c0932bf..4656571763d3 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 @@ -74,24 +74,30 @@ Bar && (Bar = (4, function () { _baz.Baz && (_baz.Baz = (4, function () { throw new Error('"' + "Baz" + '" is read-only.'); }())); -_foo.default = (_foo.default - 1, function () { + +_foo.default -= function () { throw new Error('"' + "Foo" + '" is read-only.'); -}()); -Bar = (Bar - 1, function () { +}(); + +Bar -= function () { throw new Error('"' + "Bar" + '" is read-only.'); -}()); -_baz.Baz = (_baz.Baz - 1, function () { +}(); + +_baz.Baz -= function () { throw new Error('"' + "Baz" + '" is read-only.'); -}()); -_foo.default = (_foo.default + 1, function () { +}(); + +_foo.default += function () { throw new Error('"' + "Foo" + '" is read-only.'); -}()); -Bar = (Bar + 1, function () { +}(); + +Bar += function () { throw new Error('"' + "Bar" + '" is read-only.'); -}()); -_baz.Baz = (_baz.Baz + 1, function () { +}(); + +_baz.Baz += function () { throw new Error('"' + "Baz" + '" is read-only.'); -}()); +}(); for (let _Foo in {}) { (function () { diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/module-exports/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/module-exports/output.js index 3e9254c59bf2..93a06b3ff979 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/module-exports/output.js +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/module-exports/output.js @@ -9,9 +9,9 @@ console.log(function () { throw new Error("The CommonJS '" + "exports" + "' variable is not available in ES6 modules." + "Consider setting setting sourceType:script or sourceType:unambiguous in your " + "Babel config for this file."); }().prop); -exports = function () { +exports += function () { throw new Error("The CommonJS '" + "exports" + "' variable is not available in ES6 modules." + "Consider setting setting sourceType:script or sourceType:unambiguous in your " + "Babel config for this file."); -}() + 1; +}(); exports = function () { throw new Error("The CommonJS '" + "exports" + "' variable is not available in ES6 modules." + "Consider setting setting sourceType:script or sourceType:unambiguous in your " + "Babel config for this file."); @@ -36,9 +36,9 @@ console.log(function () { throw new Error("The CommonJS '" + "module" + "' variable is not available in ES6 modules." + "Consider setting setting sourceType:script or sourceType:unambiguous in your " + "Babel config for this file."); }().exports); -module = function () { +module += function () { throw new Error("The CommonJS '" + "module" + "' variable is not available in ES6 modules." + "Consider setting setting sourceType:script or sourceType:unambiguous in your " + "Babel config for this file."); -}() + 1; +}(); module = function () { throw new Error("The CommonJS '" + "module" + "' variable is not available in ES6 modules." + "Consider setting setting sourceType:script or sourceType:unambiguous in your " + "Babel config for this file."); diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/regression/4462-T7565/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/regression/4462-T7565/output.js index ac7264e25d2f..cdd837001691 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/regression/4462-T7565/output.js +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/regression/4462-T7565/output.js @@ -9,5 +9,5 @@ var _yy; var yy = 0; exports.yy = yy; -var zz = (_yy = +yy, exports.yy = yy = _yy + 1, _yy); +var zz = (_yy = yy++, exports.yy = yy, _yy); exports.zz = zz; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/exec.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/exec.mjs new file mode 100644 index 000000000000..25f3ff97e281 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/exec.mjs @@ -0,0 +1,16 @@ +export let foo = 1n; + +export let bar = foo++; + +export let baz = ++bar; + +expect(foo).toBe(2n); +expect(bar).toBe(2n); +expect(baz).toBe(2n); + +export { foo as foofoo, bar as barbar }; +export { baz as bazbaz }; + +--foo; +bar--; +baz--; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/input.mjs new file mode 100644 index 000000000000..25f3ff97e281 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/input.mjs @@ -0,0 +1,16 @@ +export let foo = 1n; + +export let bar = foo++; + +export let baz = ++bar; + +expect(foo).toBe(2n); +expect(bar).toBe(2n); +expect(baz).toBe(2n); + +export { foo as foofoo, bar as barbar }; +export { baz as bazbaz }; + +--foo; +bar--; +baz--; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/options.json b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/options.json new file mode 100644 index 000000000000..4e7f49bb66b3 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/options.json @@ -0,0 +1,4 @@ +{ + "externalHelpers": false, + "minNodeVersion": "10.0.0" +} diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/output.js new file mode 100644 index 000000000000..c38fbf00f82c --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/bigint/output.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.foofoo = exports.foo = exports.bazbaz = exports.baz = exports.barbar = exports.bar = void 0; + +var _foo, _bar, _baz; + +let foo = 1n; +exports.foofoo = exports.foo = foo; +let bar = (_foo = foo++, exports.foofoo = exports.foo = foo, _foo); +exports.barbar = exports.bar = bar; +let baz = exports.barbar = exports.bar = ++bar; +exports.bazbaz = exports.baz = baz; +expect(foo).toBe(2n); +expect(bar).toBe(2n); +expect(baz).toBe(2n); +exports.foofoo = exports.foo = --foo; +_bar = bar--, exports.barbar = exports.bar = bar, _bar; +_baz = baz--, exports.bazbaz = exports.baz = baz, _baz; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/negative-suffix/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/negative-suffix/output.js index e6ac92435834..c25e5f37f5f7 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/negative-suffix/output.js +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/negative-suffix/output.js @@ -9,7 +9,7 @@ let diffLevel = 0; exports.diffLevel = diffLevel; function diff() { - if (!(exports.diffLevel = diffLevel = +diffLevel - 1)) { + if (!(exports.diffLevel = --diffLevel)) { console.log("hey"); } } diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/positive-suffix/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/positive-suffix/output.js index b78cd08a8e10..4b20ce4c45a3 100644 --- a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/positive-suffix/output.js +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/update-expression/positive-suffix/output.js @@ -9,7 +9,7 @@ let diffLevel = 0; exports.diffLevel = diffLevel; function diff() { - if (!(exports.diffLevel = diffLevel = +diffLevel + 1)) { + if (!(exports.diffLevel = ++diffLevel)) { console.log("hey"); } } diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/loose/remap/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/loose/remap/output.js index cf2cdf568afc..eefef7f4115c 100644 --- a/packages/babel-plugin-transform-modules-umd/test/fixtures/loose/remap/output.js +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/loose/remap/output.js @@ -15,10 +15,13 @@ _exports.__esModule = true; _exports.test = _exports.f = _exports.e = _exports.c = _exports.a = void 0; + + var _test; + var test = 2; _exports.test = test; _exports.test = test = 5; - _exports.test = test = test + 1; + _test = test++, _exports.test = test, _test; (function () { var test = 2; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/umd/remap/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/umd/remap/output.js index cf882a053b9b..050ce7ed078e 100644 --- a/packages/babel-plugin-transform-modules-umd/test/fixtures/umd/remap/output.js +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/umd/remap/output.js @@ -17,10 +17,13 @@ value: true }); _exports.test = _exports.f = _exports.e = _exports.c = _exports.a = void 0; + + var _test; + var test = 2; _exports.test = test; _exports.test = test = 5; - _exports.test = test = test + 1; + _test = test++, _exports.test = test, _test; (function () { var test = 2; From 2d49032ea680d96b9d63256d3edf32fd7d1570f7 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 10 Mar 2022 02:28:08 +0800 Subject: [PATCH 2/6] add `includeUpdateExpression` to avoid breaking change --- .../src/rewrite-live-references.ts | 1 + .../babel-helper-simple-access/src/index.ts | 81 ++++++++++++++++++- .../src/index.ts | 2 +- 3 files changed, 82 insertions(+), 2 deletions(-) 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 4bb8722b8a45..9ba5d3063182 100644 --- a/packages/babel-helper-module-transforms/src/rewrite-live-references.ts +++ b/packages/babel-helper-module-transforms/src/rewrite-live-references.ts @@ -112,6 +112,7 @@ export default function rewriteLiveReferences( programPath, // NOTE(logan): The 'Array.from' calls are to make this code with in loose mode. new Set([...Array.from(imported.keys()), ...Array.from(exported.keys())]), + false, ); // Rewrite reads/writes from imports and exports to have the correct behavior. diff --git a/packages/babel-helper-simple-access/src/index.ts b/packages/babel-helper-simple-access/src/index.ts index 23b720e9e477..9bf3383e1ecb 100644 --- a/packages/babel-helper-simple-access/src/index.ts +++ b/packages/babel-helper-simple-access/src/index.ts @@ -3,19 +3,98 @@ import { assignmentExpression, binaryExpression, cloneNode, + identifier, logicalExpression, + numericLiteral, + sequenceExpression, + unaryExpression, } from "@babel/types"; import type { NodePath } from "@babel/traverse"; -export default function simplifyAccess(path: NodePath, bindingNames) { +export default function simplifyAccess( + path: NodePath, + bindingNames, + includeUpdateExpression: boolean = true, +) { path.traverse(simpleAssignmentVisitor, { scope: path.scope, bindingNames, seen: new WeakSet(), + includeUpdateExpression, }); } const simpleAssignmentVisitor = { + UpdateExpression: { + exit(path) { + const { scope, bindingNames, includeUpdateExpression } = this; + if (!includeUpdateExpression) { + return; + } + + const arg = path.get("argument"); + if (!arg.isIdentifier()) return; + const localName = arg.node.name; + + if (!bindingNames.has(localName)) return; + + // redeclared in this scope + if (scope.getBinding(localName) !== path.scope.getBinding(localName)) { + return; + } + + if ( + path.parentPath.isExpressionStatement() && + !path.isCompletionRecord() + ) { + // ++i => (i += 1); + const operator = path.node.operator == "++" ? "+=" : "-="; + path.replaceWith( + assignmentExpression(operator, arg.node, numericLiteral(1)), + ); + } else if (path.node.prefix) { + // ++i => (i = (+i) + 1); + path.replaceWith( + assignmentExpression( + "=", + identifier(localName), + binaryExpression( + path.node.operator[0], + unaryExpression("+", arg.node), + numericLiteral(1), + ), + ), + ); + } else { + const old = path.scope.generateUidIdentifierBasedOnNode( + arg.node, + "old", + ); + const varName = old.name; + path.scope.push({ id: old }); + + const binary = binaryExpression( + path.node.operator[0], + identifier(varName), + numericLiteral(1), + ); + + // i++ => (_old = (+i), i = _old + 1, _old) + path.replaceWith( + sequenceExpression([ + assignmentExpression( + "=", + identifier(varName), + unaryExpression("+", arg.node), + ), + assignmentExpression("=", cloneNode(arg.node), binary), + identifier(varName), + ]), + ); + } + }, + }, + AssignmentExpression: { exit(path) { const { scope, seen, bindingNames } = this; diff --git a/packages/babel-plugin-transform-modules-commonjs/src/index.ts b/packages/babel-plugin-transform-modules-commonjs/src/index.ts index ded511bba2ad..b1a43c915fad 100644 --- a/packages/babel-plugin-transform-modules-commonjs/src/index.ts +++ b/packages/babel-plugin-transform-modules-commonjs/src/index.ts @@ -183,7 +183,7 @@ export default declare((api, options) => { // These objects are specific to CommonJS and are not available in // real ES6 implementations. if (!allowCommonJSExports) { - simplifyAccess(path, new Set(["module", "exports"])); + simplifyAccess(path, new Set(["module", "exports"]), false); path.traverse(moduleExportsVisitor, { scope: path.scope, }); From fec2ff56ef28abc6e265ffe797878e537acb6529 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 10 Mar 2022 02:31:37 +0800 Subject: [PATCH 3/6] chore: add comment --- packages/babel-helper-simple-access/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/babel-helper-simple-access/src/index.ts b/packages/babel-helper-simple-access/src/index.ts index 9bf3383e1ecb..623fa14cd123 100644 --- a/packages/babel-helper-simple-access/src/index.ts +++ b/packages/babel-helper-simple-access/src/index.ts @@ -14,6 +14,7 @@ import type { NodePath } from "@babel/traverse"; export default function simplifyAccess( path: NodePath, bindingNames, + // TODO(Babel 8): Remove this includeUpdateExpression: boolean = true, ) { path.traverse(simpleAssignmentVisitor, { From f63fc73a60c058954095ba8e1aea8579ebc47c84 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 10 Mar 2022 02:42:37 +0800 Subject: [PATCH 4/6] chore: revert redundant change --- packages/babel-plugin-transform-modules-commonjs/src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/babel-plugin-transform-modules-commonjs/src/index.ts b/packages/babel-plugin-transform-modules-commonjs/src/index.ts index b1a43c915fad..452da2203629 100644 --- a/packages/babel-plugin-transform-modules-commonjs/src/index.ts +++ b/packages/babel-plugin-transform-modules-commonjs/src/index.ts @@ -81,8 +81,7 @@ export default declare((api, options) => { (path.parentPath.isObjectProperty({ value: path.node }) && path.parentPath.parentPath.isObjectPattern()) || path.parentPath.isAssignmentExpression({ left: path.node }) || - path.isAssignmentExpression({ left: path.node }) || - path.parentPath.isUpdateExpression() + path.isAssignmentExpression({ left: path.node }) ) { return; } From d8735dfc113243d2794de8d8c63899b4a0c98238 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 10 Mar 2022 10:10:41 +0800 Subject: [PATCH 5/6] Add test case for simplifyAccess --- .../babel-helper-simple-access/test/index.js | 181 ++++++++++++++++++ .../test/package.json | 1 + 2 files changed, 182 insertions(+) create mode 100644 packages/babel-helper-simple-access/test/index.js create mode 100644 packages/babel-helper-simple-access/test/package.json diff --git a/packages/babel-helper-simple-access/test/index.js b/packages/babel-helper-simple-access/test/index.js new file mode 100644 index 000000000000..7514f1d7917b --- /dev/null +++ b/packages/babel-helper-simple-access/test/index.js @@ -0,0 +1,181 @@ +import * as babel from "@babel/core"; +import simplifyAccess from "../lib/index.js"; + +const plugin = (_api, options) => { + const { includeUpdateExpression, bindingNames } = options; + + return { + visitor: { + Program(path) { + simplifyAccess.default( + path, + new Set(bindingNames), + includeUpdateExpression, + ); + }, + }, + }; +}; + +it("simplifyAccess with default config", function () { + const code = ` + let a = foo++; + a = ++foo; + foo++; + ++foo; + ++a; + a++; + foo = a++; + foo = ++a; + + let b = bar--; + b = --bar; + bar--; + --bar; + --b; + b--; + bar = b--; + bar = --b; + + let c = baz += 1; + baz += 1; + c += 1; + + function f() { + let foo = 1; + let a = foo++; + a = ++foo; + foo++; + ++foo; + ++a; + a++; + foo = a++; + foo = ++a; + } +`; + + const output = babel.transformSync(code, { + configFile: false, + ast: false, + plugins: [[plugin, { bindingNames: ["foo", "bar", "baz"] }]], + }).code; + + expect(output).toMatchInlineSnapshot(` + "var _foo, _bar; + + let a = (_foo = +foo, foo = _foo + 1, _foo); + a = foo = +foo + 1; + foo = foo + 1; + foo = foo + 1; + ++a; + a++; + foo = a++; + foo = ++a; + let b = (_bar = +bar, bar = _bar - 1, _bar); + b = bar = +bar - 1; + bar = bar - 1; + bar = bar - 1; + --b; + b--; + bar = b--; + bar = --b; + let c = baz = baz + 1; + baz = baz + 1; + c += 1; + + function f() { + let foo = 1; + let a = foo++; + a = ++foo; + foo++; + ++foo; + ++a; + a++; + foo = a++; + foo = ++a; + }" + `); +}); + +it("simplifyAccess with includeUpdateExpression=false", function () { + const code = ` + let a = foo++; + a = ++foo; + foo++; + ++foo; + ++a; + a++; + foo = a++; + foo = ++a; + + let b = bar--; + b = --bar; + bar--; + --bar; + --b; + b--; + bar = b--; + bar = --b; + + let c = baz += 1; + baz += 1; + c += 1; + + function f() { + let foo = 1; + let a = foo++; + a = ++foo; + foo++; + ++foo; + ++a; + a++; + foo = a++; + foo = ++a; + } +`; + + const output = babel.transformSync(code, { + configFile: false, + ast: false, + plugins: [ + [ + plugin, + { includeUpdateExpression: false, bindingNames: ["foo", "bar", "baz"] }, + ], + ], + }).code; + + expect(output).toMatchInlineSnapshot(` + "let a = foo++; + a = ++foo; + foo++; + ++foo; + ++a; + a++; + foo = a++; + foo = ++a; + let b = bar--; + b = --bar; + bar--; + --bar; + --b; + b--; + bar = b--; + bar = --b; + let c = baz = baz + 1; + baz = baz + 1; + c += 1; + + function f() { + let foo = 1; + let a = foo++; + a = ++foo; + foo++; + ++foo; + ++a; + a++; + foo = a++; + foo = ++a; + }" +`); +}); diff --git a/packages/babel-helper-simple-access/test/package.json b/packages/babel-helper-simple-access/test/package.json new file mode 100644 index 000000000000..5ffd9800b97c --- /dev/null +++ b/packages/babel-helper-simple-access/test/package.json @@ -0,0 +1 @@ +{ "type": "module" } From b530c7ac4e4a42ec3bdcca0fde0286144b5094bb Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 10 Mar 2022 11:18:03 +0800 Subject: [PATCH 6/6] chore: add comment --- packages/babel-helper-simple-access/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/babel-helper-simple-access/src/index.ts b/packages/babel-helper-simple-access/src/index.ts index 623fa14cd123..cdb5880752e8 100644 --- a/packages/babel-helper-simple-access/src/index.ts +++ b/packages/babel-helper-simple-access/src/index.ts @@ -26,6 +26,7 @@ export default function simplifyAccess( } const simpleAssignmentVisitor = { + // TODO(Babel 8): Remove UpdateExpression UpdateExpression: { exit(path) { const { scope, bindingNames, includeUpdateExpression } = this;