forked from babel/babel
/
import-meta-resolve.ts
47 lines (43 loc) · 2.17 KB
/
import-meta-resolve.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import { createRequire } from "module";
import { resolve as polyfill } from "../../vendor/import-meta-resolve";
const require = createRequire(import.meta.url);
let import_;
try {
// Node < 13.3 doesn't support import() syntax.
import_ = require("./import").default;
} catch {}
// import.meta.resolve is only available in ESM, but this file is compiled to CJS.
// We can extract it using dynamic import.
const importMetaResolveP: Promise<ImportMeta["resolve"]> =
import_ &&
// Due to a Node.js/V8 bug (https://github.com/nodejs/node/issues/35889), we cannot
// use always dynamic import because it segfaults when running in a Node.js `vm` context,
// which is used by the default Jest environment and by webpack-cli.
//
// However, import.meta.resolve is experimental and only enabled when Node.js is run
// with the `--experimental-import-meta-resolve` flag: we can avoid calling import()
// when that flag is not enabled, so that the default behavior never segfaults.
//
// Hopefully, before Node.js unflags import.meta.resolve, either:
// - we will move to ESM, so that we have direct access to import.meta.resolve, or
// - the V8 bug will be fixed so that we can safely use dynamic import by default.
//
// I (@nicolo-ribaudo) am really anoyed by this bug, because there is no known
// work-around other than "don't use dynamic import if you are running in a `vm` context",
// but there is no reliable way to detect it (you cannot try/catch segfaults).
//
// This is the only place where we *need* to use dynamic import because we need to access
// an ES module. All the other places will first try using require() and *then*, if
// it throws because it's a module, will fallback to import().
process.execArgv.includes("--experimental-import-meta-resolve")
? import_("data:text/javascript,export default import.meta.resolve").then(
m => m.default || polyfill,
() => polyfill,
)
: Promise.resolve(polyfill);
export default async function resolve(
specifier: Parameters<ImportMeta["resolve"]>[0],
parent?: Parameters<ImportMeta["resolve"]>[1],
): ReturnType<ImportMeta["resolve"]> {
return (await importMetaResolveP)(specifier, parent);
}