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

[babel 8] Better file ext handling for TS and Flow presets #14955

Merged
merged 8 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/babel-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"@babel/plugin-transform-flow-strip-types": "workspace:^",
"@babel/plugin-transform-modules-commonjs": "workspace:^",
"@babel/preset-env": "workspace:^",
"@babel/preset-typescript": "workspace:^",
"@jridgewell/trace-mapping": "^0.3.17",
"@types/convert-source-map": "^1.5.1",
"@types/debug": "^4.1.0",
Expand Down
7 changes: 3 additions & 4 deletions packages/babel-core/src/config/files/module-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,11 @@ function loadCtsDefault(filepath: string) {
getTSPreset(filepath),
{
disallowAmbiguousJSXLike: true,
allExtensions: true,
onlyRemoveTypeImports: true,
optimizeConstEnums: true,
...(!process.env.BABEL_8_BREAKING && {
allowDeclareFields: true,
}),
...(process.env.BABEL_8_BREAKING
? { ignoreExtensions: true }
: { allExtensions: true, allowDeclareFields: true }),
},
],
],
Expand Down
119 changes: 63 additions & 56 deletions packages/babel-core/test/config-ts.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import { loadPartialConfigSync } from "../lib/index.js";
import path from "path";
import { readFileSync } from "fs";
import { fileURLToPath } from "url";
import { createRequire } from "module";
import semver from "semver";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);

let USE_ESM = false;
try {
const type = readFileSync(
new URL("../../../.module-type", import.meta.url),
"utf-8",
).trim();
USE_ESM = type === "module";
} catch {}

// We skip older versions of node testing for two reasons.
// 1. ts-node does not support the old version of node.
// 2. In the old version of node, jest has been registered in `require.extensions`, which will cause babel to disable the transforming as expected.
// TODO: Make it work with USE_ESM.
const shouldSkip = semver.lt(process.version, "12.0.0") || USE_ESM;

const lessThanNode12 = semver.lt(process.version, "12.0.0");

