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

feat: support async plugin's pre/post #16862

Merged
merged 3 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: add isAsync on PluginPass
  • Loading branch information
timofei-iatsenko committed Oct 20, 2024
commit 166c7ffc33867ba740919322e3c46b5d8a430600
6 changes: 4 additions & 2 deletions packages/babel-core/src/transformation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import generateCode from "./file/generate.ts";
import type File from "./file/file.ts";

import { flattenToSet } from "../config/helpers/deep-array.ts";
import { maybeAsync } from "../gensync-utils/async.ts";
import { isAsync, maybeAsync } from "../gensync-utils/async.ts";

export type FileResultCallback = {
(err: Error, file: null): void;
Expand Down Expand Up @@ -80,13 +80,15 @@ export function* run(
}

function* transformFile(file: File, pluginPasses: PluginPasses): Handler<void> {
const async = yield* isAsync();

for (const pluginPairs of pluginPasses) {
const passPairs: [Plugin, PluginPass][] = [];
const passes = [];
const visitors = [];

for (const plugin of pluginPairs.concat([loadBlockHoistPlugin()])) {
const pass = new PluginPass(file, plugin.key, plugin.options);
const pass = new PluginPass(file, plugin.key, plugin.options, async);

passPairs.push([plugin, pass]);
passes.push(pass);
Expand Down
21 changes: 17 additions & 4 deletions packages/babel-core/src/transformation/plugin-pass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,32 @@ export default class PluginPass<Options = object> {
file: File;
opts: Partial<Options>;

// The working directory that Babel's programmatic options are loaded
// relative to.
/**
* The working directory that Babel's programmatic options are loaded
* relative to.
*/
cwd: string;

// The absolute path of the file being compiled.
/** The absolute path of the file being compiled. */
filename: string | void;
Comment on lines +10 to 17
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With /** style of comment it's a jsdoc description which could be used as quick documentation in IDE.


constructor(file: File, key?: string | null, options?: Options) {
/**
* Is Babel executed in async mode or not.
*/
isAsync: boolean | undefined;

constructor(
file: File,
key?: string | null,
options?: Options,
isAsync?: boolean,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i've added isAsync as optional argument to the last position, so it shouldn't be a breaking change to anyone who uses PluginPass constructor directly. However, i would like to add it as required argument after the file. Let me know if that change is acceptable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only export PluginPass as a type and not as a constructor (see packages/babel-core/src/index.ts), so it should be fine to add it as a required property here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, you can just remove the ?s from the other arguments since they are always always passed. It's probably a leftover from when we converted the repo from Flow to TS.

) {
this.key = key;
this.file = file;
this.opts = options || {};
this.cwd = file.opts.cwd;
this.filename = file.opts.filename;
this.isAsync = isAsync;
}

set(key: unknown, val: unknown) {
Expand Down
28 changes: 27 additions & 1 deletion packages/babel-core/test/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,32 @@ describe("asynchronicity", () => {
});
});

describe("PluginPass.isAsync", () => {
nodeGte8("called synchronously", () => {
process.chdir("plugin-pass-is-async");

expect(babel.transformSync("")).toMatchObject({
code: `"sync"`,
});
});

nodeGte8("called asynchronously", async () => {
process.chdir("plugin-pass-is-async");

await expect(babel.transformAsync("")).resolves.toMatchObject({
code: `"async"`,
});
});

nodeGte8("should await inherited .pre", async () => {
process.chdir("plugin-pre-chaining");

await expect(babel.transformAsync("")).resolves.toMatchObject({
code: `"pluginC,pluginB,pluginA"`,
});
});
});

describe("inherits", () => {
nodeGte8("called synchronously", () => {
process.chdir("plugin-inherits");
Expand Down Expand Up @@ -312,7 +338,7 @@ describe("asynchronicity", () => {
});

describe("misc", () => {
it("unknown preset in config file does not trigget unhandledRejection if caught", async () => {
it("unknown preset in config file does not trigger unhandledRejection if caught", async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed a typo

process.chdir("unknown-preset");
const handler = jest.fn();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
plugins: ["./plugin"],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = function pluginA({ types: t }) {
return {
visitor: {
Program(path) {
const label = this.isAsync ? "async" : "sync";

path.pushContainer("body", t.stringLiteral(label));
},
},
};
};
Loading