-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
/
module-types.ts
174 lines (156 loc) 路 5.14 KB
/
module-types.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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import { isAsync, waitFor } from "../../gensync-utils/async";
import type { Handler } from "gensync";
import path from "path";
import { pathToFileURL } from "url";
import { createRequire } from "module";
import semver from "semver";
import { endHiddenCallStack } from "../../errors/rewrite-stack-trace";
import ConfigError from "../../errors/config-error";
import type { InputOptions } from "..";
import { transformFileSync } from "../../transform-file";
const require = createRequire(import.meta.url);
let import_: ((specifier: string | URL) => any) | undefined;
try {
// Old Node.js versions don't support import() syntax.
import_ = require("./import.cjs");
} catch {}
export const supportsESM = semver.satisfies(
process.versions.node,
// older versions, starting from 10, support the dynamic
// import syntax but always return a rejected promise.
"^12.17 || >=13.2",
);
export default function* loadCodeDefault(
filepath: string,
asyncError: string,
// TODO(Babel 8): Remove this
fallbackToTranspiledModule: boolean = false,
): Handler<unknown> {
switch (path.extname(filepath)) {
case ".cjs":
return loadCjsDefault(filepath, fallbackToTranspiledModule);
case ".mjs":
break;
case ".cts":
return loadCtsDefault(filepath);
default:
try {
return loadCjsDefault(filepath, fallbackToTranspiledModule);
} catch (e) {
if (e.code !== "ERR_REQUIRE_ESM") throw e;
}
}
if (yield* isAsync()) {
return yield* waitFor(loadMjsDefault(filepath));
}
throw new ConfigError(asyncError, filepath);
}
function loadCtsDefault(filepath: string) {
const ext = ".cts";
const hasTsSupport = !!(
require.extensions[".ts"] ||
require.extensions[".cts"] ||
require.extensions[".mts"]
);
let handler: NodeJS.RequireExtensions[""];
if (!hasTsSupport) {
const opts: InputOptions = {
babelrc: false,
configFile: false,
sourceType: "unambiguous",
sourceMaps: "inline",
sourceFileName: path.basename(filepath),
presets: [
[
getTSPreset(filepath),
{
onlyRemoveTypeImports: true,
optimizeConstEnums: true,
...(process.env.BABEL_8_BREAKING
? {}
: { allowDeclareFields: true }),
},
],
],
};
handler = function (m, filename) {
// If we want to support `.ts`, `.d.ts` must be handled specially.
if (handler && filename.endsWith(ext)) {
try {
// @ts-expect-error Undocumented API
return m._compile(
transformFileSync(filename, {
...opts,
filename,
}).code,
filename,
);
} catch (error) {
if (!hasTsSupport) {
const packageJson = require("@babel/preset-typescript/package.json");
if (semver.lt(packageJson.version, "7.21.4")) {
console.error(
"`.cts` configuration file failed to load, please try to update `@babel/preset-typescript`.",
);
}
}
throw error;
}
}
return require.extensions[".js"](m, filename);
};
require.extensions[ext] = handler;
}
try {
const module = endHiddenCallStack(require)(filepath);
return module?.__esModule ? module.default : module;
} finally {
if (!hasTsSupport) {
if (require.extensions[ext] === handler) delete require.extensions[ext];
handler = undefined;
}
}
}
function loadCjsDefault(filepath: string, fallbackToTranspiledModule: boolean) {
const module = endHiddenCallStack(require)(filepath);
return module?.__esModule
? // TODO (Babel 8): Remove "module" and "undefined" fallback
module.default || (fallbackToTranspiledModule ? module : undefined)
: module;
}
async function loadMjsDefault(filepath: string) {
if (!import_) {
throw new ConfigError(
"Internal error: Native ECMAScript modules aren't supported by this platform.\n",
filepath,
);
}
// import() expects URLs, not file paths.
// https://github.com/nodejs/node/issues/31710
const module = await endHiddenCallStack(import_)(pathToFileURL(filepath));
return module.default;
}
function getTSPreset(filepath: string) {
try {
// eslint-disable-next-line import/no-extraneous-dependencies
return require("@babel/preset-typescript");
} catch (error) {
if (error.code !== "MODULE_NOT_FOUND") throw error;
let message =
"You appear to be using a .cts file as Babel configuration, but the `@babel/preset-typescript` package was not found: please install it!";
if (process.versions.pnp) {
// Using Yarn PnP, which doesn't allow requiring packages that are not
// explicitly specified as dependencies.
// TODO(Babel 8): Explicitly add `@babel/preset-typescript` as an
// optional peer dependency of `@babel/core`.
message += `
If you are using Yarn Plug'n'Play, you may also need to add the following configuration to your .yarnrc.yml file:
packageExtensions:
\t"@babel/core@*":
\t\tpeerDependencies:
\t\t\t"@babel/preset-typescript": "*"
`;
}
throw new ConfigError(message, filepath);
}
}