@@ -195,82 +195,86 @@ let load: LoadHook = async (
195195 loaded,
196196 } ) ;
197197
198- if (
199- isFeatureSupported ( loadReadFromSource )
200- && loaded . format === 'commonjs'
201- && filePath . endsWith ( '.cjs' )
202- ) {
203- let code = await readFile ( new URL ( url ) , 'utf8' ) ;
204- // Contains native ESM check
205- const transformed = transformDynamicImport ( filePath , code ) ;
206- if ( transformed ) {
207- code = inlineSourceMap ( transformed ) ;
198+ if ( loaded . format === 'commonjs' ) {
199+ if (
200+ isFeatureSupported ( loadReadFromSource )
201+ && filePath . endsWith ( '.cjs' )
202+ ) {
203+ let code = await readFile ( new URL ( url ) , 'utf8' ) ;
204+ // Contains native ESM check
205+ const transformed = transformDynamicImport ( filePath , code ) ;
206+ if ( transformed ) {
207+ code = inlineSourceMap ( transformed ) ;
208+ }
209+ loaded . source = code ;
210+ loaded . shortCircuit = true ;
211+ return loaded ;
208212 }
209- loaded . source = code ;
210- loaded . shortCircuit = true ;
211- return loaded ;
212- }
213-
214- if (
215- loaded . format === 'commonjs'
216- && isFeatureSupported ( esmLoadReadFile )
217- && loaded . responseURL ?. startsWith ( 'file:' ) // Could be data:
218- && ! filePath . endsWith ( '.cjs' ) // CJS syntax doesn't need to be transformed for interop
219- ) {
220- const code = await readFile ( new URL ( url ) , 'utf8' ) ;
221213
222- // if the file extension is .js, only transform if using esm syntax
223214 if (
224- // TypeScript files
225- ! filePath . endsWith ( '.js' )
226-
227- // ESM syntax in CommonJS type package
228- || isESM ( code )
215+ isFeatureSupported ( esmLoadReadFile )
216+ && loaded . responseURL ?. startsWith ( 'file:' ) // Could be data:
217+ && ! filePath . endsWith ( '.cjs' ) // CJS syntax doesn't need to be transformed for interop
229218 ) {
230- /**
231- * es or cjs module lexer unfortunately cannot be used because it doesn't support
232- * typescript syntax
233- *
234- * While the full code is transformed, only the exports are used for parsing.
235- * In fact, the code can't even run because imports cannot be resolved relative
236- * from the data: URL.
237- *
238- * This should pre-compile for the CJS loader to have a cache hit
239- *
240- * I considered extracting the CJS exports from esbuild via (0&&(module.exports={})
241- * to minimize the data URL size but this only works for ESM->CJS and not CTS files
242- * which are already in CJS syntax.
243- * In CTS, module.exports can be written in any pattern.
244- */
245- const transformed = transformSync (
246- code ,
247- url ,
248- {
249- tsconfigRaw : fileMatcher ?.( filePath ) as TransformOptions [ 'tsconfigRaw' ] ,
250- } ,
251- ) ;
219+ const code = await readFile ( new URL ( url ) , 'utf8' ) ;
252220
253- if ( isFeatureSupported ( loadReadFromSource ) ) {
254- /**
255- * Compile ESM to CJS
256- * In v22.15, the CJS loader logic is now moved to the ESM loader
257- */
258- loaded . source = inlineSourceMap ( transformed ) ;
259- } else {
221+ // if the file extension is .js, only transform if using esm syntax
222+ if (
223+ // TypeScript files
224+ ! filePath . endsWith ( '.js' )
225+
226+ // ESM syntax in CommonJS type package
227+ || isESM ( code )
228+ ) {
260229 /**
261- * This tricks Node into thinking the file is a data URL so it doesn't try to read from disk
262- * to parse the CJS exports
230+ * es or cjs module lexer unfortunately cannot be used because it doesn't support
231+ * typescript syntax
232+ *
233+ * While the full code is transformed, only the exports are used for parsing.
234+ * In fact, the code can't even run because imports cannot be resolved relative
235+ * from the data: URL.
236+ *
237+ * This should pre-compile for the CJS loader to have a cache hit
238+ *
239+ * I considered extracting the CJS exports from esbuild via (0&&(module.exports={})
240+ * to minimize the data URL size but this only works for ESM->CJS and not CTS files
241+ * which are already in CJS syntax.
242+ * In CTS, module.exports can be written in any pattern.
263243 */
264- const filePathWithNamespace = urlNamespace ? `${ filePath } ?namespace=${ encodeURIComponent ( urlNamespace ) } ` : filePath ;
265- loaded . responseURL = `data:text/javascript,${ encodeURIComponent ( transformed . code ) } ?filePath=${ encodeURIComponent ( filePathWithNamespace ) } ` ;
244+ const transformed = transformSync (
245+ code ,
246+ url ,
247+ {
248+ tsconfigRaw : fileMatcher ?.( filePath ) as TransformOptions [ 'tsconfigRaw' ] ,
249+ } ,
250+ ) ;
251+
252+ if ( isFeatureSupported ( loadReadFromSource ) ) {
253+ /**
254+ * Compile ESM to CJS
255+ * In v22.15, the CJS loader logic is now moved to the ESM loader
256+ */
257+ loaded . source = inlineSourceMap ( transformed ) ;
258+ } else {
259+ /**
260+ * This tricks Node into thinking the file is a data URL so it doesn't try to
261+ * read from disk to parse the CJS exports
262+ */
263+ const filePathWithNamespace = urlNamespace ? `${ filePath } ?namespace=${ encodeURIComponent ( urlNamespace ) } ` : filePath ;
264+ loaded . responseURL = `data:text/javascript,${ encodeURIComponent ( transformed . code ) } ?filePath=${ encodeURIComponent ( filePathWithNamespace ) } ` ;
265+ }
266+
267+ return loaded ;
266268 }
267269
268- log ( 3 , 'returning CJS export annotation' , loaded ) ;
269- return loaded ;
270+ if ( ! loaded . source ) {
271+ loaded . source = code ;
272+ return loaded ;
273+ }
270274 }
271275 }
272276
273- // CommonJS and Internal modules (e.g. node:*)
277+ // Internal modules (e.g. node:*)
274278 if ( ! loaded . source ) {
275279 return loaded ;
276280 }
0 commit comments