Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Babel 7 plugins compatibility with Babel 8 core #16332

Merged
merged 10 commits into from Mar 7, 2024
1 change: 1 addition & 0 deletions .github/workflows/e2e-tests-breaking-esm.yml
Expand Up @@ -53,6 +53,7 @@ jobs:
# todo: verify which of these tests can be re-enabled
project:
- babel
- babel7plugins-babel8core
- create-react-app
# - vue-cli
# - jest
Expand Down
67 changes: 67 additions & 0 deletions babel.config.js
Expand Up @@ -13,6 +13,8 @@ if (typeof it === "function") {
const pathUtils = require("path");
const fs = require("fs");
const { parseSync } = require("@babel/core");
const packageJson = require("./package.json");
const babel7_8compat = require("./test/babel-7-8-compat/data.json");

function normalize(src) {
return src.replace(/\//, pathUtils.sep);
Expand Down Expand Up @@ -251,6 +253,26 @@ module.exports = function (api) {

pluginPackageJsonMacro,

[
pluginRequiredVersionMacro,
{
allowAny: !process.env.IS_PUBLISH || env === "standalone",
overwrite(requiredVersion, filename) {
if (requiredVersion === 7) requiredVersion = "^7.0.0-0";
if (process.env.BABEL_8_BREAKING) {
return packageJson.version;
}
const match = filename.match(/packages[\\/](.+?)[\\/]/);
if (
match &&
babel7_8compat["babel7plugins-babel8core"].includes(match[1])
) {
return `${requiredVersion} || >8.0.0-alpha <8.0.0-beta`;
}
},
},
],

needsPolyfillsForOldNode && pluginPolyfillsOldNode,
].filter(Boolean),
},
Expand Down Expand Up @@ -665,6 +687,51 @@ function pluginPackageJsonMacro({ types: t }) {
};
}

function pluginRequiredVersionMacro({ types: t }, { allowAny, overwrite }) {
const fnName = "REQUIRED_VERSION";

return {
visitor: {
ReferencedIdentifier(path) {
if (path.isIdentifier({ name: fnName })) {
throw path.buildCodeFrameError(
`"${fnName}" is only supported in call expressions.`
);
}
},
CallExpression(path) {
if (!path.get("callee").isIdentifier({ name: fnName })) return;

if (path.node.arguments.length !== 1) {
throw path.buildCodeFrameError(
`"${fnName}" expects exactly one argument.`
);
}

const arg = path.get("arguments.0").evaluate().value;
if (!arg) {
throw path.buildCodeFrameError(
`"${fnName}" expects a literal argument.`
);
}

if (allowAny) {
path.replaceWith(t.stringLiteral("*"));
return;
}

const version = overwrite(arg, this.filename);
if (version != null) {
path.replaceWith(t.stringLiteral(version));
return;
}

path.replaceWith(path.node.arguments[0]);
},
},
};
}

// transform `import { x } from "@babel/types"` to `import * as _t from "@babel/types"; const { x } = _t;
function transformNamedBabelTypesImportToDestructuring({
types: {
Expand Down
5 changes: 1 addition & 4 deletions eslint/babel-eslint-parser/src/parse.cts
Expand Up @@ -15,10 +15,7 @@ let isRunningMinSupportedCoreVersion: boolean = null;

export = function parse(code: string, options: Options, client: Client) {
// Ensure we're using a version of `@babel/core` that includes `parse()` and `tokTypes`.
const minSupportedCoreVersion =
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: ">=7.2.0";
const minSupportedCoreVersion = REQUIRED_VERSION(">=7.2.0");

if (typeof isRunningMinSupportedCoreVersion !== "boolean") {
isRunningMinSupportedCoreVersion = semver.satisfies(
Expand Down
2 changes: 2 additions & 0 deletions lib/globals.d.ts
@@ -1,6 +1,8 @@
declare const USE_ESM: boolean;
declare const IS_STANDALONE: boolean;
declare const PACKAGE_JSON: { name: string; version: string };
declare function REQUIRED_VERSION(version: number): number | string;
declare function REQUIRED_VERSION(version: string): string;

declare namespace NodeJS {
export interface ProcessEnv {
Expand Down
Expand Up @@ -2147,18 +2147,18 @@ export default function (
inherits: PluginObject["inherits"],
): PluginObject {
if (process.env.BABEL_8_BREAKING) {
assertVersion(process.env.IS_PUBLISH ? PACKAGE_JSON.version : "^7.21.0");
assertVersion(REQUIRED_VERSION("^7.21.0"));
} else {
if (
version === "2023-11" ||
version === "2023-05" ||
version === "2023-01"
) {
assertVersion("^7.21.0");
assertVersion(REQUIRED_VERSION("^7.21.0"));
} else if (version === "2021-12") {
assertVersion("^7.16.0");
assertVersion(REQUIRED_VERSION("^7.16.0"));
} else {
assertVersion("^7.19.0");
assertVersion(REQUIRED_VERSION("^7.19.0"));
}
}

Expand Down
Expand Up @@ -2,11 +2,7 @@ import { declare } from "@babel/helper-plugin-utils";
import { shouldTransform } from "./util.ts";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.16.0",
);
api.assertVersion(REQUIRED_VERSION("^7.16.0"));

return {
name: "plugin-bugfix-safari-id-destructuring-collision-in-function-expression",
Expand Down
Expand Up @@ -5,11 +5,7 @@ import type { NodePath } from "@babel/traverse";
import type * as t from "@babel/types";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

const noDocumentAll = api.assumption("noDocumentAll") ?? false;
const pureGetters = api.assumption("pureGetters") ?? false;
Expand Down
Expand Up @@ -32,11 +32,7 @@ function buildFieldsReplacement(
}

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

const setPublicClassFields = api.assumption("setPublicClassFields");

Expand Down
6 changes: 1 addition & 5 deletions packages/babel-plugin-external-helpers/src/index.ts
Expand Up @@ -7,11 +7,7 @@ export interface Options {
}

export default declare((api, options: Options) => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

const { helperVersion = "7.0.0-beta.0", whitelist = false } = options;

Expand Down
Expand Up @@ -4,11 +4,7 @@ import hoistVariables from "@babel/helper-hoist-variables";
import type * as t from "@babel/types";

export default declare(({ types: t, assertVersion }) => {
assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.13.0",
);
assertVersion(REQUIRED_VERSION("^7.13.0"));

return {
name: "proposal-async-do-expressions",
Expand Down
12 changes: 2 additions & 10 deletions packages/babel-plugin-proposal-decorators/src/index.ts
Expand Up @@ -17,11 +17,7 @@ interface Options extends SyntaxOptions {
export type { Options };

export default declare((api, options: Options) => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

// Options are validated in @babel/plugin-syntax-decorators
if (!process.env.BABEL_8_BREAKING) {
Expand Down Expand Up @@ -49,11 +45,7 @@ export default declare((api, options: Options) => {
version === "2023-05" ||
version === "2023-11"
) {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.0.2",
);
api.assertVersion(REQUIRED_VERSION("^7.0.2"));
return createClassFeaturePlugin({
name: "proposal-decorators",

Expand Down
Expand Up @@ -14,11 +14,7 @@ import type { NodePath, Visitor } from "@babel/traverse";
import type * as t from "@babel/types";

export default declare(function ({ assertVersion, assumption, types: t }) {
assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.17.0",
);
assertVersion(REQUIRED_VERSION("^7.17.0"));
const {
assignmentExpression,
assignmentPattern,
Expand Down
6 changes: 1 addition & 5 deletions packages/babel-plugin-proposal-do-expressions/src/index.ts
Expand Up @@ -2,11 +2,7 @@ import { declare } from "@babel/helper-plugin-utils";
import syntaxDoExpressions from "@babel/plugin-syntax-do-expressions";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

return {
name: "proposal-do-expressions",
Expand Down
Expand Up @@ -7,11 +7,7 @@ export interface Options {
}

export default declare((api, options: Options) => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.19.0",
);
api.assertVersion(REQUIRED_VERSION("^7.19.0"));

const { runtime } = options;
if (runtime !== undefined && typeof runtime !== "boolean") {
Expand Down
Expand Up @@ -9,11 +9,7 @@ const enum USING_KIND {
}

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.22.0",
);
api.assertVersion(REQUIRED_VERSION("^7.22.0"));

const TOP_LEVEL_USING = new Map<t.Node, USING_KIND>();

Expand Down
Expand Up @@ -3,11 +3,7 @@ import syntaxExportDefaultFrom from "@babel/plugin-syntax-export-default-from";
import { types as t } from "@babel/core";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

return {
name: "proposal-export-default-from",
Expand Down
6 changes: 1 addition & 5 deletions packages/babel-plugin-proposal-function-bind/src/index.ts
Expand Up @@ -4,11 +4,7 @@ import { types as t } from "@babel/core";
import type { Scope } from "@babel/traverse";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

function getTempId(scope: Scope) {
let id = scope.path.getData("functionBind");
Expand Down
6 changes: 1 addition & 5 deletions packages/babel-plugin-proposal-function-sent/src/index.ts
Expand Up @@ -5,11 +5,7 @@ import { types as t } from "@babel/core";
import type { Visitor } from "@babel/traverse";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

const isFunctionSent = (node: t.MetaProperty) =>
t.isIdentifier(node.meta, { name: "function" }) &&
Expand Down
Expand Up @@ -4,11 +4,7 @@ import type * as t from "@babel/types";
import syntaxImportAttributes from "@babel/plugin-syntax-import-attributes";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

return {
name: "proposal-import-attributes-to-assertions",
Expand Down
6 changes: 1 addition & 5 deletions packages/babel-plugin-proposal-import-defer/src/index.ts
Expand Up @@ -6,11 +6,7 @@ import { defineCommonJSHook } from "@babel/plugin-transform-modules-commonjs";
import syntaxImportDefer from "@babel/plugin-syntax-import-defer";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.23.0",
);
api.assertVersion(REQUIRED_VERSION("^7.23.0"));
// We need the explicit type annotation otherwise when using t.assert* ts
// reports that 'Assertions require every name in the call target to be
// declared with an explicit type annotation'
Expand Down
Expand Up @@ -11,11 +11,7 @@ import {

export default declare(api => {
const { types: t, template } = api;
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.23.0",
);
api.assertVersion(REQUIRED_VERSION("^7.23.0"));

const targets = api.targets();

Expand Down
6 changes: 1 addition & 5 deletions packages/babel-plugin-proposal-json-modules/src/index.ts
Expand Up @@ -10,11 +10,7 @@ import {

export default declare(api => {
const { types: t, template } = api;
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.22.0",
);
api.assertVersion(REQUIRED_VERSION("^7.22.0"));

const targets = api.targets();

Expand Down
Expand Up @@ -6,11 +6,7 @@ import { skipTransparentExprWrappers } from "@babel/helper-skip-transparent-expr
import { transformOptionalChain } from "@babel/plugin-transform-optional-chaining";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: "^7.22.5",
);
api.assertVersion(REQUIRED_VERSION("^7.22.5"));

const assumptions = {
noDocumentAll: api.assumption("noDocumentAll") ?? false,
Expand Down
Expand Up @@ -4,11 +4,7 @@ import { types as t } from "@babel/core";
import type { Scope } from "@babel/traverse";

export default declare(api => {
api.assertVersion(
process.env.BABEL_8_BREAKING && process.env.IS_PUBLISH
? PACKAGE_JSON.version
: 7,
);
api.assertVersion(REQUIRED_VERSION(7));

/**
* a function to figure out if a call expression has
Expand Down