@@ -88,8 +88,14 @@ const loadMjsFromPath = endHiddenCallStack(async function loadMjsFromPath(
88
88
}
89
89
} ) ;
90
90
91
- const SUPPORTED_EXTENSIONS = new Set ( [ ".js" , ".mjs" , ".cjs" , ".cts" ] as const ) ;
92
- type SetValue < T extends Set < unknown > > = T extends Set < infer U > ? U : never ;
91
+ const SUPPORTED_EXTENSIONS = {
92
+ ".js" : "unknown" ,
93
+ ".mjs" : "esm" ,
94
+ ".cjs" : "cjs" ,
95
+ ".ts" : "unknown" ,
96
+ ".mts" : "esm" ,
97
+ ".cts" : "cjs" ,
98
+ } as const ;
93
99
94
100
const asyncModules = new Set ( ) ;
95
101
@@ -101,15 +107,23 @@ export default function* loadCodeDefault(
101
107
) : Handler < unknown > {
102
108
let async ;
103
109
104
- let ext = path . extname ( filepath ) ;
105
- if ( ! SUPPORTED_EXTENSIONS . has ( ext as any ) ) ext = ".js " ;
110
+ const ext = path . extname ( filepath ) ;
111
+ const isTS = ext === ".ts" || ext === ".cts" || ext === ".mts " ;
106
112
107
- const pattern =
108
- `${ loader } ${ ext } ` as `${typeof loader } ${SetValue < typeof SUPPORTED_EXTENSIONS > } `;
113
+ const type =
114
+ SUPPORTED_EXTENSIONS [
115
+ Object . hasOwn ( SUPPORTED_EXTENSIONS , ext )
116
+ ? ( ext as keyof typeof SUPPORTED_EXTENSIONS )
117
+ : ( ".js" as const )
118
+ ] ;
119
+
120
+ const pattern = `${ loader } ${ type } ` as const ;
109
121
switch ( pattern ) {
110
- case "require .cjs" :
111
- case "auto .cjs" :
112
- if ( process . env . BABEL_8_BREAKING ) {
122
+ case "require cjs" :
123
+ case "auto cjs" :
124
+ if ( isTS ) {
125
+ return ensureTsSupport ( filepath , ext , ( ) => loadCjsDefault ( filepath ) ) ;
126
+ } else if ( process . env . BABEL_8_BREAKING ) {
113
127
return loadCjsDefault ( filepath ) ;
114
128
} else {
115
129
return loadCjsDefault (
@@ -118,14 +132,13 @@ export default function* loadCodeDefault(
118
132
/* fallbackToTranspiledModule */ arguments [ 2 ] ,
119
133
) ;
120
134
}
121
- case "require .cts" :
122
- case "auto .cts" :
123
- return loadCtsDefault ( filepath ) ;
124
- case "auto .js" :
125
- case "require .js" :
126
- case "require .mjs" : // Some versions of Node.js support require(esm):
135
+ case "auto unknown" :
136
+ case "require unknown" :
137
+ case "require esm" :
127
138
try {
128
- if ( process . env . BABEL_8_BREAKING ) {
139
+ if ( isTS ) {
140
+ return ensureTsSupport ( filepath , ext , ( ) => loadCjsDefault ( filepath ) ) ;
141
+ } else if ( process . env . BABEL_8_BREAKING ) {
129
142
return loadCjsDefault ( filepath ) ;
130
143
} else {
131
144
return loadCjsDefault (
@@ -151,92 +164,104 @@ export default function* loadCodeDefault(
151
164
// fall through: require() failed due to TLA
152
165
} else if (
153
166
e . code === "ERR_REQUIRE_ESM" ||
154
- ( ! process . env . BABEL_8_BREAKING && ext === ".mjs " )
167
+ ( ! process . env . BABEL_8_BREAKING && type === "esm " )
155
168
) {
156
169
// fall through: require() failed due to ESM
157
170
} else {
158
171
throw e ;
159
172
}
160
173
}
161
174
// fall through: require() failed due to ESM or TLA, try import()
162
- case "auto .mjs " :
175
+ case "auto esm " :
163
176
if ( ( async ??= yield * isAsync ( ) ) ) {
164
- return ( yield * waitFor ( loadMjsFromPath ( filepath ) ) ) . default ;
177
+ const promise = isTS
178
+ ? ensureTsSupport ( filepath , ext , ( ) => loadMjsFromPath ( filepath ) )
179
+ : loadMjsFromPath ( filepath ) ;
180
+
181
+ return ( yield * waitFor ( promise ) ) . default ;
165
182
}
166
183
throw new ConfigError ( esmError , filepath ) ;
167
184
default :
168
185
throw new Error ( "Internal Babel error: unreachable code." ) ;
169
186
}
170
187
}
171
188
172
- function loadCtsDefault ( filepath : string ) {
173
- const ext = ".cts" ;
174
- const hasTsSupport = ! ! (
189
+ function ensureTsSupport < T > (
190
+ filepath : string ,
191
+ ext : string ,
192
+ callback : ( ) => T ,
193
+ ) : T {
194
+ if (
175
195
require . extensions [ ".ts" ] ||
176
196
require . extensions [ ".cts" ] ||
177
197
require . extensions [ ".mts" ]
178
- ) ;
198
+ ) {
199
+ return callback ( ) ;
200
+ }
179
201
180
- let handler : NodeJS . RequireExtensions [ "" ] ;
202
+ if ( ext !== ".cts" ) {
203
+ throw new ConfigError (
204
+ `\
205
+ You are using a ${ ext } config file, but Babel only supports transpiling .cts configs. Either:
206
+ - Use a .cts config file
207
+ - Update to Node.js 23.6.0, which has native TypeScript support
208
+ - Install ts-node to transpile ${ ext } files on the fly\
209
+ ` ,
210
+ filepath ,
211
+ ) ;
212
+ }
181
213
182
- if ( ! hasTsSupport ) {
183
- const opts : InputOptions = {
184
- babelrc : false ,
185
- configFile : false ,
186
- sourceType : "unambiguous" ,
187
- sourceMaps : "inline" ,
188
- sourceFileName : path . basename ( filepath ) ,
189
- presets : [
190
- [
191
- getTSPreset ( filepath ) ,
192
- {
193
- onlyRemoveTypeImports : true ,
194
- optimizeConstEnums : true ,
195
- ...( process . env . BABEL_8_BREAKING
196
- ? { }
197
- : { allowDeclareFields : true } ) ,
198
- } ,
199
- ] ,
214
+ const opts : InputOptions = {
215
+ babelrc : false ,
216
+ configFile : false ,
217
+ sourceType : "unambiguous" ,
218
+ sourceMaps : "inline" ,
219
+ sourceFileName : path . basename ( filepath ) ,
220
+ presets : [
221
+ [
222
+ getTSPreset ( filepath ) ,
223
+ {
224
+ onlyRemoveTypeImports : true ,
225
+ optimizeConstEnums : true ,
226
+ ...( process . env . BABEL_8_BREAKING ? { } : { allowDeclareFields : true } ) ,
227
+ } ,
200
228
] ,
201
- } ;
229
+ ] ,
230
+ } ;
202
231
203
- handler = function ( m , filename ) {
204
- // If we want to support `.ts`, `.d.ts` must be handled specially.
205
- if ( handler && filename . endsWith ( ext ) ) {
206
- try {
207
- // @ts -expect-error Undocumented API
208
- return m . _compile (
209
- transformFileSync ( filename , {
210
- ...opts ,
211
- filename,
212
- } ) . code ,
232
+ let handler : NodeJS . RequireExtensions [ "" ] = function ( m , filename ) {
233
+ // If we want to support `.ts`, `.d.ts` must be handled specially.
234
+ if ( handler && filename . endsWith ( ".cts" ) ) {
235
+ try {
236
+ // @ts -expect-error Undocumented API
237
+ return m . _compile (
238
+ transformFileSync ( filename , {
239
+ ...opts ,
213
240
filename,
241
+ } ) . code ,
242
+ filename ,
243
+ ) ;
244
+ } catch ( error ) {
245
+ // TODO(Babel 8): Add this as an optional peer dependency
246
+ // eslint-disable-next-line import/no-extraneous-dependencies
247
+ const packageJson = require ( "@babel/preset-typescript/package.json" ) ;
248
+ if ( semver . lt ( packageJson . version , "7.21.4" ) ) {
249
+ console . error (
250
+ "`.cts` configuration file failed to load, please try to update `@babel/preset-typescript`." ,
214
251
) ;
215
- } catch ( error ) {
216
- if ( ! hasTsSupport ) {
217
- // TODO(Babel 8): Add this as an optional peer dependency
218
- // eslint-disable-next-line import/no-extraneous-dependencies
219
- const packageJson = require ( "@babel/preset-typescript/package.json" ) ;
220
- if ( semver . lt ( packageJson . version , "7.21.4" ) ) {
221
- console . error (
222
- "`.cts` configuration file failed to load, please try to update `@babel/preset-typescript`." ,
223
- ) ;
224
- }
225
- }
226
- throw error ;
227
252
}
253
+ throw error ;
228
254
}
229
- return require . extensions [ ".js" ] ( m , filename ) ;
230
- } ;
231
- require . extensions [ ext ] = handler ;
232
- }
255
+ }
256
+ return require . extensions [ ".js" ] ( m , filename ) ;
257
+ } ;
258
+ require . extensions [ ext ] = handler ;
259
+
233
260
try {
234
- return loadCjsDefault ( filepath ) ;
261
+ return callback ( ) ;
235
262
} finally {
236
- if ( ! hasTsSupport ) {
237
- if ( require . extensions [ ext ] === handler ) delete require . extensions [ ext ] ;
238
- handler = undefined ;
239
- }
263
+ if ( require . extensions [ ext ] === handler ) delete require . extensions [ ext ] ;
264
+ handler = undefined ;
240
265
}
241
266
}
242
267
0 commit comments