Skip to content

Commit 2ea9054

Browse files
Avoid dynamic import when it's not needed (#14192)
1 parent e5d29f6 commit 2ea9054

2 files changed

Lines changed: 25 additions & 21 deletions

File tree

packages/babel-core/src/config/files/import-meta-resolve.ts

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,38 @@ try {
1010
} catch {}
1111

1212
// import.meta.resolve is only available in ESM, but this file is compiled to CJS.
13-
// We can extract ir using dynamic import.
14-
const resolveP =
13+
// We can extract it using dynamic import.
14+
const importMetaResolveP: Promise<ImportMeta["resolve"]> =
1515
import_ &&
1616
// Due to a Node.js/V8 bug (https://github.com/nodejs/node/issues/35889), we cannot
17-
// use dynamic import when running in the default Jest environment because it
18-
// uses vm.SourceTextModule.
19-
// Jest defines globalThis["jest-symbol-do-not-touch"] in
20-
// https://github.com/facebook/jest/blob/11d79ec096a25851124356095d60352f6ca2824e/packages/jest-util/src/installCommonGlobals.ts#L49
21-
// which is called by
22-
// https://github.com/facebook/jest/blob/11d79ec096a25851124356095d60352f6ca2824e/packages/jest-environment-node/src/index.ts#L85
17+
// use always dynamic import because it segfaults when running in a Node.js `vm` context,
18+
// which is used by the default Jest environment and by webpack-cli.
2319
//
24-
// Note that our Jest runner doesn't have this problem, because it runs ESM in the default
25-
// Node.js context rather than using the `vm` module.
20+
// However, import.meta.resolve is experimental and only enabled when Node.js is run
21+
// with the `--experimental-import-meta-resolve` flag: we can avoid calling import()
22+
// when that flag is not enabled, so that the default behavior never segfaults.
2623
//
27-
// When V8 fixes this bug, we can remove this check. We usually don't have package-specific hacks,
28-
// but Jest is a big Babel consumer widely used in the community and they cannot workaround
29-
// this problem on their side.
30-
!Object.hasOwnProperty.call(global, "jest-symbol-do-not-touch")
24+
// Hopefully, before Node.js unflags import.meta.resolve, either:
25+
// - we will move to ESM, so that we have direct access to import.meta.resolve, or
26+
// - the V8 bug will be fixed so that we can safely use dynamic import by default.
27+
//
28+
// I (@nicolo-ribaudo) am really anoyed by this bug, because there is no known
29+
// work-around other than "don't use dynamic import if you are running in a `vm` context",
30+
// but there is no reliable way to detect it (you cannot try/catch segfaults).
31+
//
32+
// This is the only place where we *need* to use dynamic import because we need to access
33+
// an ES module. All the other places will first try using require() and *then*, if
34+
// it throws because it's a module, will fallback to import().
35+
process.execArgv.includes("--experimental-import-meta-resolve")
3136
? import_("data:text/javascript,export default import.meta.resolve").then(
32-
// Since import.meta.resolve is unstable and only available when
33-
// using the --experimental-import-meta-resolve flag, we almost
34-
// always use the polyfill for now.
3537
m => m.default || polyfill,
3638
() => polyfill,
3739
)
3840
: Promise.resolve(polyfill);
3941

40-
export default function getImportMetaResolve(): Promise<ImportMeta["resolve"]> {
41-
return resolveP;
42+
export default async function resolve(
43+
specifier: Parameters<ImportMeta["resolve"]>[0],
44+
parent?: Parameters<ImportMeta["resolve"]>[1],
45+
): ReturnType<ImportMeta["resolve"]> {
46+
return (await importMetaResolveP)(specifier, parent);
4247
}

packages/babel-core/src/config/files/plugins.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { isAsync } from "../../gensync-utils/async";
99
import loadCjsOrMjsDefault, { supportsESM } from "./module-types";
1010
import { fileURLToPath, pathToFileURL } from "url";
1111

12-
import getImportMetaResolve from "./import-meta-resolve";
12+
import importMetaResolve from "./import-meta-resolve";
1313

1414
import { createRequire } from "module";
1515
const require = createRequire(import.meta.url);
@@ -134,7 +134,6 @@ async function tryImportMetaResolve(
134134
id: Parameters<ImportMeta["resolve"]>[0],
135135
options: Parameters<ImportMeta["resolve"]>[1],
136136
): Promise<Result<string>> {
137-
const importMetaResolve = await getImportMetaResolve();
138137
try {
139138
return { error: null, value: await importMetaResolve(id, options) };
140139
} catch (error) {

0 commit comments

Comments
 (0)