From 12cefe9ab2702962898c797b80e5ff82f02c7a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 24 Sep 2022 22:05:28 +0200 Subject: [PATCH 1/2] Internally rename proposal-* to transform-* in preset-env --- .../babel-preset-env/src/available-plugins.ts | 38 ++++---- packages/babel-preset-env/src/debug.ts | 21 ++++- packages/babel-preset-env/src/index.ts | 14 +-- .../babel-preset-env/src/normalize-options.ts | 89 ++++++++++--------- .../src/plugins-compat-data.ts | 48 +++++++--- .../babel-preset-env/src/shipped-proposals.ts | 24 ++--- .../test/index.skip-bundled.js | 13 +-- .../test/normalize-options.skip-bundled.js | 22 +++++ 8 files changed, 167 insertions(+), 102 deletions(-) diff --git a/packages/babel-preset-env/src/available-plugins.ts b/packages/babel-preset-env/src/available-plugins.ts index a43a47875bd3..9b1d79d8c022 100644 --- a/packages/babel-preset-env/src/available-plugins.ts +++ b/packages/babel-preset-env/src/available-plugins.ts @@ -83,23 +83,6 @@ export default { "bugfix/transform-tagged-template-caching": () => bugfixTaggedTemplateCaching, "bugfix/transform-v8-spread-parameters-in-optional-chaining": () => bugfixV8SpreadParametersInOptionalChaining, - "proposal-async-generator-functions": () => proposalAsyncGeneratorFunctions, - "proposal-class-properties": () => proposalClassProperties, - "proposal-class-static-block": () => proposalClassStaticBlock, - "proposal-dynamic-import": () => proposalDynamicImport, - "proposal-export-namespace-from": () => proposalExportNamespaceFrom, - "proposal-json-strings": () => proposalJsonStrings, - "proposal-logical-assignment-operators": () => - proposalLogicalAssignmentOperators, - "proposal-nullish-coalescing-operator": () => - proposalNullishCoalescingOperator, - "proposal-numeric-separator": () => proposalNumericSeparator, - "proposal-object-rest-spread": () => proposalObjectRestSpread, - "proposal-optional-catch-binding": () => proposalOptionalCatchBinding, - "proposal-optional-chaining": () => proposalOptionalChaining, - "proposal-private-methods": () => proposalPrivateMethods, - "proposal-private-property-in-object": () => proposalPrivatePropertyInObject, - "proposal-unicode-property-regex": () => proposalUnicodePropertyRegex, "syntax-async-generators": () => syntaxAsyncGenerators, "syntax-class-properties": () => syntaxClassProperties, "syntax-class-static-block": () => syntaxClassStaticBlock, @@ -116,18 +99,26 @@ export default { "syntax-private-property-in-object": () => syntaxPrivatePropertyInObject, "syntax-top-level-await": () => syntaxTopLevelAwait, "transform-arrow-functions": () => transformArrowFunctions, + "transform-async-generator-functions": () => proposalAsyncGeneratorFunctions, "transform-async-to-generator": () => transformAsyncToGenerator, "transform-block-scoped-functions": () => transformBlockScopedFunctions, "transform-block-scoping": () => transformBlockScoping, + "transform-class-properties": () => proposalClassProperties, + "transform-class-static-block": () => proposalClassStaticBlock, "transform-classes": () => transformClasses, "transform-computed-properties": () => transformComputedProperties, "transform-destructuring": () => transformDestructuring, "transform-dotall-regex": () => transformDotallRegex, "transform-duplicate-keys": () => transformDuplicateKeys, + "transform-dynamic-import": () => proposalDynamicImport, "transform-exponentiation-operator": () => transformExponentialOperator, + "transform-export-namespace-from": () => proposalExportNamespaceFrom, "transform-for-of": () => transformForOf, "transform-function-name": () => transformFunctionName, + "transform-json-strings": () => proposalJsonStrings, "transform-literals": () => transformLiterals, + "transform-logical-assignment-operators": () => + proposalLogicalAssignmentOperators, "transform-member-expression-literals": () => transformMemberExpressionLiterals, "transform-modules-amd": () => transformModulesAmd, @@ -137,8 +128,16 @@ export default { "transform-named-capturing-groups-regex": () => transformNamedCapturingGroupsRegex, "transform-new-target": () => transformNewTarget, + "transform-nullish-coalescing-operator": () => + proposalNullishCoalescingOperator, + "transform-numeric-separator": () => proposalNumericSeparator, + "transform-object-rest-spread": () => proposalObjectRestSpread, "transform-object-super": () => transformObjectSuper, + "transform-optional-catch-binding": () => proposalOptionalCatchBinding, + "transform-optional-chaining": () => proposalOptionalChaining, "transform-parameters": () => transformParameters, + "transform-private-methods": () => proposalPrivateMethods, + "transform-private-property-in-object": () => proposalPrivatePropertyInObject, "transform-property-literals": () => transformPropertyLiterals, "transform-regenerator": () => transformRegenerator, "transform-reserved-words": () => transformReservedWords, @@ -148,12 +147,13 @@ export default { "transform-template-literals": () => transformTemplateLiterals, "transform-typeof-symbol": () => transformTypeofSymbol, "transform-unicode-escapes": () => transformUnicodeEscapes, + "transform-unicode-property-regex": () => proposalUnicodePropertyRegex, "transform-unicode-regex": () => transformUnicodeRegex, }; export const minVersions = { "bugfix/transform-safari-id-destructuring-collision-in-function-expression": "7.16.0", - "proposal-class-static-block": "7.12.0", - "proposal-private-property-in-object": "7.10.0", + "transform-class-static-block": "7.12.0", + "transform-private-property-in-object": "7.10.0", }; diff --git a/packages/babel-preset-env/src/debug.ts b/packages/babel-preset-env/src/debug.ts index a1998fda9ac9..53c5e07fc051 100644 --- a/packages/babel-preset-env/src/debug.ts +++ b/packages/babel-preset-env/src/debug.ts @@ -1,6 +1,9 @@ -import { getInclusionReasons } from "@babel/helper-compilation-targets"; - -import type { Targets, Target } from "@babel/helper-compilation-targets"; +import { + getInclusionReasons, + type Targets, + type Target, +} from "@babel/helper-compilation-targets"; +import compatData from "@babel/compat-data/plugins"; // Outputs a message that shows which target(s) caused an item to be included: // transform-foo { "edge":"13", "firefox":"49", "ie":"10" } @@ -13,6 +16,18 @@ export const logPlugin = ( const support = list[item]; + // TODO(Babel 8): Remove this. It's needed to keep outputting proposal- + // in the debug log. + if (item.startsWith("transform-")) { + const proposalName = `proposal-${item.slice(10)}`; + if ( + proposalName === "proposal-dynamic-import" || + Object.prototype.hasOwnProperty.call(compatData, proposalName) + ) { + item = proposalName; + } + } + if (!support) { console.log(` ${item}`); return; diff --git a/packages/babel-preset-env/src/index.ts b/packages/babel-preset-env/src/index.ts index e36e03d14170..6edd65ff5854 100644 --- a/packages/babel-preset-env/src/index.ts +++ b/packages/babel-preset-env/src/index.ts @@ -16,8 +16,8 @@ import { import { plugins as pluginsList, pluginsBugfixes as pluginsBugfixesList, + overlappingPlugins, } from "./plugins-compat-data"; -import overlappingPlugins from "@babel/compat-data/overlapping-plugins"; import removeRegeneratorEntryPlugin from "./polyfills/regenerator"; import legacyBabelPolyfillPlugin from "./polyfills/babel-polyfill"; @@ -146,7 +146,7 @@ export const getModulesPluginNames = ({ shouldTransformESM && modules !== "umd" ) { - modulesPluginNames.push("proposal-dynamic-import"); + modulesPluginNames.push("transform-dynamic-import"); } else { if (shouldTransformDynamicImport) { console.warn( @@ -161,7 +161,7 @@ export const getModulesPluginNames = ({ } if (shouldTransformExportNamespaceFrom) { - modulesPluginNames.push("proposal-export-namespace-from"); + modulesPluginNames.push("transform-export-namespace-from"); } else { modulesPluginNames.push("syntax-export-namespace-from"); } @@ -362,7 +362,7 @@ option \`forceAllTransforms: true\` instead. const shouldSkipExportNamespaceFrom = (modules === "auto" && api.caller?.(supportsExportNamespaceFrom)) || (modules === false && - !isRequired("proposal-export-namespace-from", transformTargets, { + !isRequired("transform-export-namespace-from", transformTargets, { compatData, includes: include.plugins, excludes: exclude.plugins, @@ -411,9 +411,9 @@ option \`forceAllTransforms: true\` instead. const plugins = Array.from(pluginNames) .map(pluginName => { if ( - pluginName === "proposal-class-properties" || - pluginName === "proposal-private-methods" || - pluginName === "proposal-private-property-in-object" + pluginName === "transform-class-properties" || + pluginName === "transform-private-methods" || + pluginName === "transform-private-property-in-object" ) { return [ getPlugin(pluginName), diff --git a/packages/babel-preset-env/src/normalize-options.ts b/packages/babel-preset-env/src/normalize-options.ts index 76383862ba03..9d971a809c79 100644 --- a/packages/babel-preset-env/src/normalize-options.ts +++ b/packages/babel-preset-env/src/normalize-options.ts @@ -1,7 +1,7 @@ import semver, { type SemVer } from "semver"; import corejs2Polyfills from "@babel/compat-data/corejs2-built-ins"; // @ts-expect-error Fixme: TS can not infer types from ../data/core-js-compat.js -// but we can't import core-js-compat/data.json because JSON imports does +// but we can't import core-js-compat/data.json because JSON imports do // not work on Node 14 import corejs3Polyfills from "../data/core-js-compat"; import { plugins as pluginsList } from "./plugins-compat-data"; @@ -20,7 +20,6 @@ import type { CorejsOption, ModuleOption, Options, - PluginListItem, PluginListOption, } from "./types"; @@ -34,7 +33,7 @@ const allPluginsList = Object.keys(pluginsList); // should only be possible to exclude and not include module plugins, otherwise it's possible that preset-env // will add a module plugin twice. const modulePlugins = [ - "proposal-dynamic-import", + "transform-dynamic-import", ...Object.keys(moduleTransformations).map(m => moduleTransformations[m]), ]; @@ -42,59 +41,65 @@ const getValidIncludesAndExcludes = ( type: "include" | "exclude", corejs: number | false, ) => - new Set([ - ...allPluginsList, - ...(type === "exclude" ? modulePlugins : []), - ...(corejs - ? corejs == 2 - ? [...Object.keys(corejs2Polyfills), ...corejs2DefaultWebIncludes] - : Object.keys(corejs3Polyfills) - : []), - ]); - -const pluginToRegExp = (plugin: PluginListItem) => { - if (plugin instanceof RegExp) return plugin; - try { - return new RegExp(`^${normalizePluginName(plugin)}$`); - } catch (e) { - return null; - } -}; - -const selectPlugins = ( - regexp: RegExp | null, - type: "include" | "exclude", - corejs: number | false, -) => - Array.from(getValidIncludesAndExcludes(type, corejs)).filter( - item => regexp instanceof RegExp && regexp.test(item), + Array.from( + new Set([ + ...allPluginsList, + ...(type === "exclude" ? modulePlugins : []), + ...(corejs + ? corejs == 2 + ? [...Object.keys(corejs2Polyfills), ...corejs2DefaultWebIncludes] + : Object.keys(corejs3Polyfills) + : []), + ]), ); -const flatten = (array: Array>): Array => [].concat(...array); +function flatMap(array: Array, fn: (item: T) => Array): Array { + return Array.prototype.concat.apply([], array.map(fn)); +} const expandIncludesAndExcludes = ( - plugins: PluginListOption = [], + filterList: PluginListOption = [], type: "include" | "exclude", corejs: number | false, ) => { - if (plugins.length === 0) return []; - - const selectedPlugins = plugins.map(plugin => - selectPlugins(pluginToRegExp(plugin), type, corejs), - ); - const invalidRegExpList = plugins.filter( - (p, i) => selectedPlugins[i].length === 0, - ); + if (filterList.length === 0) return []; + + const filterableItems = getValidIncludesAndExcludes(type, corejs); + + const invalidFilters: PluginListOption = []; + const selectedPlugins = flatMap(filterList, filter => { + let re: RegExp; + if (typeof filter === "string") { + try { + re = new RegExp(`^${normalizePluginName(filter)}$`); + } catch (e) { + invalidFilters.push(filter); + return []; + } + } else { + re = filter; + } + const items = filterableItems.filter( + item => + re.test(item) || + // For backwards compatibility, we also support matching against the + // proposal- name. + // TODO(Babel 8): Remove this. + re.test(item.replace(/^transform-/, "proposal-")), + ); + if (items.length === 0) invalidFilters.push(filter); + return items; + }); v.invariant( - invalidRegExpList.length === 0, - `The plugins/built-ins '${invalidRegExpList.join( + invalidFilters.length === 0, + `The plugins/built-ins '${invalidFilters.join( ", ", )}' passed to the '${type}' option are not valid. Please check data/[plugin-features|built-in-features].js in babel-preset-env`, ); - return flatten(selectedPlugins); + return selectedPlugins; }; export const normalizePluginName = (plugin: string) => diff --git a/packages/babel-preset-env/src/plugins-compat-data.ts b/packages/babel-preset-env/src/plugins-compat-data.ts index 92e98ecd1cca..c4dabe9b2833 100644 --- a/packages/babel-preset-env/src/plugins-compat-data.ts +++ b/packages/babel-preset-env/src/plugins-compat-data.ts @@ -1,22 +1,42 @@ -import plugins from "@babel/compat-data/plugins"; -import bugfixPlugins from "@babel/compat-data/plugin-bugfixes"; +import originalPlugins from "@babel/compat-data/plugins"; +import originalPluginsBugfixes from "@babel/compat-data/plugin-bugfixes"; +import originalOverlappingPlugins from "@babel/compat-data/overlapping-plugins"; import availablePlugins from "./available-plugins"; -const pluginsFiltered = {}; -const bugfixPluginsFiltered = {}; +const keys: (o: O) => (keyof O)[] = Object.keys; -for (const plugin of Object.keys(plugins)) { - if (Object.hasOwnProperty.call(availablePlugins, plugin)) { - // @ts-expect-error fixme: refine pluginsFiltered types - pluginsFiltered[plugin] = plugins[plugin]; +export const plugins = filterAvailable(proposalToTransform(originalPlugins)); +export const pluginsBugfixes = filterAvailable( + proposalToTransform(originalPluginsBugfixes), +); +export const overlappingPlugins = proposalToTransform( + originalOverlappingPlugins, +); + +function filterAvailable( + data: Data, +): { [Name in keyof Data & keyof typeof availablePlugins]: Data[Name] } { + const result = {} as any; + for (const plugin of keys(data)) { + if (Object.hasOwnProperty.call(availablePlugins, plugin)) { + result[plugin] = data[plugin]; + } } + return result; } -for (const plugin of Object.keys(bugfixPlugins)) { - if (Object.hasOwnProperty.call(availablePlugins, plugin)) { - // @ts-expect-error fixme: refine bugfixPluginsFiltered types - bugfixPluginsFiltered[plugin] = bugfixPlugins[plugin]; +// TODO(Babel 8): Store the plugins directly as transform- in @babel/compat-data +function proposalToTransform( + plugins: Data, +): { + [Name in keyof Data as Name extends `proposal-${infer Feat}` + ? `transform-${Feat}` + : Name]: Data[Name]; +} { + const result = {} as any; + for (const plugin of keys(plugins)) { + result[(plugin as string).replace(/^proposal-/, "transform-")] = + plugins[plugin]; } + return result; } - -export { pluginsFiltered as plugins, bugfixPluginsFiltered as pluginsBugfixes }; diff --git a/packages/babel-preset-env/src/shipped-proposals.ts b/packages/babel-preset-env/src/shipped-proposals.ts index fb77edc566e7..504db4060289 100644 --- a/packages/babel-preset-env/src/shipped-proposals.ts +++ b/packages/babel-preset-env/src/shipped-proposals.ts @@ -11,19 +11,19 @@ const proposalSyntaxPlugins = ["syntax-import-assertions"] as const; // use intermediary object to enforce alphabetical key order const pluginSyntaxObject = { - "proposal-async-generator-functions": "syntax-async-generators", - "proposal-class-properties": "syntax-class-properties", - "proposal-class-static-block": "syntax-class-static-block", - "proposal-json-strings": "syntax-json-strings", - "proposal-nullish-coalescing-operator": "syntax-nullish-coalescing-operator", - "proposal-numeric-separator": "syntax-numeric-separator", - "proposal-object-rest-spread": "syntax-object-rest-spread", - "proposal-optional-catch-binding": "syntax-optional-catch-binding", - "proposal-optional-chaining": "syntax-optional-chaining", + "transform-async-generator-functions": "syntax-async-generators", + "transform-class-properties": "syntax-class-properties", + "transform-class-static-block": "syntax-class-static-block", + "transform-json-strings": "syntax-json-strings", + "transform-nullish-coalescing-operator": "syntax-nullish-coalescing-operator", + "transform-numeric-separator": "syntax-numeric-separator", + "transform-object-rest-spread": "syntax-object-rest-spread", + "transform-optional-catch-binding": "syntax-optional-catch-binding", + "transform-optional-chaining": "syntax-optional-chaining", // note: we don't have syntax-private-methods - "proposal-private-methods": "syntax-class-properties", - "proposal-private-property-in-object": "syntax-private-property-in-object", - "proposal-unicode-property-regex": null as null, + "transform-private-methods": "syntax-class-properties", + "transform-private-property-in-object": "syntax-private-property-in-object", + "transform-unicode-property-regex": null as null, } as const; const pluginSyntaxEntries = Object.keys(pluginSyntaxObject).map< diff --git a/packages/babel-preset-env/test/index.skip-bundled.js b/packages/babel-preset-env/test/index.skip-bundled.js index 33f2a8916768..2c2d14d66523 100644 --- a/packages/babel-preset-env/test/index.skip-bundled.js +++ b/packages/babel-preset-env/test/index.skip-bundled.js @@ -103,7 +103,7 @@ describe("babel-preset-env", () => { }); }); describe("dynamic imports should be transformed", () => { - it("returns specified modules transform and proposal-dynamic-import", () => { + it("returns specified modules transform and transform-dynamic-import", () => { expect( babelPresetEnv.getModulesPluginNames({ modules: "systemjs", @@ -114,7 +114,7 @@ describe("babel-preset-env", () => { }), ).toEqual([ "transform-modules-systemjs", - "proposal-dynamic-import", + "transform-dynamic-import", "syntax-export-namespace-from", ]); }); @@ -130,8 +130,8 @@ describe("babel-preset-env", () => { }), ).toEqual([ "transform-modules-systemjs", - "proposal-dynamic-import", - "proposal-export-namespace-from", + "transform-dynamic-import", + "transform-export-namespace-from", ]); }); }); @@ -302,7 +302,10 @@ describe("babel-preset-env", () => { it("available-plugins is in sync with @babel/compat-data", () => { const arrAvailablePlugins = Object.keys(availablePlugins).sort(); - const arrCompatData = Object.keys(compatData).sort(); + const arrCompatData = Object.keys(compatData) + // TODO(Babel 8): Remove this .map + .map(name => name.replace("proposal-", "transform-")) + .sort(); expect(arrAvailablePlugins).toEqual(expect.arrayContaining(arrCompatData)); }); diff --git a/packages/babel-preset-env/test/normalize-options.skip-bundled.js b/packages/babel-preset-env/test/normalize-options.skip-bundled.js index 88067e57fd79..04ee2ef1f2a5 100644 --- a/packages/babel-preset-env/test/normalize-options.skip-bundled.js +++ b/packages/babel-preset-env/test/normalize-options.skip-bundled.js @@ -144,6 +144,28 @@ describe("normalize-options", () => { ]); }); + it("should work both with proposal-* and transform-*", () => { + expect( + normalizeOptions({ include: ["proposal-.*-regex"] }).include, + ).toEqual([ + "transform-dotall-regex", + "transform-unicode-property-regex", + "transform-named-capturing-groups-regex", + "transform-sticky-regex", + "transform-unicode-regex", + ]); + + expect( + normalizeOptions({ include: ["transform-.*-regex"] }).include, + ).toEqual([ + "transform-dotall-regex", + "transform-unicode-property-regex", + "transform-named-capturing-groups-regex", + "transform-sticky-regex", + "transform-unicode-regex", + ]); + }); + it("should not allow the same modules in `include` and `exclude`", () => { const normalizeWithNonExistingPlugin = () => { normalizeOptions({ From 898160cb8175524b52103ea446eff9e50a18e3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 27 Sep 2022 16:12:10 +0200 Subject: [PATCH 2/2] Add new plugin names to compat-data --- .../data/overlapping-plugins.json | 3 + .../data/plugin-bugfixes.json | 11 ++ packages/babel-compat-data/data/plugins.json | 153 ++++++++++++++++++ .../scripts/build-bugfixes-targets.js | 9 +- .../babel-compat-data/scripts/build-data.js | 15 +- .../scripts/data/legacy-plugin-aliases.js | 20 +++ .../scripts/data/plugin-bugfixes.js | 2 +- .../scripts/data/plugin-features.js | 26 +-- .../scripts/utils-build-data.js | 15 ++ .../src/plugins-compat-data.ts | 26 +-- 10 files changed, 238 insertions(+), 42 deletions(-) create mode 100644 packages/babel-compat-data/scripts/data/legacy-plugin-aliases.js diff --git a/packages/babel-compat-data/data/overlapping-plugins.json b/packages/babel-compat-data/data/overlapping-plugins.json index 6ad09e432450..94fda05db6b8 100644 --- a/packages/babel-compat-data/data/overlapping-plugins.json +++ b/packages/babel-compat-data/data/overlapping-plugins.json @@ -16,6 +16,9 @@ "transform-template-literals": [ "bugfix/transform-tagged-template-caching" ], + "transform-optional-chaining": [ + "bugfix/transform-v8-spread-parameters-in-optional-chaining" + ], "proposal-optional-chaining": [ "bugfix/transform-v8-spread-parameters-in-optional-chaining" ] diff --git a/packages/babel-compat-data/data/plugin-bugfixes.json b/packages/babel-compat-data/data/plugin-bugfixes.json index a16d707df069..4fbe7dd72d2d 100644 --- a/packages/babel-compat-data/data/plugin-bugfixes.json +++ b/packages/babel-compat-data/data/plugin-bugfixes.json @@ -88,6 +88,17 @@ "ios": "13.4", "electron": "13.0" }, + "transform-optional-chaining": { + "chrome": "80", + "opera": "67", + "edge": "80", + "firefox": "74", + "safari": "13.1", + "node": "14", + "ios": "13.4", + "samsung": "13", + "electron": "8.0" + }, "proposal-optional-chaining": { "chrome": "80", "opera": "67", diff --git a/packages/babel-compat-data/data/plugins.json b/packages/babel-compat-data/data/plugins.json index 96c64cab34f2..7162a282f95d 100644 --- a/packages/babel-compat-data/data/plugins.json +++ b/packages/babel-compat-data/data/plugins.json @@ -1,4 +1,12 @@ { + "transform-class-static-block": { + "chrome": "94", + "opera": "80", + "edge": "94", + "firefox": "93", + "node": "16.11", + "electron": "15.0" + }, "proposal-class-static-block": { "chrome": "94", "opera": "80", @@ -7,6 +15,16 @@ "node": "16.11", "electron": "15.0" }, + "transform-private-property-in-object": { + "chrome": "91", + "opera": "77", + "edge": "91", + "firefox": "90", + "safari": "15", + "node": "16.9", + "ios": "15", + "electron": "13.0" + }, "proposal-private-property-in-object": { "chrome": "91", "opera": "77", @@ -17,6 +35,17 @@ "ios": "15", "electron": "13.0" }, + "transform-class-properties": { + "chrome": "74", + "opera": "62", + "edge": "79", + "firefox": "90", + "safari": "14.1", + "node": "12", + "ios": "15", + "samsung": "11", + "electron": "6.0" + }, "proposal-class-properties": { "chrome": "74", "opera": "62", @@ -28,6 +57,17 @@ "samsung": "11", "electron": "6.0" }, + "transform-private-methods": { + "chrome": "84", + "opera": "70", + "edge": "84", + "firefox": "90", + "safari": "15", + "node": "14.6", + "ios": "15", + "samsung": "14", + "electron": "10.0" + }, "proposal-private-methods": { "chrome": "84", "opera": "70", @@ -39,6 +79,18 @@ "samsung": "14", "electron": "10.0" }, + "transform-numeric-separator": { + "chrome": "75", + "opera": "62", + "edge": "79", + "firefox": "70", + "safari": "13", + "node": "12.5", + "ios": "13", + "samsung": "11", + "rhino": "1.7.14", + "electron": "6.0" + }, "proposal-numeric-separator": { "chrome": "75", "opera": "62", @@ -51,6 +103,17 @@ "rhino": "1.7.14", "electron": "6.0" }, + "transform-logical-assignment-operators": { + "chrome": "85", + "opera": "71", + "edge": "85", + "firefox": "79", + "safari": "14", + "node": "15", + "ios": "14", + "samsung": "14", + "electron": "10.0" + }, "proposal-logical-assignment-operators": { "chrome": "85", "opera": "71", @@ -62,6 +125,17 @@ "samsung": "14", "electron": "10.0" }, + "transform-nullish-coalescing-operator": { + "chrome": "80", + "opera": "67", + "edge": "80", + "firefox": "72", + "safari": "13.1", + "node": "14", + "ios": "13.4", + "samsung": "13", + "electron": "8.0" + }, "proposal-nullish-coalescing-operator": { "chrome": "80", "opera": "67", @@ -73,6 +147,16 @@ "samsung": "13", "electron": "8.0" }, + "transform-optional-chaining": { + "chrome": "91", + "opera": "77", + "edge": "91", + "firefox": "74", + "safari": "13.1", + "node": "16.9", + "ios": "13.4", + "electron": "13.0" + }, "proposal-optional-chaining": { "chrome": "91", "opera": "77", @@ -83,6 +167,18 @@ "ios": "13.4", "electron": "13.0" }, + "transform-json-strings": { + "chrome": "66", + "opera": "53", + "edge": "79", + "firefox": "62", + "safari": "12", + "node": "10", + "ios": "12", + "samsung": "9", + "rhino": "1.7.14", + "electron": "3.0" + }, "proposal-json-strings": { "chrome": "66", "opera": "53", @@ -95,6 +191,17 @@ "rhino": "1.7.14", "electron": "3.0" }, + "transform-optional-catch-binding": { + "chrome": "66", + "opera": "53", + "edge": "79", + "firefox": "58", + "safari": "11.1", + "node": "10", + "ios": "11.3", + "samsung": "9", + "electron": "3.0" + }, "proposal-optional-catch-binding": { "chrome": "66", "opera": "53", @@ -115,6 +222,17 @@ "samsung": "5", "electron": "0.37" }, + "transform-async-generator-functions": { + "chrome": "63", + "opera": "50", + "edge": "79", + "firefox": "57", + "safari": "12", + "node": "10", + "ios": "12", + "samsung": "8", + "electron": "3.0" + }, "proposal-async-generator-functions": { "chrome": "63", "opera": "50", @@ -126,6 +244,17 @@ "samsung": "8", "electron": "3.0" }, + "transform-object-rest-spread": { + "chrome": "60", + "opera": "47", + "edge": "79", + "firefox": "55", + "safari": "11.1", + "node": "8.3", + "ios": "11.3", + "samsung": "8", + "electron": "2.0" + }, "proposal-object-rest-spread": { "chrome": "60", "opera": "47", @@ -148,6 +277,17 @@ "samsung": "8", "electron": "3.0" }, + "transform-unicode-property-regex": { + "chrome": "64", + "opera": "51", + "edge": "79", + "firefox": "78", + "safari": "11.1", + "node": "10", + "ios": "11.3", + "samsung": "9", + "electron": "3.0" + }, "proposal-unicode-property-regex": { "chrome": "64", "opera": "51", @@ -462,6 +602,19 @@ "rhino": "1.7.13", "electron": "0.20" }, + "transform-export-namespace-from": { + "chrome": "72", + "and_chr": "72", + "edge": "79", + "firefox": "80", + "and_ff": "80", + "node": "13.2", + "opera": "60", + "op_mob": "51", + "samsung": "11.0", + "android": "72", + "electron": "5.0" + }, "proposal-export-namespace-from": { "chrome": "72", "and_chr": "72", diff --git a/packages/babel-compat-data/scripts/build-bugfixes-targets.js b/packages/babel-compat-data/scripts/build-bugfixes-targets.js index 722e3d949f47..bbb894aced2c 100644 --- a/packages/babel-compat-data/scripts/build-bugfixes-targets.js +++ b/packages/babel-compat-data/scripts/build-bugfixes-targets.js @@ -4,7 +4,12 @@ const path = require("path"); -const { generateData, environments, writeFile } = require("./utils-build-data"); +const { + generateData, + environments, + writeFile, + defineLegacyPluginAliases, +} = require("./utils-build-data"); const pluginBugfixes = require("./data/plugin-bugfixes"); const pluginFeatures = require("./data/plugin-features"); @@ -34,7 +39,7 @@ for (const [filename, data] of [ ]) { const dataPath = path.join(__dirname, `../data/${filename}.json`); - if (!writeFile(data, dataPath, filename)) { + if (!writeFile(defineLegacyPluginAliases(data), dataPath, filename)) { process.exitCode = 1; break; } diff --git a/packages/babel-compat-data/scripts/build-data.js b/packages/babel-compat-data/scripts/build-data.js index 553d3bbdd79b..3ae6f15979a9 100644 --- a/packages/babel-compat-data/scripts/build-data.js +++ b/packages/babel-compat-data/scripts/build-data.js @@ -3,13 +3,18 @@ const path = require("path"); const compatData = require("@mdn/browser-compat-data").javascript; const { process } = require("./build-modules-support"); -const { generateData, environments, writeFile } = require("./utils-build-data"); +const { + generateData, + environments, + writeFile, + defineLegacyPluginAliases, +} = require("./utils-build-data"); for (const target of ["plugin", "corejs2-built-in"]) { // We ignore 'overlapping' here, because it's already generated by // built-bugfixes-targets.js which has a complete view over all the // plugins that we have data for. - const { data: newData } = generateData( + let { data: newData } = generateData( environments, require(`./data/${target}-features`) ); @@ -21,7 +26,11 @@ for (const target of ["plugin", "corejs2-built-in"]) { // the node.js compat data is 12.0, the first node version ships `export *` behind a flag // here we overwrite to 13.2 which is the first unflagged version exportNamespaceFromCompatData.node = "13.2"; - newData["proposal-export-namespace-from"] = exportNamespaceFromCompatData; + newData["transform-export-namespace-from"] = exportNamespaceFromCompatData; + + // Add proposal-* aliases for backward compatibility. + // TODO(Babel 7): This won't be needed anymore. + newData = defineLegacyPluginAliases(newData); } const dataPath = path.join(__dirname, `../data/${target}s.json`); diff --git a/packages/babel-compat-data/scripts/data/legacy-plugin-aliases.js b/packages/babel-compat-data/scripts/data/legacy-plugin-aliases.js new file mode 100644 index 000000000000..d588f3b4ded0 --- /dev/null +++ b/packages/babel-compat-data/scripts/data/legacy-plugin-aliases.js @@ -0,0 +1,20 @@ +// TODO(Babel 7): This won't be needed anymore + +// prettier-ignore +module.exports = { + __proto__: null, + "transform-class-static-block": "proposal-class-static-block", + "transform-private-property-in-object": "proposal-private-property-in-object", + "transform-class-properties": "proposal-class-properties", + "transform-private-methods": "proposal-private-methods", + "transform-numeric-separator": "proposal-numeric-separator", + "transform-logical-assignment-operators": "proposal-logical-assignment-operators", + "transform-nullish-coalescing-operator": "proposal-nullish-coalescing-operator", + "transform-optional-chaining": "proposal-optional-chaining", + "transform-json-strings": "proposal-json-strings", + "transform-optional-catch-binding": "proposal-optional-catch-binding", + "transform-async-generator-functions": "proposal-async-generator-functions", + "transform-object-rest-spread": "proposal-object-rest-spread", + "transform-unicode-property-regex": "proposal-unicode-property-regex", + "transform-export-namespace-from": "proposal-export-namespace-from", +}; diff --git a/packages/babel-compat-data/scripts/data/plugin-bugfixes.js b/packages/babel-compat-data/scripts/data/plugin-bugfixes.js index c6cb32795dd1..4ed282c77982 100644 --- a/packages/babel-compat-data/scripts/data/plugin-bugfixes.js +++ b/packages/babel-compat-data/scripts/data/plugin-bugfixes.js @@ -43,6 +43,6 @@ module.exports = { features: [ "optional chaining operator (?.) / spread parameters after optional chaining", ], - replaces: "proposal-optional-chaining", + replaces: "transform-optional-chaining", }, }; diff --git a/packages/babel-compat-data/scripts/data/plugin-features.js b/packages/babel-compat-data/scripts/data/plugin-features.js index 779a96df99a1..6c4365b0f096 100644 --- a/packages/babel-compat-data/scripts/data/plugin-features.js +++ b/packages/babel-compat-data/scripts/data/plugin-features.js @@ -128,34 +128,34 @@ const es2017 = { }; const es2018 = { - "proposal-async-generator-functions": "Asynchronous Iterators", - "proposal-object-rest-spread": "object rest/spread properties", + "transform-async-generator-functions": "Asynchronous Iterators", + "transform-object-rest-spread": "object rest/spread properties", "transform-dotall-regex": "s (dotAll) flag for regular expressions", - "proposal-unicode-property-regex": "RegExp Unicode Property Escapes", + "transform-unicode-property-regex": "RegExp Unicode Property Escapes", "transform-named-capturing-groups-regex": "RegExp named capture groups", }; const es2019 = { - "proposal-json-strings": "JSON superset", - "proposal-optional-catch-binding": "optional catch binding", + "transform-json-strings": "JSON superset", + "transform-optional-catch-binding": "optional catch binding", }; const es2020 = { - "proposal-nullish-coalescing-operator": "nullish coalescing operator (??)", - "proposal-optional-chaining": "optional chaining operator (?.)", + "transform-nullish-coalescing-operator": "nullish coalescing operator (??)", + "transform-optional-chaining": "optional chaining operator (?.)", }; const es2021 = { - "proposal-numeric-separator": "numeric separators", - "proposal-logical-assignment-operators": "Logical Assignment", + "transform-numeric-separator": "numeric separators", + "transform-logical-assignment-operators": "Logical Assignment", }; const es2022 = { - "proposal-class-static-block": "Class static initialization blocks", - "proposal-private-property-in-object": + "transform-class-static-block": "Class static initialization blocks", + "transform-private-property-in-object": "Ergonomic brand checks for private fields", - "proposal-class-properties": { + "transform-class-properties": { features: [ "static class fields / public static class fields", "static class fields / private static class fields", @@ -165,7 +165,7 @@ const es2022 = { "instance class fields / computed instance class fields", ], }, - "proposal-private-methods": "private class methods", + "transform-private-methods": "private class methods", }; const shippedProposal = {}; diff --git a/packages/babel-compat-data/scripts/utils-build-data.js b/packages/babel-compat-data/scripts/utils-build-data.js index 628d91766013..e0037bb9dcaa 100644 --- a/packages/babel-compat-data/scripts/utils-build-data.js +++ b/packages/babel-compat-data/scripts/utils-build-data.js @@ -7,6 +7,7 @@ const envs = require("../build/compat-table/environments"); const parseEnvsVersions = require("../build/compat-table/build-utils/parse-envs-versions"); const interpolateAllResults = require("../build/compat-table/build-utils/interpolate-all-results"); const compareVersions = require("../build/compat-table/build-utils/compare-versions"); +const legacyPluginAliases = require("./data/legacy-plugin-aliases"); const envsVersions = parseEnvsVersions(envs); @@ -165,3 +166,17 @@ exports.writeFile = function (data, dataPath, name) { } return true; }; + +// TODO(Babel 8): Remove this. +exports.defineLegacyPluginAliases = function (data) { + // We create a new object to inject legacy aliases in the correct + // order, rather than all at the end. + const result = {}; + for (const key in data) { + result[key] = data[key]; + if (key in legacyPluginAliases) { + result[legacyPluginAliases[key]] = data[key]; + } + } + return result; +}; diff --git a/packages/babel-preset-env/src/plugins-compat-data.ts b/packages/babel-preset-env/src/plugins-compat-data.ts index c4dabe9b2833..40d16f0f8de9 100644 --- a/packages/babel-preset-env/src/plugins-compat-data.ts +++ b/packages/babel-preset-env/src/plugins-compat-data.ts @@ -5,13 +5,9 @@ import availablePlugins from "./available-plugins"; const keys: (o: O) => (keyof O)[] = Object.keys; -export const plugins = filterAvailable(proposalToTransform(originalPlugins)); -export const pluginsBugfixes = filterAvailable( - proposalToTransform(originalPluginsBugfixes), -); -export const overlappingPlugins = proposalToTransform( - originalOverlappingPlugins, -); +export const plugins = filterAvailable(originalPlugins); +export const pluginsBugfixes = filterAvailable(originalPluginsBugfixes); +export const overlappingPlugins = filterAvailable(originalOverlappingPlugins); function filterAvailable( data: Data, @@ -24,19 +20,3 @@ function filterAvailable( } return result; } - -// TODO(Babel 8): Store the plugins directly as transform- in @babel/compat-data -function proposalToTransform( - plugins: Data, -): { - [Name in keyof Data as Name extends `proposal-${infer Feat}` - ? `transform-${Feat}` - : Name]: Data[Name]; -} { - const result = {} as any; - for (const plugin of keys(plugins)) { - result[(plugin as string).replace(/^proposal-/, "transform-")] = - plugins[plugin]; - } - return result; -}