diff --git a/babel.config.js b/babel.config.js index 9b7d0c085d99..093bc1d1c239 100644 --- a/babel.config.js +++ b/babel.config.js @@ -244,16 +244,20 @@ module.exports = function (api) { name: "process.env.IS_PUBLISH", value: bool(process.env.IS_PUBLISH), }, + "flag-IS_PUBLISH", ], - process.env.STRIP_BABEL_8_FLAG && [ - pluginToggleBooleanFlag, - { - name: "process.env.BABEL_8_BREAKING", - value: bool(process.env.BABEL_8_BREAKING), - }, - "flag-BABEL_8_BREAKING", - ], + process.env.STRIP_BABEL_8_FLAG + ? [ + pluginToggleBooleanFlag, + { + name: "process.env.BABEL_8_BREAKING", + attributeName: "BABEL_8_BREAKING", + value: bool(process.env.BABEL_8_BREAKING), + }, + "flag-BABEL_8_BREAKING", + ] + : [pluginDropBooleanImportAttribute, { name: "BABEL_8_BREAKING" }], pluginPackageJsonMacro, @@ -575,7 +579,10 @@ function pluginPolyfillsOldNode({ template, types: t }) { * @param {import("@babel/core")} pluginAPI * @returns {import("@babel/core").PluginObject} */ -function pluginToggleBooleanFlag({ types: t }, { name, value }) { +function pluginToggleBooleanFlag( + { types: t }, + { name, attributeName = name, value } +) { if (typeof value !== "boolean") throw new Error(`.value must be a boolean`); function evaluate(test) { @@ -684,6 +691,64 @@ function pluginToggleBooleanFlag({ types: t }, { name, value }) { throw path.buildCodeFrameError("This check could not be stripped."); } }, + ImportDeclaration(path) { + if (!path.node.attributes?.length) return; + + /** @type {null | import("@babel/core").NodePath} */ + const attribute = path + .get("attributes") + .find(attr => attr.node.key.name === attributeName); + if (attribute == null) { + return; + } + + const attributeValue = attribute.node.value.value; + if (attributeValue !== "true" && attributeValue !== "false") { + throw new path.buildCodeFrameError( + `${attributeName} attribute must be "true" or "false"` + ); + } + + if (attributeValue !== String(value)) { + path.remove(); + } else { + attribute.remove(); + if (path.node.attributes.length === 0) { + path.node.attributes = null; + } + } + }, + }, + }; +} + +/** + * @param {import("@babel/core")} pluginAPI + * @returns {import("@babel/core").PluginObject} + */ +function pluginDropBooleanImportAttribute(_babel, { name }) { + return { + visitor: { + ImportDeclaration(path) { + if (!path.node.attributes?.length) return; + + const attribute = path + .get("attributes") + .find(attr => attr.node.key.name === name); + if (attribute == null) return; + + const attributeValue = attribute.node.value.value; + if (attributeValue !== "true" && attributeValue !== "false") { + throw new path.buildCodeFrameError( + `${name} attribute must be "true" or "false"` + ); + } + + attribute.remove(); + if (path.node.attributes.length === 0) { + path.node.attributes = null; + } + }, }, }; } @@ -916,6 +981,12 @@ function pluginImportMetaUrl({ types: t, template }) { // Let's just remove this declaration to unshadow the "global" cjs require. path.remove(); + path.scope.crawl(); + + const createRequireBinding = path.scope.getBinding("createRequire"); + if (!createRequireBinding.referenced) { + createRequireBinding.path.remove(); + } }, // import.meta.url diff --git a/packages/babel-core/src/index.ts b/packages/babel-core/src/index.ts index 80850aeb7576..273628923877 100644 --- a/packages/babel-core/src/index.ts +++ b/packages/babel-core/src/index.ts @@ -92,8 +92,8 @@ export const DEFAULT_EXTENSIONS = Object.freeze([ ".cjs", ] as const); -import Module from "module"; -import * as thisFile from "./index.ts"; +import Module from "module" with { USE_ESM: "true", IS_STANDALONE: "false" }; +import * as thisFile from "./index.ts" with { USE_ESM: "true", IS_STANDALONE: "false" }; if (USE_ESM && !IS_STANDALONE) { // Pass this module to the CJS proxy, so that it can be synchronously accessed. const cjsProxy = Module.createRequire(import.meta.url)("../cjs-proxy.cjs"); diff --git a/packages/babel-core/src/transformation/file/babel-7-helpers.cjs b/packages/babel-core/src/transformation/file/babel-7-helpers.cjs index d30a95bc765a..dd548635525b 100644 --- a/packages/babel-core/src/transformation/file/babel-7-helpers.cjs +++ b/packages/babel-core/src/transformation/file/babel-7-helpers.cjs @@ -1,4 +1,10 @@ // TODO(Babel 8): Remove this file -exports.getModuleName = () => - require("@babel/helper-module-transforms").getModuleName; +if (!process.env.BABEL_8_BREAKING) { + exports.getModuleName = () => + require("@babel/helper-module-transforms").getModuleName; +} else if (process.env.IS_PUBLISH) { + throw new Error( + "Internal Babel error: This file should only be loaded in Babel 7", + ); +} diff --git a/packages/babel-core/src/transformation/file/file.ts b/packages/babel-core/src/transformation/file/file.ts index c7b9e7ee4c35..9d2f19dab57a 100644 --- a/packages/babel-core/src/transformation/file/file.ts +++ b/packages/babel-core/src/transformation/file/file.ts @@ -10,7 +10,7 @@ import semver from "semver"; import type { NormalizedFile } from "../normalize-file.ts"; // @ts-expect-error This file is `any` -import * as babel7 from "./babel-7-helpers.cjs"; +import babel7 from "./babel-7-helpers.cjs" with { BABEL_8_BREAKING: "false" }; const errorVisitor: Visitor<{ loc: t.SourceLocation | null }> = { enter(path, state) { diff --git a/packages/babel-helper-create-class-features-plugin/src/decorators-2018-09.ts b/packages/babel-helper-create-class-features-plugin/src/decorators-2018-09.ts index ae802ca1e12b..fd57436afa35 100644 --- a/packages/babel-helper-create-class-features-plugin/src/decorators-2018-09.ts +++ b/packages/babel-helper-create-class-features-plugin/src/decorators-2018-09.ts @@ -1,4 +1,9 @@ // TODO(Babel 8): Remove this file +if (process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH) { + throw new Error( + "Internal Babel error: This file should only be loaded in Babel 7", + ); +} import { types as t, template } from "@babel/core"; import type { File, NodePath } from "@babel/core"; @@ -6,15 +11,6 @@ import ReplaceSupers from "@babel/helper-replace-supers"; type Decoratable = Extract; -export function hasOwnDecorators(node: t.Class | t.ClassBody["body"][number]) { - // @ts-expect-error: 'decorators' not in TSIndexSignature - return !!node.decorators?.length; -} - -export function hasDecorators(node: t.Class) { - return hasOwnDecorators(node) || node.body.body.some(hasOwnDecorators); -} - function prop(key: string, value?: t.Expression) { if (!value) return null; return t.objectProperty(t.identifier(key), value); diff --git a/packages/babel-helper-create-class-features-plugin/src/decorators.ts b/packages/babel-helper-create-class-features-plugin/src/decorators.ts index 244ce84447b3..aecd2deda109 100644 --- a/packages/babel-helper-create-class-features-plugin/src/decorators.ts +++ b/packages/babel-helper-create-class-features-plugin/src/decorators.ts @@ -9,6 +9,15 @@ import { } from "./fields.ts"; import { memoiseComputedKey } from "./misc.ts"; +export function hasOwnDecorators(node: t.Class | t.ClassBody["body"][number]) { + // @ts-expect-error: 'decorators' not in TSIndexSignature + return !!node.decorators?.length; +} + +export function hasDecorators(node: t.Class) { + return hasOwnDecorators(node) || node.body.body.some(hasOwnDecorators); +} + // We inline this package // eslint-disable-next-line import/no-extraneous-dependencies import * as charCodes from "charcodes"; diff --git a/packages/babel-helper-create-class-features-plugin/src/features.ts b/packages/babel-helper-create-class-features-plugin/src/features.ts index 5104e2bb44ea..d86bf982903a 100644 --- a/packages/babel-helper-create-class-features-plugin/src/features.ts +++ b/packages/babel-helper-create-class-features-plugin/src/features.ts @@ -1,6 +1,6 @@ import type { File, types as t } from "@babel/core"; import type { NodePath } from "@babel/core"; -import { hasOwnDecorators } from "./decorators-2018-09.ts"; +import { hasOwnDecorators } from "./decorators.ts"; export const FEATURES = Object.freeze({ //classes: 1 << 0, diff --git a/packages/babel-helper-create-class-features-plugin/src/index.ts b/packages/babel-helper-create-class-features-plugin/src/index.ts index 8c4a769a8d05..cd0a87eb46a2 100644 --- a/packages/babel-helper-create-class-features-plugin/src/index.ts +++ b/packages/babel-helper-create-class-features-plugin/src/index.ts @@ -1,7 +1,5 @@ import { types as t } from "@babel/core"; import type { PluginAPI, PluginObject, NodePath } from "@babel/core"; -import createDecoratorTransform from "./decorators.ts"; -import type { DecoratorVersionKind } from "./decorators.ts"; import semver from "semver"; @@ -13,7 +11,9 @@ import { buildCheckInRHS, } from "./fields.ts"; import type { PropPath } from "./fields.ts"; -import { buildDecoratedClass, hasDecorators } from "./decorators-2018-09.ts"; +import createDecoratorTransform, { hasDecorators } from "./decorators.ts"; +import type { DecoratorVersionKind } from "./decorators.ts"; +import { buildDecoratedClass } from "./decorators-2018-09.ts" with { BABEL_8_BREAKING: "false" }; import { injectInitialization, extractComputedKeys } from "./misc.ts"; import { enableFeature, diff --git a/packages/babel-plugin-transform-for-of/src/index.ts b/packages/babel-plugin-transform-for-of/src/index.ts index d0a62ba58381..9f47020692fe 100644 --- a/packages/babel-plugin-transform-for-of/src/index.ts +++ b/packages/babel-plugin-transform-for-of/src/index.ts @@ -1,7 +1,7 @@ import { declare } from "@babel/helper-plugin-utils"; import { template, types as t, type NodePath } from "@babel/core"; -import transformWithoutHelper from "./no-helper-implementation.ts"; +import transformWithoutHelper from "./no-helper-implementation.ts" with { BABEL_8_BREAKING: "false" }; import { skipTransparentExprWrapperNodes } from "@babel/helper-skip-transparent-expression-wrappers"; export interface Options { diff --git a/packages/babel-plugin-transform-for-of/src/no-helper-implementation.ts b/packages/babel-plugin-transform-for-of/src/no-helper-implementation.ts index 69d3187f55b4..ac2b33a662b2 100644 --- a/packages/babel-plugin-transform-for-of/src/no-helper-implementation.ts +++ b/packages/babel-plugin-transform-for-of/src/no-helper-implementation.ts @@ -1,3 +1,9 @@ +if (process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH) { + throw new Error( + "Internal Babel error: This file should only be loaded in Babel 7", + ); +} + import { template, types as t } from "@babel/core"; import type { PluginPass, NodePath } from "@babel/core"; diff --git a/packages/babel-plugin-transform-runtime/src/index.ts b/packages/babel-plugin-transform-runtime/src/index.ts index 3c6ff3766ae8..5031037ece91 100644 --- a/packages/babel-plugin-transform-runtime/src/index.ts +++ b/packages/babel-plugin-transform-runtime/src/index.ts @@ -6,7 +6,7 @@ import { hasMinVersion } from "./helpers.ts"; import getRuntimePath, { resolveFSPath } from "./get-runtime-path/index.ts"; // TODO(Babel 8): Remove this -import babel7 from "./babel-7/index.cjs"; +import babel7 from "./babel-7/index.cjs" with { BABEL_8_BREAKING: "false" }; export interface Options { absoluteRuntime?: boolean; diff --git a/packages/babel-preset-env/src/available-plugins.ts b/packages/babel-preset-env/src/available-plugins.ts index a86bae9d1054..b916057fe3b4 100644 --- a/packages/babel-preset-env/src/available-plugins.ts +++ b/packages/babel-preset-env/src/available-plugins.ts @@ -1,6 +1,7 @@ /* eslint sort-keys: "error" */ -import otherBabel7Plugins from "./babel-7-available-plugins.cjs"; +import syntaxImportAssertions from "@babel/plugin-syntax-import-assertions" with { BABEL_8_BREAKING: "false" }; +import syntaxImportAttributes from "@babel/plugin-syntax-import-assertions" with { BABEL_8_BREAKING: "false" }; import transformAsyncGeneratorFunctions from "@babel/plugin-transform-async-generator-functions"; import transformAsyncToGenerator from "@babel/plugin-transform-async-to-generator"; @@ -185,6 +186,11 @@ if (!process.env.BABEL_8_BREAKING) { "syntax-private-property-in-object": syntax("privateIn"), "syntax-top-level-await": syntax("topLevelAwait"), + // These plugins have more logic than just enabling/disabling a feature + // eslint-disable-next-line sort-keys + "syntax-import-assertions": () => syntaxImportAssertions, + "syntax-import-attributes": () => syntaxImportAttributes, + // These are CJS plugins that depend on a package from the monorepo, so it // breaks using ESM. Given that ESM builds are new enough to have this // syntax enabled by default, we can safely skip enabling it. @@ -193,24 +199,6 @@ if (!process.env.BABEL_8_BREAKING) { USE_ESM || IS_STANDALONE ? () => () => ({}) : () => require("@babel/plugin-syntax-unicode-sets-regex"), - - // We need to keep these plugins because they do not simply enable a - // feature, but can affect the AST shape (.attributes vs .assertions). - // TLA is only used for local development with ESM, since we cannot - // require() monorepo files in that case. - // eslint-disable-next-line sort-keys - "syntax-import-assertions": - USE_ESM && !IS_STANDALONE - ? await import("@babel/plugin-syntax-import-assertions").then( - m => () => m.default, - ) - : otherBabel7Plugins["syntax-import-assertions"], - "syntax-import-attributes": - USE_ESM && !IS_STANDALONE - ? await import("@babel/plugin-syntax-import-attributes").then( - m => () => m.default, - ) - : otherBabel7Plugins["syntax-import-attributes"], }; Object.assign(availablePlugins, legacyBabel7SyntaxPluginsLoaders); diff --git a/packages/babel-preset-env/src/babel-7-available-plugins.cjs b/packages/babel-preset-env/src/babel-7-available-plugins.cjs deleted file mode 100644 index c107279ac100..000000000000 --- a/packages/babel-preset-env/src/babel-7-available-plugins.cjs +++ /dev/null @@ -1,15 +0,0 @@ -// TODO(Babel 8): Remove this file - -if (!process.env.BABEL_8_BREAKING) { - // We need to keep these plugins because they do not simply enable a - // feature, but can affect the AST shape (.attributes vs .assertions). - // TLA is only used for local development with ESM. - const availablePlugins = { - "syntax-import-assertions": () => - require("@babel/plugin-syntax-import-assertions"), - "syntax-import-attributes": () => - require("@babel/plugin-syntax-import-attributes"), - }; - - module.exports = availablePlugins; -} diff --git a/packages/babel-preset-env/src/babel-7-available-plugins.d.cts b/packages/babel-preset-env/src/babel-7-available-plugins.d.cts deleted file mode 100644 index 2bcc6e0b69db..000000000000 --- a/packages/babel-preset-env/src/babel-7-available-plugins.d.cts +++ /dev/null @@ -1,7 +0,0 @@ -// TODO(Babel 8): Remove this file - -declare const exp: { - "syntax-import-assertions": Function; - "syntax-import-attributes": Function; -}; -export default exp; diff --git a/packages/babel-preset-env/src/index.ts b/packages/babel-preset-env/src/index.ts index 10888dd0586c..b7a9bb51fc8b 100644 --- a/packages/babel-preset-env/src/index.ts +++ b/packages/babel-preset-env/src/index.ts @@ -24,8 +24,7 @@ import _pluginCoreJS3 from "babel-plugin-polyfill-corejs3"; // TODO(Babel 8): Just use the default import const pluginCoreJS3 = _pluginCoreJS3.default || _pluginCoreJS3; -// TODO(Babel 8): Remove this -import babel7 from "./polyfills/babel-7-plugins.cjs"; +import babel7 from "./polyfills/babel-7-plugins.cjs" with { BABEL_8_BREAKING: "false" }; import getTargets, { prettifyTargets, diff --git a/packages/babel-preset-env/src/normalize-options.ts b/packages/babel-preset-env/src/normalize-options.ts index 11cf03590603..b5c9908a0d8c 100644 --- a/packages/babel-preset-env/src/normalize-options.ts +++ b/packages/babel-preset-env/src/normalize-options.ts @@ -9,8 +9,7 @@ import { } from "./options.ts"; import { OptionValidator } from "@babel/helper-validator-option"; -// TODO(Babel 8): Remove this -import babel7 from "./polyfills/babel-7-plugins.cjs"; +import babel7 from "./polyfills/babel-7-plugins.cjs" with { BABEL_8_BREAKING: "false" }; import type { BuiltInsOption, diff --git a/packages/babel-traverse/src/path/lib/hoister.ts b/packages/babel-traverse/src/path/lib/hoister.ts index 8c915ae7083e..95c11a50ac1a 100644 --- a/packages/babel-traverse/src/path/lib/hoister.ts +++ b/packages/babel-traverse/src/path/lib/hoister.ts @@ -1,4 +1,4 @@ -// Remove this file in Babel 8 +// TODO: Remove this file in Babel 8 import { react } from "@babel/types"; import { diff --git a/packages/babel-traverse/src/path/modification.ts b/packages/babel-traverse/src/path/modification.ts index 9ba5c8ceba2f..be88f3e19979 100644 --- a/packages/babel-traverse/src/path/modification.ts +++ b/packages/babel-traverse/src/path/modification.ts @@ -1,7 +1,6 @@ // This file contains methods that modify the path/node in some ways. import { getCachedPaths } from "../cache.ts"; -import PathHoister from "./lib/hoister.ts"; import NodePath from "./index.ts"; import { _getQueueContexts, pushContext, setScope } from "./context.ts"; import { _assertUnremoved } from "./removal.ts"; @@ -403,6 +402,7 @@ export function pushContainer< return path.replaceWithMultiple(verifiedNodes); } +import PathHoister from "./lib/hoister.ts" with { BABEL_8_BREAKING: "false", USE_ESM: "false" }; if (!process.env.BABEL_8_BREAKING && !USE_ESM) { /** * Hoist the current node to the highest scope possible and return a UID diff --git a/packages/babel-types/src/converters/gatherSequenceExpressions.ts b/packages/babel-types/src/converters/gatherSequenceExpressions.ts index f00525b1f9f0..7952b751199b 100644 --- a/packages/babel-types/src/converters/gatherSequenceExpressions.ts +++ b/packages/babel-types/src/converters/gatherSequenceExpressions.ts @@ -1,5 +1,5 @@ // TODO(Babel 8) Remove this file -if (process.env.BABEL_8_BREAKING) { +if (process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH) { throw new Error( "Internal Babel error: This file should only be loaded in Babel 7", ); diff --git a/packages/babel-types/src/converters/toSequenceExpression.ts b/packages/babel-types/src/converters/toSequenceExpression.ts index 6619a1ceeace..4253e1547fa6 100644 --- a/packages/babel-types/src/converters/toSequenceExpression.ts +++ b/packages/babel-types/src/converters/toSequenceExpression.ts @@ -1,5 +1,5 @@ // TODO(Babel 8) Remove this file -if (process.env.BABEL_8_BREAKING) { +if (process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH) { throw new Error( "Internal Babel error: This file should only be loaded in Babel 7", ); diff --git a/packages/babel-types/src/index.ts b/packages/babel-types/src/index.ts index 231465c15e6c..b3c99b60f6d7 100644 --- a/packages/babel-types/src/index.ts +++ b/packages/babel-types/src/index.ts @@ -109,11 +109,10 @@ export type * from "./ast-types/generated/index.ts"; // this is used by @babel/traverse to warn about deprecated visitors export { default as __internal__deprecationWarning } from "./utils/deprecationWarning.ts"; +import toSequenceExpression from "./converters/toSequenceExpression.ts" with { BABEL_8_BREAKING: "false", USE_ESM: "false", IS_STANDALONE: "false" }; if (!process.env.BABEL_8_BREAKING && !USE_ESM && !IS_STANDALONE) { // eslint-disable-next-line no-restricted-globals - exports.toSequenceExpression = - // eslint-disable-next-line no-restricted-globals - require("./converters/toSequenceExpression.js").default; + exports.toSequenceExpression = toSequenceExpression; } if (!process.env.BABEL_8_BREAKING && process.env.BABEL_TYPES_8_BREAKING) {