(lessThanNode12 ? describe : describe.skip)(
(shouldSkip ? describe : describe.skip)(
"@babel/core config with ts [dummy]",
() => {
it("dummy", () => {
Expand All @@ -22,72 +32,69 @@ const lessThanNode12 = semver.lt(process.version, "12.0.0");
},
);

(lessThanNode12 ? describe.skip : describe)(
"@babel/core config with ts",
() => {
it("should work with simple .cts", () => {
const config = loadPartialConfigSync({
configFile: path.join(
__dirname,
"fixtures/config-ts/simple-cts/babel.config.cts",
),
});
(shouldSkip ? describe.skip : describe)("@babel/core config with ts", () => {
it("should work with simple .cts", () => {
const config = loadPartialConfigSync({
configFile: path.join(
__dirname,
"fixtures/config-ts/simple-cts/babel.config.cts",
),
});

expect(config.options.targets).toMatchInlineSnapshot(`
expect(config.options.targets).toMatchInlineSnapshot(`
Object {
"node": "12.0.0",
}
`);
});
});

it("should throw with invalid .ts register", () => {
require.extensions[".ts"] = () => {
throw new Error("Not support .ts.");
};
try {
expect(() => {
loadPartialConfigSync({
configFile: path.join(
__dirname,
"fixtures/config-ts/invalid-cts-register/babel.config.cts",
),
});
}).toThrow(/Unexpected identifier.*/);
} finally {
delete require.extensions[".ts"];
}
});

it("should throw with invalid .ts register", () => {
require.extensions[".ts"] = () => {
throw new Error("Not support .ts.");
};
try {
expect(() => {
loadPartialConfigSync({
configFile: path.join(
__dirname,
"fixtures/config-ts/invalid-cts-register/babel.config.cts",
),
});
}).toThrow(/Unexpected identifier.*/);
} finally {
delete require.extensions[".ts"];
}
it("should work with ts-node", async () => {
const service = require("ts-node").register({
experimentalResolver: true,
compilerOptions: {
module: "CommonJS",
},
});
service.enabled(true);

it("should work with ts-node", async () => {
const service = require("ts-node").register({
experimentalResolver: true,
compilerOptions: {
module: "CommonJS",
},
});
service.enabled(true);
try {
require(path.join(
__dirname,
"fixtures/config-ts/simple-cts-with-ts-node/babel.config.cts",
));

try {
require(path.join(
const config = loadPartialConfigSync({
configFile: path.join(
__dirname,
"fixtures/config-ts/simple-cts-with-ts-node/babel.config.cts",
));

const config = loadPartialConfigSync({
configFile: path.join(
__dirname,
"fixtures/config-ts/simple-cts-with-ts-node/babel.config.cts",
),
});
),
});

expect(config.options.targets).toMatchInlineSnapshot(`
expect(config.options.targets).toMatchInlineSnapshot(`
Object {
"node": "12.0.0",
}
`);
} finally {
service.enabled(false);
}
});
},
);
} finally {
service.enabled(false);
}
});
});
18 changes: 10 additions & 8 deletions packages/babel-plugin-syntax-flow/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ export default declare((api, options: FlowPluginOptions) => {
name: "syntax-flow",

manipulateOptions(opts, parserOpts) {
// If the file has already enabled TS, assume that this is not a
// valid Flowtype file.
if (
parserOpts.plugins.some(
p => (Array.isArray(p) ? p[0] : p) === "typescript",
)
) {
return;
if (!process.env.BABEL_8_BREAKING) {
// If the file has already enabled TS, assume that this is not a
// valid Flowtype file.
if (
parserOpts.plugins.some(
p => (Array.isArray(p) ? p[0] : p) === "typescript",
)
) {
return;
}
}

parserOpts.plugins.push(["flow", { all, enums }]);
Expand Down
17 changes: 11 additions & 6 deletions packages/babel-plugin-syntax-jsx/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ export default declare(api => {
name: "syntax-jsx",

manipulateOptions(opts, parserOpts) {
const { plugins } = parserOpts;
// If the Typescript plugin already ran, it will have decided whether
// or not this is a TSX file.
if (plugins.some(p => (Array.isArray(p) ? p[0] : p) === "typescript")) {
return;
if (!process.env.BABEL_8_BREAKING) {
// If the Typescript plugin already ran, it will have decided whether
// or not this is a TSX file.
if (
parserOpts.plugins.some(
p => (Array.isArray(p) ? p[0] : p) === "typescript",
)
) {
return;
}
}

plugins.push("jsx");
parserOpts.plugins.push("jsx");
},
};
});
70 changes: 39 additions & 31 deletions packages/babel-plugin-syntax-typescript/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { declare } from "@babel/helper-plugin-utils";
import type { ParserPlugin } from "@babel/parser";

function removePlugin(plugins: ParserPlugin[], name: string) {
const indices: number[] = [];
plugins.forEach((plugin, i) => {
const n = Array.isArray(plugin) ? plugin[0] : plugin;
if (!process.env.BABEL_8_BREAKING) {
// eslint-disable-next-line no-var
var removePlugin = function (plugins: any[], name: string) {
const indices: number[] = [];
plugins.forEach((plugin, i) => {
const n = Array.isArray(plugin) ? plugin[0] : plugin;

if (n === name) {
indices.unshift(i);
}
});
if (n === name) {
indices.unshift(i);
}
});

for (const i of indices) {
plugins.splice(i, 1);
}
for (const i of indices) {
plugins.splice(i, 1);
}
};
}

export interface Options {
Expand All @@ -22,14 +24,21 @@ export interface Options {
isTSX?: boolean;
}

export default declare(
(api, { disallowAmbiguousJSXLike, dts, isTSX }: Options) => {
api.assertVersion(7);
export default declare((api, opts: Options) => {
api.assertVersion(7);

return {
name: "syntax-typescript",
const { disallowAmbiguousJSXLike, dts } = opts;

if (!process.env.BABEL_8_BREAKING) {
// eslint-disable-next-line no-var
var { isTSX } = opts;
}

manipulateOptions(opts, parserOpts) {
return {
name: "syntax-typescript",

manipulateOptions(opts, parserOpts) {
if (!process.env.BABEL_8_BREAKING) {
const { plugins } = parserOpts;
// If the Flow syntax plugin already ran, remove it since Typescript
// takes priority.
Expand All @@ -39,20 +48,19 @@ export default declare(
// in TS depends on the extensions, and is purely dependent on 'isTSX'.
removePlugin(plugins, "jsx");

plugins.push(
["typescript", { disallowAmbiguousJSXLike, dts }],
"classProperties",
);

if (!process.env.BABEL_8_BREAKING) {
// This is enabled by default since @babel/parser 7.1.5
plugins.push("objectRestSpread");
}
// These are now enabled by default in @babel/parser, but we push
// them for compat with older versions.
plugins.push("objectRestSpread", "classProperties");

if (isTSX) {
plugins.push("jsx");
}
},
};
},
);
}

parserOpts.plugins.push([
"typescript",
{ disallowAmbiguousJSXLike, dts },
]);
},
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["transform-parameters", "syntax-flow"]
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"plugins": [
"proposal-class-properties",
"syntax-typescript",
"syntax-flow",
"transform-parameters",
"transform-block-scoping",
"transform-spread",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"plugins": [
"transform-parameters",
"syntax-typescript",
"transform-block-scoping",
"transform-destructuring"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["transform-parameters", "syntax-typescript"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export namespace Namespaced {
export const Component = () => (
<div>Hello, world!</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"BABEL_8_BREAKING": false,
"plugins": [
"transform-react-jsx-development",
["syntax-typescript", { "isTSX": true }]
],
"sourceType": "module",
"os": ["linux", "darwin"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var _jsxFileName = "<CWD>/packages/babel-plugin-transform-react-jsx-development/test/fixtures/linux/within-ts-module-block-babel-7/input.ts";
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
export namespace Namespaced {
export const Component = () => /*#__PURE__*/_jsxDEV("div", {
children: "Hello, world!"
}, void 0, false, {
fileName: _jsxFileName,
lineNumber: 3,
columnNumber: 3
}, this);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"BABEL_8_BREAKING": true,
"plugins": [
"transform-react-jsx-development",
["syntax-typescript", { "isTSX": true }]
"syntax-typescript",
"syntax-jsx"
],
"sourceType": "module",
"os": ["linux", "darwin"]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export namespace Namespaced {
export const Component = () => (
<div>Hello, world!</div>
);
}