diff --git a/CHANGELOG.md b/CHANGELOG.md index 9da1639a8124..1a0ecd23e805 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,71 @@ This file contains the changelog starting from v7.15.0. +## v7.27.1 (2025-04-30) + +#### :eyeglasses: Spec Compliance +* `babel-parser` + * [#17254](https://github.com/babel/babel/pull/17254) Allow `using of` as lexical declaration within for ([@JLHwung](https://github.com/JLHwung)) + * [#17230](https://github.com/babel/babel/pull/17230) Disallow get/set in TSPropertySignature ([@JLHwung](https://github.com/JLHwung)) +* `babel-parser`, `babel-types` + * [#17193](https://github.com/babel/babel/pull/17193) Stricter TSImportType options parsing ([@JLHwung](https://github.com/JLHwung)) + +#### :bug: Bug Fix +* `babel-plugin-proposal-destructuring-private`, `babel-plugin-proposal-do-expressions`, `babel-traverse` + * [#17137](https://github.com/babel/babel/pull/17137) fix: do expressions should allow early exit ([@kermanx](https://github.com/kermanx)) +* `babel-helper-wrap-function`, `babel-plugin-transform-async-to-generator` + * [#17251](https://github.com/babel/babel/pull/17251) Fix: propagate argument evaluation errors through async promise chain ([@magic-akari](https://github.com/magic-akari)) +* `babel-helper-remap-async-to-generator`, `babel-plugin-transform-async-to-generator` + * [#17231](https://github.com/babel/babel/pull/17231) fix apply()/call() annotated as pure ([@Lacsw](https://github.com/Lacsw)) +* `babel-helper-fixtures`, `babel-parser` + * [#17233](https://github.com/babel/babel/pull/17233) Create ChainExpression within TSInstantiationExpression ([@JLHwung](https://github.com/JLHwung)) +* `babel-generator`, `babel-parser` + * [#17226](https://github.com/babel/babel/pull/17226) Fill optional AST properties when both estree and typescript parser plugin are enabled (Part 2) ([@JLHwung](https://github.com/JLHwung)) +* `babel-parser` + * [#17224](https://github.com/babel/babel/pull/17224) Fill optional AST properties when both estree and typescript parser plugin are enabled (Part 1) ([@JLHwung](https://github.com/JLHwung)) + * [#17080](https://github.com/babel/babel/pull/17080) Fix start of TSParameterProperty ([@JLHwung](https://github.com/JLHwung)) +* `babel-compat-data`, `babel-preset-env` + * [#17228](https://github.com/babel/babel/pull/17228) Update firefox bugfix compat data ([@JLHwung](https://github.com/JLHwung)) +* `babel-traverse` + * [#17156](https://github.com/babel/babel/pull/17156) fix: Objects and arrays with multiple references should not be evaluated ([@liuxingbaoyu](https://github.com/liuxingbaoyu)) +* `babel-generator` + * [#17216](https://github.com/babel/babel/pull/17216) Fix: support const type parameter in generator ([@JLHwung](https://github.com/JLHwung)) + +#### :nail_care: Polish +* `babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining`, `babel-plugin-proposal-decorators`, `babel-plugin-transform-arrow-functions`, `babel-plugin-transform-class-properties`, `babel-plugin-transform-destructuring`, `babel-plugin-transform-object-rest-spread`, `babel-plugin-transform-optional-chaining`, `babel-plugin-transform-parameters`, `babel-traverse` + * [#17221](https://github.com/babel/babel/pull/17221) Reduce generated names size for the 10th-11th ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) + +#### :house: Internal +* `babel-runtime-corejs2`, `babel-runtime-corejs3`, `babel-runtime` + * [#17263](https://github.com/babel/babel/pull/17263) Remove unused `regenerator-runtime` dep in `@babel/runtime` ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) +* `babel-compat-data`, `babel-preset-env` + * [#17256](https://github.com/babel/babel/pull/17256) Tune plugin compat data ([@JLHwung](https://github.com/JLHwung)) +* `babel-compat-data`, `babel-standalone` + * [#17236](https://github.com/babel/babel/pull/17236) migrate babel-compat-data build script to mjs ([@JLHwung](https://github.com/JLHwung)) +* Other + * [#17232](https://github.com/babel/babel/pull/17232) Bump typescript-eslint to 8.29.1 ([@JLHwung](https://github.com/JLHwung)) + * [#17219](https://github.com/babel/babel/pull/17219) test: add basic typescript-eslint integration tests ([@JLHwung](https://github.com/JLHwung)) + * [#17205](https://github.com/babel/babel/pull/17205) Inline regenerator in the relevant packages ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) +* `babel-register` + * [#16844](https://github.com/babel/babel/pull/16844) Migrate `@babel/register` to cts ([@liuxingbaoyu](https://github.com/liuxingbaoyu)) +* `babel-cli`, `babel-compat-data`, `babel-core`, `babel-generator`, `babel-helper-compilation-targets`, `babel-helper-fixtures`, `babel-helper-module-imports`, `babel-helper-module-transforms`, `babel-helper-plugin-test-runner`, `babel-helper-transform-fixture-test-runner`, `babel-helpers`, `babel-node`, `babel-parser`, `babel-plugin-transform-modules-amd`, `babel-plugin-transform-modules-commonjs`, `babel-plugin-transform-modules-systemjs`, `babel-plugin-transform-modules-umd`, `babel-plugin-transform-react-display-name`, `babel-plugin-transform-regenerator`, `babel-plugin-transform-runtime`, `babel-plugin-transform-typeof-symbol`, `babel-plugin-transform-typescript`, `babel-preset-env`, `babel-register`, `babel-standalone`, `babel-types` + * [#17207](https://github.com/babel/babel/pull/17207) Enforce node protocol import ([@JLHwung](https://github.com/JLHwung)) +* `babel-plugin-transform-regenerator` + * [#17205](https://github.com/babel/babel/pull/17205) Inline regenerator in the relevant packages ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) + * [#17205](https://github.com/babel/babel/pull/17205) Inline regenerator in the relevant packages ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) +* `babel-helpers`, `babel-plugin-transform-async-generator-functions`, `babel-plugin-transform-regenerator`, `babel-preset-env`, `babel-runtime-corejs3` + * [#17205](https://github.com/babel/babel/pull/17205) Inline regenerator in the relevant packages ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) +* `babel-helpers`, `babel-plugin-transform-regenerator` + * [#17205](https://github.com/babel/babel/pull/17205) Inline regenerator in the relevant packages ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) + * [#17205](https://github.com/babel/babel/pull/17205) Inline regenerator in the relevant packages ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) +* `babel-helpers` + * [#17205](https://github.com/babel/babel/pull/17205) Inline regenerator in the relevant packages ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo)) + +#### :microscope: Output optimization +* `babel-helpers`, `babel-plugin-transform-modules-commonjs`, `babel-runtime-corejs3` + * [#16538](https://github.com/babel/babel/pull/16538) Reduce `interopRequireWildcard` size ([@liuxingbaoyu](https://github.com/liuxingbaoyu)) +* `babel-helpers`, `babel-plugin-transform-async-generator-functions`, `babel-plugin-transform-regenerator`, `babel-preset-env`, `babel-runtime-corejs3` + * [#17213](https://github.com/babel/babel/pull/17213) Reduce `regeneratorRuntime` size ([@liuxingbaoyu](https://github.com/liuxingbaoyu)) ## v7.27.0 (2025-03-24) #### :eyeglasses: Spec Compliance diff --git a/Gulpfile.mjs b/Gulpfile.mjs index 1f1c0805f846..93567d62ef68 100644 --- a/Gulpfile.mjs +++ b/Gulpfile.mjs @@ -410,6 +410,9 @@ function buildRollup(packages, buildStandalone) { getBabelOutputPlugin({ configFile: false, babelrc: false, + generatorOpts: { + compact: false, + }, plugins: [ function babelPluginInlineConstNumericObjects({ types: t }) { return { diff --git a/Makefile b/Makefile index f59e1b35de68..e5ebc51294e9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ FLOW_COMMIT = b7f56844ec194c8901a18d11e6b356dd56b3bdeb -TEST262_COMMIT = cba890eef02121251b7f11eb890b0202edf56d6f +TEST262_COMMIT = 27622d764767dcb3778784884022c2c7de5769b8 TYPESCRIPT_COMMIT = afc463980f55d634c56dfedc6852f6f46f596621 SOURCES = packages codemods eslint diff --git a/benchmark/babel-cli/print-usage/bench.mjs b/benchmark/babel-cli/print-usage/bench.mjs new file mode 100644 index 000000000000..31c1c7049321 --- /dev/null +++ b/benchmark/babel-cli/print-usage/bench.mjs @@ -0,0 +1,52 @@ +import Benchmark from "benchmark"; +import { report } from "../../util.mjs"; +import { execFileSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; +import { readFileSync, writeFileSync } from "node:fs"; + +const suite = new Benchmark.Suite(); + +// Modify `@babel/cli`'s package.json such that we can run ./bin/babel.js directly from the monorepo +function changeBabelCliModuleType() { + const packageJSONPath = fileURLToPath( + import.meta.resolve("@babel/cli/package.json") + ); + const content = readFileSync(packageJSONPath, "utf-8"); + const patchedContent = content.replace( + `"type": "module"`, + `"type": "commonjs"` + ); + writeFileSync(packageJSONPath, patchedContent); + return () => writeFileSync(packageJSONPath, content); +} + +const revert = changeBabelCliModuleType(); +function benchCases( + name, + implementationPackageJSONSpecifier, + binaryRelativePath +) { + const binaryPath = fileURLToPath( + new URL( + binaryRelativePath, + import.meta.resolve(implementationPackageJSONSpecifier) + ) + ); + suite.add( + `${name}`, + () => { + execFileSync(binaryPath, ["--help"]); + }, + { + minSamples: 1, + } + ); +} + +benchCases("baseline", "@babel-baseline/cli/package.json", "./bin/babel.js"); +benchCases("current", "@babel/cli/package.json", "./bin/babel.js"); +benchCases("current-esm", "@babel/cli/package.json", "./bin/babel.mjs"); + +suite.on("cycle", report).run(); + +revert(); diff --git a/benchmark/package.json b/benchmark/package.json index 2a2457fdd1bb..d2dce4c4a220 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -3,6 +3,7 @@ "private": true, "type": "module", "devDependencies": { + "@babel-baseline/cli": "npm:@babel/cli@7.27.1", "@babel-baseline/core": "npm:@babel/core@7.24.4", "@babel-baseline/generator": "npm:@babel/generator@7.24.4", "@babel-baseline/helper-compilation-targets": "npm:@babel/helper-compilation-targets@7.23.6", @@ -10,6 +11,7 @@ "@babel-baseline/parser": "npm:@babel/parser@7.24.4", "@babel-baseline/traverse": "npm:@babel/traverse@7.24.1", "@babel-baseline/types": "npm:@babel/types@7.24.0", + "@babel/cli": "workspace:^", "@babel/core": "workspace:^", "@babel/generator": "workspace:^", "@babel/helper-compilation-targets": "workspace:^", @@ -23,5 +25,5 @@ "@babel/types": "workspace:^", "benchmark": "^2.1.4" }, - "version": "7.27.1" + "version": "7.27.2" } diff --git a/package.json b/package.json index 013777663a48..0e8c59d0b58c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "babel", - "version": "7.27.1", + "version": "7.27.2", "version_babel8": "8.0.0-alpha.17", "private": true, "type": "commonjs", diff --git a/packages/babel-cli/bin/babel.js b/packages/babel-cli/bin/babel.js index 7c227455f1df..025e82c31cf2 100755 --- a/packages/babel-cli/bin/babel.js +++ b/packages/babel-cli/bin/babel.js @@ -1,3 +1,8 @@ #!/usr/bin/env node +/* eslint-disable unicorn/prefer-node-protocol */ + +// Enable Node compile cache to speed up initialization +const mod = require("module"); +if (mod.enableCompileCache != null) mod.enableCompileCache(); require("../lib/babel"); diff --git a/packages/babel-cli/bin/babel.mjs b/packages/babel-cli/bin/babel.mjs index 9ad45a8cc57b..c292543e674c 100755 --- a/packages/babel-cli/bin/babel.mjs +++ b/packages/babel-cli/bin/babel.mjs @@ -1,3 +1,6 @@ #!/usr/bin/env node +import mod from "node:module"; import "../lib/babel/index.js"; + +mod.enableCompileCache?.(); diff --git a/packages/babel-cli/package.json b/packages/babel-cli/package.json index e903a4ec700a..6f47baa06793 100644 --- a/packages/babel-cli/package.json +++ b/packages/babel-cli/package.json @@ -1,6 +1,6 @@ { "name": "@babel/cli", - "version": "7.27.1", + "version": "7.27.2", "description": "Babel command line.", "author": "The Babel Team (https://babel.dev/team)", "homepage": "https://babel.dev/docs/en/next/babel-cli", diff --git a/packages/babel-compat-data/native-modules.js b/packages/babel-compat-data/native-modules.js index 8e97da4bcfde..f8c25fa37c72 100644 --- a/packages/babel-compat-data/native-modules.js +++ b/packages/babel-compat-data/native-modules.js @@ -1 +1,2 @@ +// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly module.exports = require("./data/native-modules.json"); diff --git a/packages/babel-compat-data/overlapping-plugins.js b/packages/babel-compat-data/overlapping-plugins.js index 88242e467810..0dd35f1573f9 100644 --- a/packages/babel-compat-data/overlapping-plugins.js +++ b/packages/babel-compat-data/overlapping-plugins.js @@ -1 +1,2 @@ +// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly module.exports = require("./data/overlapping-plugins.json"); diff --git a/packages/babel-compat-data/package.json b/packages/babel-compat-data/package.json index 64fed8ebf766..13ef94bdc6ac 100644 --- a/packages/babel-compat-data/package.json +++ b/packages/babel-compat-data/package.json @@ -1,6 +1,6 @@ { "name": "@babel/compat-data", - "version": "7.27.1", + "version": "7.27.2", "author": "The Babel Team (https://babel.dev/team)", "license": "MIT", "description": "The compat-data to determine required Babel plugins", @@ -16,25 +16,34 @@ "BABEL_8_BREAKING": [ { "exports": { - "./plugins": "./plugins.js", - "./native-modules": "./native-modules.js", - "./overlapping-plugins": "./overlapping-plugins.js", - "./plugin-bugfixes": "./plugin-bugfixes.js" + "./plugins": "./data/plugins.json", + "./native-modules": "./data/native-modules.json", + "./overlapping-plugins": "./data/overlapping-plugins.json", + "./plugin-bugfixes": "./data/plugin-bugfixes.json" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, - null + { + "exports": { + "./plugins": "./plugins.js", + "./native-modules": "./native-modules.js", + "./corejs2-built-ins": "./corejs2-built-ins.js", + "./corejs3-shipped-proposals": "./corejs3-shipped-proposals.js", + "./overlapping-plugins": "./overlapping-plugins.js", + "./plugin-bugfixes": "./plugin-bugfixes.js" + } + } ] }, "exports": { - "./plugins": "./plugins.js", - "./native-modules": "./native-modules.js", - "./corejs2-built-ins": "./corejs2-built-ins.js", - "./corejs3-shipped-proposals": "./corejs3-shipped-proposals.js", - "./overlapping-plugins": "./overlapping-plugins.js", - "./plugin-bugfixes": "./plugin-bugfixes.js" + "./plugins": "./data/plugins.json", + "./native-modules": "./data/native-modules.json", + "./corejs2-built-ins": "./data/corejs2-built-ins.json", + "./corejs3-shipped-proposals": "./data/corejs3-shipped-proposals.json", + "./overlapping-plugins": "./data/overlapping-plugins.json", + "./plugin-bugfixes": "./data/plugin-bugfixes.json" }, "scripts": { "build-data": "./scripts/download-compat-table.sh && node ./scripts/build-data.mjs && node ./scripts/build-modules-support.mjs && node ./scripts/build-bugfixes-targets.mjs" diff --git a/packages/babel-compat-data/plugin-bugfixes.js b/packages/babel-compat-data/plugin-bugfixes.js index f390181a6302..9aaf36417013 100644 --- a/packages/babel-compat-data/plugin-bugfixes.js +++ b/packages/babel-compat-data/plugin-bugfixes.js @@ -1 +1,2 @@ +// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly module.exports = require("./data/plugin-bugfixes.json"); diff --git a/packages/babel-compat-data/plugins.js b/packages/babel-compat-data/plugins.js index 42646edce6dc..b191017be6a8 100644 --- a/packages/babel-compat-data/plugins.js +++ b/packages/babel-compat-data/plugins.js @@ -1 +1,2 @@ +// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly module.exports = require("./data/plugins.json"); diff --git a/packages/babel-helper-compilation-targets/package.json b/packages/babel-helper-compilation-targets/package.json index 22c104be5928..b00c258ea6d7 100644 --- a/packages/babel-helper-compilation-targets/package.json +++ b/packages/babel-helper-compilation-targets/package.json @@ -1,6 +1,6 @@ { "name": "@babel/helper-compilation-targets", - "version": "7.27.1", + "version": "7.27.2", "author": "The Babel Team (https://babel.dev/team)", "license": "MIT", "description": "Helper functions on Babel compilation targets", diff --git a/packages/babel-helper-compilation-targets/src/filter-items.ts b/packages/babel-helper-compilation-targets/src/filter-items.ts index c74337d3afe5..cf418e89f51d 100644 --- a/packages/babel-helper-compilation-targets/src/filter-items.ts +++ b/packages/babel-helper-compilation-targets/src/filter-items.ts @@ -1,6 +1,6 @@ import semver from "semver"; -import pluginsCompatData from "@babel/compat-data/plugins"; +import pluginsCompatData from "@babel/compat-data/plugins" with { type: "json" }; import type { Targets } from "./types.ts"; import { diff --git a/packages/babel-helper-compilation-targets/src/index.ts b/packages/babel-helper-compilation-targets/src/index.ts index e5edb6295616..f6ef756ca469 100644 --- a/packages/babel-helper-compilation-targets/src/index.ts +++ b/packages/babel-helper-compilation-targets/src/index.ts @@ -1,6 +1,6 @@ import browserslist from "browserslist"; import { findSuggestion } from "@babel/helper-validator-option"; -import browserModulesData from "@babel/compat-data/native-modules"; +import browserModulesData from "@babel/compat-data/native-modules" with { type: "json" }; import LruCache from "lru-cache"; import { @@ -20,7 +20,7 @@ import type { Browsers, BrowserslistBrowserName, TargetsTuple, -} from "./types.ts"; +} from "./types.d.ts"; export type { Target, Targets, InputTargets }; diff --git a/packages/babel-parser/bin/babel-parser.js b/packages/babel-parser/bin/babel-parser.js index f59f1ec6019a..4808c5ee86f7 100755 --- a/packages/babel-parser/bin/babel-parser.js +++ b/packages/babel-parser/bin/babel-parser.js @@ -1,8 +1,8 @@ #!/usr/bin/env node -/* eslint no-var: 0 */ +/* eslint-disable no-var, unicorn/prefer-node-protocol */ var parser = require(".."); -var fs = require("node:fs"); +var fs = require("fs"); var filename = process.argv[2]; if (!filename) { diff --git a/packages/babel-parser/package.json b/packages/babel-parser/package.json index 80781fbdb8ac..ba2b1758ff08 100644 --- a/packages/babel-parser/package.json +++ b/packages/babel-parser/package.json @@ -1,6 +1,6 @@ { "name": "@babel/parser", - "version": "7.27.1", + "version": "7.27.2", "description": "A JavaScript parser", "author": "The Babel Team (https://babel.dev/team)", "homepage": "https://babel.dev/docs/en/next/babel-parser", diff --git a/packages/babel-parser/src/plugins/typescript/index.ts b/packages/babel-parser/src/plugins/typescript/index.ts index d7adda5180f9..aae3cbc09ea5 100644 --- a/packages/babel-parser/src/plugins/typescript/index.ts +++ b/packages/babel-parser/src/plugins/typescript/index.ts @@ -3553,7 +3553,10 @@ export default (superClass: ClassWithMixin) => ) { if (node.type === "TSDeclareMethod") return; // This happens when using the "estree" plugin. - if ((node as N.Node).type === "MethodDefinition" && node.body == null) { + if ( + (node as N.Node).type === "MethodDefinition" && + (node as unknown as N.EstreeMethodDefinition).value.body == null + ) { return; } diff --git a/packages/babel-parser/test/fixtures/misc/regression/issue-17290/input.js b/packages/babel-parser/test/fixtures/misc/regression/issue-17290/input.js new file mode 100644 index 000000000000..90f93ca30fdb --- /dev/null +++ b/packages/babel-parser/test/fixtures/misc/regression/issue-17290/input.js @@ -0,0 +1,9 @@ +class Reflection { + get attributes() { + return this.#parseAttributes() + } + + #parseAttributes() { + 111; + } +} diff --git a/packages/babel-parser/test/fixtures/misc/regression/issue-17290/options.json b/packages/babel-parser/test/fixtures/misc/regression/issue-17290/options.json new file mode 100644 index 000000000000..fd101f30897e --- /dev/null +++ b/packages/babel-parser/test/fixtures/misc/regression/issue-17290/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "estree", + { + "classFeatures": true + } + ], + "typescript" + ] +} diff --git a/packages/babel-parser/test/fixtures/misc/regression/issue-17290/output.json b/packages/babel-parser/test/fixtures/misc/regression/issue-17290/output.json new file mode 100644 index 000000000000..1d9ec311a6f4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/misc/regression/issue-17290/output.json @@ -0,0 +1,133 @@ +{ + "type": "File", + "start":0,"end":117,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":117,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":117,"loc":{"start":{"line":1,"column":0},"end":{"line":9,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":16,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":16},"identifierName":"Reflection"}, + "name": "Reflection", + "decorators": [], + "optional": false + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":17,"end":117,"loc":{"start":{"line":1,"column":17},"end":{"line":9,"column":1}}, + "body": [ + { + "type": "MethodDefinition", + "start":21,"end":78,"loc":{"start":{"line":2,"column":2},"end":{"line":4,"column":3}}, + "static": false, + "key": { + "type": "Identifier", + "start":25,"end":35,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":16},"identifierName":"attributes"}, + "name": "attributes", + "decorators": [], + "optional": false + }, + "computed": false, + "kind": "get", + "value": { + "type": "FunctionExpression", + "start":35,"end":78,"loc":{"start":{"line":2,"column":16},"end":{"line":4,"column":3}}, + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":38,"end":78,"loc":{"start":{"line":2,"column":19},"end":{"line":4,"column":3}}, + "body": [ + { + "type": "ReturnStatement", + "start":44,"end":74,"loc":{"start":{"line":3,"column":4},"end":{"line":3,"column":34}}, + "argument": { + "type": "CallExpression", + "start":51,"end":74,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":34}}, + "callee": { + "type": "MemberExpression", + "start":51,"end":72,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":32}}, + "object": { + "type": "ThisExpression", + "start":51,"end":55,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":15}} + }, + "computed": false, + "property": { + "type": "PrivateIdentifier", + "start":56,"end":72,"loc":{"start":{"line":3,"column":16},"end":{"line":3,"column":32}}, + "name": "parseAttributes" + }, + "optional": false + }, + "arguments": [], + "optional": false + } + } + ] + }, + "declare": false + }, + "decorators": [], + "override": false, + "optional": false + }, + { + "type": "MethodDefinition", + "start":82,"end":115,"loc":{"start":{"line":6,"column":2},"end":{"line":8,"column":3}}, + "static": false, + "key": { + "type": "PrivateIdentifier", + "start":82,"end":98,"loc":{"start":{"line":6,"column":2},"end":{"line":6,"column":18}}, + "name": "parseAttributes" + }, + "kind": "method", + "value": { + "type": "FunctionExpression", + "start":98,"end":115,"loc":{"start":{"line":6,"column":18},"end":{"line":8,"column":3}}, + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":101,"end":115,"loc":{"start":{"line":6,"column":21},"end":{"line":8,"column":3}}, + "body": [ + { + "type": "ExpressionStatement", + "start":107,"end":111,"loc":{"start":{"line":7,"column":4},"end":{"line":7,"column":8}}, + "expression": { + "type": "Literal", + "start":107,"end":110,"loc":{"start":{"line":7,"column":4},"end":{"line":7,"column":7}}, + "value": 111, + "raw": "111" + } + } + ] + }, + "declare": false + }, + "computed": false, + "decorators": [], + "override": false, + "optional": false + } + ] + }, + "abstract": false, + "declare": false, + "decorators": [], + "implements": [] + } + ] + } +} diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/export-empty-name/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/export-empty-name/input.mjs new file mode 100644 index 000000000000..9b774a069ecb --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/export-empty-name/input.mjs @@ -0,0 +1,3 @@ +const a = "foo"; + +export { a as "" }; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/export-empty-name/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/export-empty-name/output.js new file mode 100644 index 000000000000..7a31e7ac53a3 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/misc/export-empty-name/output.js @@ -0,0 +1,7 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports[""] = void 0; +const a = exports[""] = "foo"; diff --git a/packages/babel-plugin-transform-object-rest-spread/package.json b/packages/babel-plugin-transform-object-rest-spread/package.json index c7036cb74871..d6da7c7b6f2e 100644 --- a/packages/babel-plugin-transform-object-rest-spread/package.json +++ b/packages/babel-plugin-transform-object-rest-spread/package.json @@ -1,6 +1,6 @@ { "name": "@babel/plugin-transform-object-rest-spread", - "version": "7.27.1", + "version": "7.27.2", "description": "Compile object rest and spread to ES5", "repository": { "type": "git", @@ -19,6 +19,7 @@ "dependencies": { "@babel/helper-compilation-targets": "workspace:^", "@babel/helper-plugin-utils": "workspace:^", + "@babel/plugin-transform-destructuring": "workspace:^", "@babel/plugin-transform-parameters": "workspace:^" }, "peerDependencies": { diff --git a/packages/babel-plugin-transform-object-rest-spread/src/index.ts b/packages/babel-plugin-transform-object-rest-spread/src/index.ts index ac21306c4038..6cf60d2b2bfb 100644 --- a/packages/babel-plugin-transform-object-rest-spread/src/index.ts +++ b/packages/babel-plugin-transform-object-rest-spread/src/index.ts @@ -5,8 +5,8 @@ import { convertFunctionParams } from "@babel/plugin-transform-parameters"; import { isRequired } from "@babel/helper-compilation-targets"; import shouldStoreRHSInTemporaryVariable from "./shouldStoreRHSInTemporaryVariable.ts"; import compatData from "./compat-data.ts"; +import { unshiftForXStatementBody } from "@babel/plugin-transform-destructuring"; -const { isAssignmentPattern, isObjectProperty } = t; // @babel/types <=7.3.3 counts FOO as referenced in var { x: FOO }. // We need to detect this bug to know if "unused" means 0 or 1 references. if (!process.env.BABEL_8_BREAKING) { @@ -18,7 +18,6 @@ if (!process.env.BABEL_8_BREAKING) { var ZERO_REFS = t.isReferenced(node, property, pattern) ? 1 : 0; } -type Param = NodePath; export interface Options { useBuiltIns?: boolean; loose?: boolean; @@ -51,42 +50,50 @@ export default declare((api, opts: Options) => { : file.addHelper("extends"); } - function hasRestElement(path: Param) { - let foundRestElement = false; - visitRestElements(path, restElement => { - foundRestElement = true; - restElement.stop(); - }); - return foundRestElement; + function* iterateObjectRestElement( + path: NodePath, + ): Generator> { + switch (path.type) { + case "ArrayPattern": + for (const elementPath of path.get("elements")) { + if (elementPath.isRestElement()) { + yield* iterateObjectRestElement(elementPath.get("argument")); + } else { + yield* iterateObjectRestElement(elementPath); + } + } + break; + case "ObjectPattern": + for (const propertyPath of path.get("properties")) { + if (propertyPath.isRestElement()) { + yield propertyPath; + } else { + yield* iterateObjectRestElement( + propertyPath.get("value") as NodePath, + ); + } + } + break; + case "AssignmentPattern": + yield* iterateObjectRestElement(path.get("left")); + break; + default: + break; + } } - function hasObjectPatternRestElement(path: NodePath): boolean { - let foundRestElement = false; - visitRestElements(path, restElement => { - if (restElement.parentPath.isObjectPattern()) { - foundRestElement = true; - restElement.stop(); - } - }); - return foundRestElement; + function hasObjectRestElement(path: NodePath): boolean { + const objectRestPatternIterator = iterateObjectRestElement(path); + return !objectRestPatternIterator.next().done; } - function visitRestElements( - path: NodePath, - visitor: (path: NodePath) => any, + function visitObjectRestElements( + path: NodePath, + visitor: (path: NodePath) => void, ) { - path.traverse({ - Expression(path) { - const { parent, key } = path; - if ( - (isAssignmentPattern(parent) && key === "right") || - (isObjectProperty(parent) && parent.computed && key === "key") - ) { - path.skip(); - } - }, - RestElement: visitor, - }); + for (const restElementPath of iterateObjectRestElement(path)) { + visitor(restElementPath); + } } function hasSpread(node: t.ObjectExpression): boolean { @@ -273,7 +280,7 @@ export default declare((api, opts: Options) => { return; } - if (paramPath.isArrayPattern() && hasRestElement(paramPath)) { + if (paramPath.isArrayPattern() && hasObjectRestElement(paramPath)) { const elements = paramPath.get("elements"); for (let i = 0; i < elements.length; i++) { @@ -281,7 +288,7 @@ export default declare((api, opts: Options) => { } } - if (paramPath.isObjectPattern() && hasRestElement(paramPath)) { + if (paramPath.isObjectPattern() && hasObjectRestElement(paramPath)) { const uid = parentPath.scope.generateUidIdentifier("ref"); const declar = t.variableDeclaration("let", [ @@ -315,7 +322,7 @@ export default declare((api, opts: Options) => { const idsInRestParams = new Set(); for (let i = 0; i < params.length; ++i) { const param = params[i]; - if (hasRestElement(param)) { + if (hasObjectRestElement(param)) { paramsWithRestElement.add(i); for (const name of Object.keys(param.getBindingIdentifiers())) { idsInRestParams.add(name); @@ -389,14 +396,7 @@ export default declare((api, opts: Options) => { let insertionPath = path; const originalPath = path; - visitRestElements(path.get("id"), path => { - if (!path.parentPath.isObjectPattern()) { - // Return early if the parent is not an ObjectPattern, but - // (for example) an ArrayPattern or Function, because that - // means this RestElement is an not an object property. - return; - } - + visitObjectRestElements(path.get("id"), path => { if ( // skip single-property case, e.g. // const { ...x } = foo(); @@ -450,10 +450,8 @@ export default declare((api, opts: Options) => { ); }); - //@ts-expect-error: findParent can not apply assertions on result shape - const objectPatternPath: NodePath = path.findParent( - path => path.isObjectPattern(), - ); + const objectPatternPath = + path.parentPath as NodePath; const [impureComputedPropertyDeclarators, argument, callExpression] = createObjectRest( @@ -496,7 +494,7 @@ export default declare((api, opts: Options) => { const hasRest = declaration .get("declarations") - .some(path => hasObjectPatternRestElement(path.get("id"))); + .some(path => hasObjectRestElement(path.get("id"))); if (!hasRest) return; const specifiers = []; @@ -523,7 +521,7 @@ export default declare((api, opts: Options) => { // ({a, ...b} = c); AssignmentExpression(path, file) { const leftPath = path.get("left"); - if (leftPath.isObjectPattern() && hasRestElement(leftPath)) { + if (leftPath.isObjectPattern() && hasObjectRestElement(leftPath)) { const nodes = []; const refName = path.scope.generateUidBasedOnNode( @@ -564,13 +562,11 @@ export default declare((api, opts: Options) => { ForXStatement(path: NodePath) { const { node, scope } = path; const leftPath = path.get("left"); - const left = node.left; - - if (!hasObjectPatternRestElement(leftPath)) { - return; - } - if (!t.isVariableDeclaration(left)) { + if (!leftPath.isVariableDeclaration()) { + if (!hasObjectRestElement(leftPath)) { + return; + } // for ({a, ...b} of []) {} const temp = scope.generateUidIdentifier("ref"); @@ -579,22 +575,34 @@ export default declare((api, opts: Options) => { ]); path.ensureBlock(); - const body = path.node.body as t.BlockStatement; - if (body.body.length === 0 && path.isCompletionRecord()) { - body.body.unshift( - t.expressionStatement(scope.buildUndefinedNode()), - ); + const statementBody = (path.node.body as t.BlockStatement).body; + const nodes = []; + // todo: the completion of a for statement can only be observed from + // a do block (or eval that we don't support), + // but the new do-expression proposal plans to ban iteration ends in the + // do block, maybe we can get rid of this + if (statementBody.length === 0 && path.isCompletionRecord()) { + nodes.unshift(t.expressionStatement(scope.buildUndefinedNode())); } - body.body.unshift( + nodes.unshift( t.expressionStatement( - t.assignmentExpression("=", left, t.cloneNode(temp)), + t.assignmentExpression("=", leftPath.node, t.cloneNode(temp)), ), ); + + unshiftForXStatementBody(path, nodes); + scope.crawl(); + return; } else { // for (var {a, ...b} of []) {} - const pattern = left.declarations[0].id; + const patternPath = leftPath.get("declarations")[0].get("id"); + if (!hasObjectRestElement(patternPath)) { + return; + } + const left = leftPath.node; + const pattern = patternPath.node; const key = scope.generateUidIdentifier("ref"); node.left = t.variableDeclaration(left.kind, [ @@ -602,47 +610,65 @@ export default declare((api, opts: Options) => { ]); path.ensureBlock(); - const body = node.body as t.BlockStatement; - body.body.unshift( + unshiftForXStatementBody(path, [ t.variableDeclaration(node.left.kind, [ t.variableDeclarator(pattern, t.cloneNode(key)), ]), - ); + ]); + scope.crawl(); + return; } }, // [{a, ...b}] = c; ArrayPattern(path) { - const objectPatterns: t.VariableDeclarator[] = []; - - visitRestElements(path, path => { - if (!path.parentPath.isObjectPattern()) { - // Return early if the parent is not an ObjectPattern, but - // (for example) an ArrayPattern or Function, because that - // means this RestElement is an not an object property. - return; - } + type LhsAndRhs = { left: t.ObjectPattern; right: t.Identifier }; + const objectPatterns: LhsAndRhs[] = []; + const { scope } = path; + const uidIdentifiers: t.Identifier[] = []; - const objectPattern = path.parentPath; + visitObjectRestElements(path, path => { + const objectPattern = path.parentPath as NodePath; - const uid = path.scope.generateUidIdentifier("ref"); - objectPatterns.push(t.variableDeclarator(objectPattern.node, uid)); + const uid = scope.generateUidIdentifier("ref"); + objectPatterns.push({ left: objectPattern.node, right: uid }); + uidIdentifiers.push(uid); objectPattern.replaceWith(t.cloneNode(uid)); path.skip(); }); if (objectPatterns.length > 0) { - const statementPath = path.getStatementParent(); - const statementNode = statementPath.node; - const kind = - statementNode.type === "VariableDeclaration" - ? statementNode.kind - : "var"; - statementPath.insertAfter( - t.variableDeclaration(kind, objectPatterns), + const patternParentPath = path.findParent( + path => !(path.isPattern() || path.isObjectProperty()), ); + const patternParent = patternParentPath.node; + switch (patternParent.type) { + case "VariableDeclarator": + patternParentPath.insertAfter( + objectPatterns.map(({ left, right }) => + t.variableDeclarator(left, right), + ), + ); + break; + case "AssignmentExpression": + { + for (const uidIdentifier of uidIdentifiers) { + scope.push({ id: t.cloneNode(uidIdentifier) }); + } + patternParentPath.insertAfter( + objectPatterns.map(({ left, right }) => + t.assignmentExpression("=", left, right), + ), + ); + } + break; + default: + throw new Error( + `Unexpected pattern parent type: ${patternParent.type}`, + ); + } } }, diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/exec.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/exec.js new file mode 100644 index 000000000000..b2f29d54b252 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/exec.js @@ -0,0 +1,4 @@ +let a, result; +for (const [{...a}] of [[{ a: 0}]]) { result = a; } + +expect(result).toEqual({ a: 0 }); diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/input.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/input.js new file mode 100644 index 000000000000..5dc36a14d723 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/input.js @@ -0,0 +1,18 @@ +// ForXStatement +{ + let a; + for (const [{...a}] of []) {} + for ([{...a}] of []) {} + async function f() { + for await ([{...a}] of []) {} + } +} + +// skip +{ + for ([...a] in {}) {} + for ([...a] of []) {} + async function a() { + for await ([...a] of []) {} + } +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/output.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/output.js new file mode 100644 index 000000000000..8eecfe3ef431 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern-rest-only/output.js @@ -0,0 +1,35 @@ +// ForXStatement +{ + let a; + for (const _ref of []) { + const [_ref2] = _ref, + a = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref2), _ref2)); + } + for (var _ref3 of []) { + var _ref4; + [_ref4] = _ref3; + var _ref5 = _ref4; + ({} = _ref5); + a = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref5), _ref5)); + _ref5; + } + async function f() { + for await (var _ref6 of []) { + var _ref7; + [_ref7] = _ref6; + var _ref8 = _ref7; + ({} = _ref8); + a = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref8), _ref8)); + _ref8; + } + } +} + +// skip +{ + for ([...a] in {}) {} + for ([...a] of []) {} + async function a() { + for await ([...a] of []) {} + } +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern/input.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern/input.js index 8ab978fb9402..4c6815ef86dd 100644 --- a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern/input.js +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern/input.js @@ -1,19 +1,27 @@ // ForXStatement -for (const [{a, ...b}] of []) {} -for ([{a, ...b}] of []) {} -async function a() { - for await ([{a, ...b}] of []) {} +{ + let a, b; + for (const [{a, ...b}] of []) {} + for ([{a, ...b}] of []) {} + async function f() { + for await ([{a, ...b}] of []) {} + } + + for (const { a: [{a, ...b}] } of []) {} } // skip -for ([{a}] in {}) {} -for ([{a}] of []) {} -async function a() { - for await ([{a}] of []) {} +{ + for ([{a}] in {}) {} + for ([{a}] of []) {} + async function a() { + for await ([{a}] of []) {} + } } - -for ([a, ...b] in {}) {} -for ([a, ...b] of []) {} -async function a() { - for await ([a, ...b] of []) {} +{ + for ([a, ...b] in {}) {} + for ([a, ...b] of []) {} + async function a() { + for await ([a, ...b] of []) {} + } } diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern/output.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern/output.js index b1fe16509574..adf212105f6c 100644 --- a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern/output.js +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-array-pattern/output.js @@ -1,45 +1,67 @@ const _excluded = ["a"], _excluded2 = ["a"], - _excluded3 = ["a"]; + _excluded3 = ["a"], + _excluded4 = ["a"]; // ForXStatement -for (const _ref of []) { - const [_ref2] = _ref; - const { - a - } = _ref2, - b = babelHelpers.objectWithoutProperties(_ref2, _excluded); -} -for (var _ref3 of []) { - [_ref4] = _ref3; - var { +{ + let a, b; + for (const _ref of []) { + const [_ref2] = _ref, + { + a + } = _ref2, + b = babelHelpers.objectWithoutProperties(_ref2, _excluded); + } + for (var _ref3 of []) { + var _ref4; + [_ref4] = _ref3; + var _ref5 = _ref4; + ({ a - } = _ref4, - b = babelHelpers.objectWithoutProperties(_ref4, _excluded2); -} -async function a() { - for await (var _ref5 of []) { - [_ref6] = _ref5; - var { + } = _ref5); + b = babelHelpers.objectWithoutProperties(_ref5, _excluded2); + _ref5; + } + async function f() { + for await (var _ref6 of []) { + var _ref7; + [_ref7] = _ref6; + var _ref8 = _ref7; + ({ a - } = _ref6, - b = babelHelpers.objectWithoutProperties(_ref6, _excluded3); + } = _ref8); + b = babelHelpers.objectWithoutProperties(_ref8, _excluded3); + _ref8; + } + } + for (const _ref9 of []) { + const { + a: [{ + a + }] + } = _ref9, + b = babelHelpers.objectWithoutProperties(_ref9.a, _excluded4); } } // skip -for ([{ - a -}] in {}) {} -for ([{ - a -}] of []) {} -async function a() { - for await ([{ +{ + for ([{ + a + }] in {}) {} + for ([{ a }] of []) {} + async function a() { + for await ([{ + a + }] of []) {} + } } -for ([a, ...b] in {}) {} -for ([a, ...b] of []) {} -async function a() { - for await ([a, ...b] of []) {} +{ + for ([a, ...b] in {}) {} + for ([a, ...b] of []) {} + async function a() { + for await ([a, ...b] of []) {} + } } diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/exec.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/exec.js new file mode 100644 index 000000000000..0b501aad4359 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/exec.js @@ -0,0 +1,7 @@ +let a = 0, result, y; + +for ({ [a++]: result, ...y} of [["0", "1"]]) { + const a = 1; +} + +expect(result).toBe("0"); diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/input.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/input.js new file mode 100644 index 000000000000..01562dfa7d65 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/input.js @@ -0,0 +1,5 @@ +let a = 0, result, y; + +for ({ [a++]: result, ...y} of [["0", "1"]]) { + const a = 1; +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/output.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/output.js new file mode 100644 index 000000000000..5ce40460a554 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-assignment-shadowed-block-scoped-bindings/output.js @@ -0,0 +1,15 @@ +let a = 0, + result, + y; +for (var _ref of [["0", "1"]]) { + var _ref2 = _ref; + var _a = a++; + ({ + [_a]: result + } = _ref2); + y = babelHelpers.objectWithoutProperties(_ref2, [_a].map(babelHelpers.toPropertyKey)); + _ref2; + { + const a = 1; + } +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/exec.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/exec.js new file mode 100644 index 000000000000..730df566d9e8 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/exec.js @@ -0,0 +1,8 @@ +let a = 0, result; + +for (const { [a++]: x, ...y} of [["0", "1"]]) { + const a = 1; + result = x; +} + +expect(result).toBe("0"); diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/input.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/input.js new file mode 100644 index 000000000000..cc717e0d4510 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/input.js @@ -0,0 +1,6 @@ +let a = 0, result; + +for (const { [a++]: x, ...y} of [["0", "1"]]) { + const a = 1; + result = x; +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/output.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/output.js new file mode 100644 index 000000000000..62617c4d86d5 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x-declaration-shadowed-block-scoped-bindings/output.js @@ -0,0 +1,13 @@ +let a = 0, + result; +for (const _ref of [["0", "1"]]) { + const _a = a++, + { + [_a]: x + } = _ref, + y = babelHelpers.objectWithoutProperties(_ref, [_a].map(babelHelpers.toPropertyKey)); + { + const a = 1; + result = x; + } +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array-2/output.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array-2/output.js index fd33795ae64c..6a36ec22c35e 100644 --- a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array-2/output.js +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array-2/output.js @@ -1,7 +1,7 @@ const [a, [_ref], _ref2, [_ref3, { - h: [i, _ref4] -}]] = x; -const { + h: [i, _ref4] + }]] = x, + { b } = _ref, c = babelHelpers.objectWithoutProperties(_ref, ["b"]), diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array/exec.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array/exec.js new file mode 100644 index 000000000000..ee26efe69f6d --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array/exec.js @@ -0,0 +1,16 @@ +const [a, {b, ...c}] = [1, { b: 2, other: 3 }]; +expect(a).toBe(1); +expect(b).toBe(2); +expect(c).toStrictEqual({ other: 3 }); + +let [d, {e, ...f}] = [4, { e: 5, other: 6 }]; +expect(d).toBe(4); +expect(e).toBe(5); +expect(f).toStrictEqual({ other: 6 }); + +let g, h, i; + +[g, {h, ...i}] = [7, { h: 8, other: 9 }]; +expect(g).toBe(7); +expect(h).toBe(8); +expect(i).toStrictEqual({ other: 9 }); diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array/output.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array/output.js index fee66847bc02..da87e1b8e2a2 100644 --- a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array/output.js +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/nested-array/output.js @@ -1,15 +1,18 @@ -const [a, _ref] = x; -const { +var _ref3; +const [a, _ref] = x, + { b } = _ref, c = babelHelpers.objectWithoutProperties(_ref, ["b"]); -let [d, _ref2] = x; -let { +let [d, _ref2] = x, + { e } = _ref2, f = babelHelpers.objectWithoutProperties(_ref2, ["e"]); [g, _ref3] = x; -var { - h - } = _ref3, - i = babelHelpers.objectWithoutProperties(_ref3, ["h"]); +var _ref4 = _ref3; +({ + h +} = _ref4); +i = babelHelpers.objectWithoutProperties(_ref4, ["h"]); +_ref4; diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/output.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/output.js index b5aeeda93d2b..968d5acdf8ad 100644 --- a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/output.js +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/output.js @@ -98,10 +98,10 @@ const { x16: [] } = z(); const [...[...y17]] = z(); -const [..._ref] = z(); -const y18 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref), _ref)); -const [..._ref2] = z(); -const { +const [..._ref] = z(), + y18 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref), _ref)); +const [..._ref2] = z(), + { a19 } = _ref2, y19 = babelHelpers.objectWithoutProperties(_ref2, ["a19"]); @@ -116,8 +116,8 @@ const _z12 = z(), } = _z12, y22 = babelHelpers.objectWithoutProperties(_z12.x22, ["q22"]); const [[...y23] = []] = z(); -const [_ref3 = []] = z(); -const y24 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref3), _ref3)); +const [_ref3 = []] = z(), + y24 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref3), _ref3)); const { x25: [...y25] = [] } = z(); @@ -136,19 +136,19 @@ const _z14 = z(), }] } = _z14, y29 = babelHelpers.objectWithoutProperties(_z14.x29, ["q29"]); -const [,, _ref4] = z(); -const { +const [,, _ref4] = z(), + { y30 } = _ref4, x30 = babelHelpers.objectWithoutProperties(_ref4, ["y30"]); -const [,, _ref5] = z(); -const x31 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref5), _ref5)); +const [,, _ref5] = z(), + x31 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref5), _ref5)); const _z15 = z(), { x32: {} } = _z15, y32 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_z15.w32), _z15.w32)); -const [,, {}, _ref6] = z(); -const q32 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref6), _ref6)); +const [,, {}, _ref6] = z(), + q32 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_ref6), _ref6)); const _z16 = z(), y33 = babelHelpers.extends({}, (babelHelpers.objectDestructuringEmpty(_z16), _z16)); diff --git a/packages/babel-plugin-transform-object-rest-spread/tsconfig.json b/packages/babel-plugin-transform-object-rest-spread/tsconfig.json index caef23cb8e24..f30abf2ecee0 100644 --- a/packages/babel-plugin-transform-object-rest-spread/tsconfig.json +++ b/packages/babel-plugin-transform-object-rest-spread/tsconfig.json @@ -17,6 +17,9 @@ { "path": "../../packages/babel-helper-plugin-utils" }, + { + "path": "../../packages/babel-plugin-transform-destructuring" + }, { "path": "../../packages/babel-plugin-transform-parameters" }, diff --git a/packages/babel-preset-env/package.json b/packages/babel-preset-env/package.json index c9c071fc5bd8..1fe663c933b9 100644 --- a/packages/babel-preset-env/package.json +++ b/packages/babel-preset-env/package.json @@ -1,6 +1,6 @@ { "name": "@babel/preset-env", - "version": "7.27.1", + "version": "7.27.2", "description": "A Babel preset for each environment.", "author": "The Babel Team (https://babel.dev/team)", "homepage": "https://babel.dev/docs/en/next/babel-preset-env", diff --git a/packages/babel-preset-env/src/debug.ts b/packages/babel-preset-env/src/debug.ts index 24ba84ccb9b0..af441a80fe56 100644 --- a/packages/babel-preset-env/src/debug.ts +++ b/packages/babel-preset-env/src/debug.ts @@ -3,7 +3,7 @@ import { type Targets, type Target, } from "@babel/helper-compilation-targets"; -import compatData from "@babel/compat-data/plugins"; +import compatData from "@babel/compat-data/plugins" with { type: "json" }; // Outputs a message that shows which target(s) caused an item to be included: // transform-foo { "edge":"13", "firefox":"49", "ie":"10" } diff --git a/packages/babel-preset-env/src/index.ts b/packages/babel-preset-env/src/index.ts index 9ca1a804570d..8ef3835eb53f 100644 --- a/packages/babel-preset-env/src/index.ts +++ b/packages/babel-preset-env/src/index.ts @@ -35,7 +35,7 @@ import type { Targets, InputTargets } from "@babel/helper-compilation-targets"; import availablePlugins from "./available-plugins.ts"; import { declarePreset } from "@babel/helper-plugin-utils"; -import type { BuiltInsOption, ModuleOption, Options } from "./types.ts"; +import type { BuiltInsOption, ModuleOption, Options } from "./types.d.ts"; export type { Options }; // TODO: Remove in Babel 8 diff --git a/packages/babel-preset-env/src/plugins-compat-data.ts b/packages/babel-preset-env/src/plugins-compat-data.ts index be63df2d3829..3e578bf355f6 100644 --- a/packages/babel-preset-env/src/plugins-compat-data.ts +++ b/packages/babel-preset-env/src/plugins-compat-data.ts @@ -1,6 +1,6 @@ -import originalPlugins from "@babel/compat-data/plugins"; -import originalPluginsBugfixes from "@babel/compat-data/plugin-bugfixes"; -import originalOverlappingPlugins from "@babel/compat-data/overlapping-plugins"; +import originalPlugins from "@babel/compat-data/plugins" with { type: "json" }; +import originalPluginsBugfixes from "@babel/compat-data/plugin-bugfixes" with { type: "json" }; +import originalOverlappingPlugins from "@babel/compat-data/overlapping-plugins" with { type: "json" }; import availablePlugins from "./available-plugins.ts"; const keys: (o: O) => (keyof O)[] = Object.keys; diff --git a/packages/babel-preset-env/test/index.skip-bundled.js b/packages/babel-preset-env/test/index.skip-bundled.js index 28cef43692c4..4118e853502b 100644 --- a/packages/babel-preset-env/test/index.skip-bundled.js +++ b/packages/babel-preset-env/test/index.skip-bundled.js @@ -1,7 +1,3 @@ -// eslint-disable-next-line import/extensions -import compatData from "@babel/compat-data/plugins"; -// eslint-disable-next-line import/extensions -import bugfixesData from "@babel/compat-data/plugin-bugfixes"; import * as babel from "@babel/core"; import { USE_ESM, itBabel7, itBabel8, describeBabel7NoESM } from "$repo-utils"; @@ -34,6 +30,13 @@ if (!process.env.BABEL_8_BREAKING) { } = require("../lib/polyfills/babel-7-plugins.cjs"); } +// TODO(Babel 8): Once we only run tests in modern Node.js versions, we can +// use import with { type: "json" } to load the compat data. +// eslint-disable-next-line import/extensions +const compatData = require("@babel/compat-data/plugins"); +// eslint-disable-next-line import/extensions +const bugfixesData = require("@babel/compat-data/plugin-bugfixes"); + describe("babel-preset-env", () => { describe("transformIncludesAndExcludes", () => { it("should return in transforms array", () => { diff --git a/packages/babel-standalone/package.json b/packages/babel-standalone/package.json index a5620014f466..cc2e3132bb3c 100644 --- a/packages/babel-standalone/package.json +++ b/packages/babel-standalone/package.json @@ -1,6 +1,6 @@ { "name": "@babel/standalone", - "version": "7.27.1", + "version": "7.27.2", "description": "Standalone build of Babel for use in non-Node.js environments.", "main": "./babel.js", "files": [ diff --git a/packages/babel-template/package.json b/packages/babel-template/package.json index 9d02bff472a0..6b28d75cd83f 100644 --- a/packages/babel-template/package.json +++ b/packages/babel-template/package.json @@ -1,6 +1,6 @@ { "name": "@babel/template", - "version": "7.27.1", + "version": "7.27.2", "description": "Generate an AST from a string template.", "author": "The Babel Team (https://babel.dev/team)", "homepage": "https://babel.dev/docs/en/next/babel-template", diff --git a/packages/babel-template/src/populate.ts b/packages/babel-template/src/populate.ts index c7b5784feb4e..88e19225776d 100644 --- a/packages/babel-template/src/populate.ts +++ b/packages/babel-template/src/populate.ts @@ -50,7 +50,7 @@ export default function populatePlaceholders( applyReplacement( placeholder, ast, - (replacements && replacements[placeholder.name]) || null, + (replacements && replacements[placeholder.name]) ?? null, ); } catch (e) { e.message = `@babel/template placeholder "${placeholder.name}": ${e.message}`; diff --git a/packages/babel-template/test/index.js b/packages/babel-template/test/index.js index fba8a9769311..d715ca44db3b 100644 --- a/packages/babel-template/test/index.js +++ b/packages/babel-template/test/index.js @@ -244,6 +244,11 @@ describe("@babel/template", function () { expect(result.test.left).toBe(value); }); + it("should correctly handle empty string as computed property key", () => { + const result = template.ast`obj["${""}"] = 1`; + expect(result.type).toBe("ExpressionStatement"); + }); + it("should return assertions in ImportDeclaration when using .ast", () => { const result = template.ast( `import json from "./foo.json" with { type: "json" };`, diff --git a/scripts/generators/tsconfig.js b/scripts/generators/tsconfig.js index f9e349011290..178c9cc631db 100644 --- a/scripts/generators/tsconfig.js +++ b/scripts/generators/tsconfig.js @@ -78,12 +78,7 @@ function getTsPkgs(subRoot) { return [["", "/src"]]; } if (name === "@babel/compat-data") { - // map ./plugins to ./data/plugins.json - const subExport = _export.slice(1); - const subExportPath = exportPath - .replace("./", "/data/") - .replace(/\.js$/, ".json"); - return [[subExport, subExportPath]]; + return [[_export.slice(1), exportPath.slice(1)]]; } // [{esm, default}, "./lib/index.js"] if (Array.isArray(exportPath)) { diff --git a/yarn.lock b/yarn.lock index e1d36cb95859..96415d6fd808 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,6 +28,33 @@ __metadata: languageName: node linkType: hard +"@babel-baseline/cli@npm:@babel/cli@7.27.1": + version: 7.27.1 + resolution: "@babel/cli@npm:7.27.1" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.25" + "@nicolo-ribaudo/chokidar-2": "npm:2.1.8-no-fsevents.3" + chokidar: "npm:^3.6.0" + commander: "npm:^6.2.0" + convert-source-map: "npm:^2.0.0" + fs-readdir-recursive: "npm:^1.1.0" + glob: "npm:^7.2.0" + make-dir: "npm:^2.1.0" + slash: "npm:^2.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + dependenciesMeta: + "@nicolo-ribaudo/chokidar-2": + optional: true + chokidar: + optional: true + bin: + babel: ./bin/babel.js + babel-external-helpers: ./bin/babel-external-helpers.js + checksum: 10/b16dc3c4242da3e23ef98e68af89b86740bef9cc2a47678e344a6b84a6f40b29d0ee0915bb89067d610c7db2efec1c5d6973f4303f3c762a44dfc87f393c3634 + languageName: node + linkType: hard + "@babel-baseline/core@npm:@babel/core@7.24.4, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3": version: 7.24.4 resolution: "@babel/core@npm:7.24.4" @@ -174,6 +201,7 @@ __metadata: version: 0.0.0-use.local resolution: "@babel/benchmark@workspace:benchmark" dependencies: + "@babel-baseline/cli": "npm:@babel/cli@7.27.1" "@babel-baseline/core": "npm:@babel/core@7.24.4" "@babel-baseline/generator": "npm:@babel/generator@7.24.4" "@babel-baseline/helper-compilation-targets": "npm:@babel/helper-compilation-targets@7.23.6" @@ -181,6 +209,7 @@ __metadata: "@babel-baseline/parser": "npm:@babel/parser@7.24.4" "@babel-baseline/traverse": "npm:@babel/traverse@7.24.1" "@babel-baseline/types": "npm:@babel/types@7.24.0" + "@babel/cli": "workspace:^" "@babel/core": "workspace:^" "@babel/generator": "workspace:^" "@babel/helper-compilation-targets": "workspace:^" @@ -219,7 +248,7 @@ __metadata: languageName: node linkType: hard -"@babel/cli@workspace:packages/babel-cli": +"@babel/cli@workspace:^, @babel/cli@workspace:packages/babel-cli": version: 0.0.0-use.local resolution: "@babel/cli@workspace:packages/babel-cli" dependencies: @@ -2973,6 +3002,7 @@ __metadata: "@babel/helper-plugin-test-runner": "workspace:^" "@babel/helper-plugin-utils": "workspace:^" "@babel/parser": "workspace:^" + "@babel/plugin-transform-destructuring": "workspace:^" "@babel/plugin-transform-parameters": "workspace:^" peerDependencies: "@babel/core": ^7.0.0-0 @@ -4786,7 +4816,7 @@ __metadata: languageName: node linkType: hard -"@nicolo-ribaudo/chokidar-2-BABEL_8_BREAKING-false@npm:@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": +"@nicolo-ribaudo/chokidar-2-BABEL_8_BREAKING-false@npm:@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3, @nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.3": version: 2.1.8-no-fsevents.3 resolution: "@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.3" checksum: 10/c6e83af3b5051a3f6562649ff8fe37de9934a4cc02138678ed1badbd13ed3334f7ae5f63f2bbc3432210f6b245f082ac97e9b2afe0c13730c9838b295658c185 @@ -7830,7 +7860,7 @@ __metadata: languageName: node linkType: hard -"commander-BABEL_8_BREAKING-false@npm:commander@^6.2.0": +"commander-BABEL_8_BREAKING-false@npm:commander@^6.2.0, commander@npm:^6.2.0": version: 6.2.1 resolution: "commander@npm:6.2.1" checksum: 10/25b88c2efd0380c84f7844b39cf18510da7bfc5013692d68cdc65f764a1c34e6c8a36ea6d72b6620e3710a930cf8fab2695bdec2bf7107a0f4fa30a3ef3b7d0e @@ -12690,7 +12720,7 @@ __metadata: languageName: node linkType: hard -"make-dir-BABEL_8_BREAKING-false@npm:make-dir@^2.1.0, make-dir@npm:^2.0.0": +"make-dir-BABEL_8_BREAKING-false@npm:make-dir@^2.1.0, make-dir@npm:^2.0.0, make-dir@npm:^2.1.0": version: 2.1.0 resolution: "make-dir@npm:2.1.0" dependencies: @@ -15264,7 +15294,7 @@ __metadata: languageName: node linkType: hard -"slash-BABEL_8_BREAKING-false@npm:slash@^2.0.0": +"slash-BABEL_8_BREAKING-false@npm:slash@^2.0.0, slash@npm:^2.0.0": version: 2.0.0 resolution: "slash@npm:2.0.0" checksum: 10/512d4350735375bd11647233cb0e2f93beca6f53441015eea241fe784d8068281c3987fbaa93e7ef1c38df68d9c60013045c92837423c69115297d6169aa85e6