@@ -69,7 +69,11 @@ export namespace NodeLoaderHooksAPI2 {
6969      parentURL : string ; 
7070    } , 
7171    defaultResolve : ResolveHook 
72-   )  =>  Promise < {  url : string ;  format ?: NodeLoaderHooksFormat  } > ; 
72+   )  =>  Promise < { 
73+     url : string ; 
74+     format ?: NodeLoaderHooksFormat ; 
75+     shortCircuit ?: boolean ; 
76+   } > ; 
7377  export  type  LoadHook  =  ( 
7478    url : string , 
7579    context : { 
@@ -80,6 +84,7 @@ export namespace NodeLoaderHooksAPI2 {
8084  )  =>  Promise < { 
8185    format : NodeLoaderHooksFormat ; 
8286    source : string  |  Buffer  |  undefined ; 
87+     shortCircuit ?: boolean ; 
8388  } > ; 
8489  export  type  NodeImportConditions  =  unknown ; 
8590  export  interface  NodeImportAssertions  { 
@@ -205,32 +210,34 @@ export function createEsmHooks(tsNodeService: Service) {
205210      } 
206211    } 
207212
208-     const  parsed  =  parseUrl ( specifier ) ; 
209-     const  {  pathname,  protocol,  hostname }  =  parsed ; 
213+     return  addShortCircuitFlag ( async  ( )  =>  { 
214+       const  parsed  =  parseUrl ( specifier ) ; 
215+       const  {  pathname,  protocol,  hostname }  =  parsed ; 
210216
211-     if  ( ! isFileUrlOrNodeStyleSpecifier ( parsed ) )  { 
212-       return  entrypointFallback ( defer ) ; 
213-     } 
217+        if  ( ! isFileUrlOrNodeStyleSpecifier ( parsed ) )  { 
218+          return  entrypointFallback ( defer ) ; 
219+        } 
214220
215-     if  ( protocol  !==  null  &&  protocol  !==  'file:' )  { 
216-       return  entrypointFallback ( defer ) ; 
217-     } 
221+        if  ( protocol  !==  null  &&  protocol  !==  'file:' )  { 
222+          return  entrypointFallback ( defer ) ; 
223+        } 
218224
219-     // Malformed file:// URL?  We should always see `null` or `''` 
220-     if  ( hostname )  { 
221-       // TODO file://./foo sets `hostname` to `'.'`.  Perhaps we should special-case this. 
222-       return  entrypointFallback ( defer ) ; 
223-     } 
225+        // Malformed file:// URL?  We should always see `null` or `''` 
226+        if  ( hostname )  { 
227+          // TODO file://./foo sets `hostname` to `'.'`.  Perhaps we should special-case this. 
228+          return  entrypointFallback ( defer ) ; 
229+        } 
224230
225-     // pathname is the path to be resolved 
231+        // pathname is the path to be resolved 
226232
227-     return  entrypointFallback ( ( )  => 
228-       nodeResolveImplementation . defaultResolve ( 
229-         specifier , 
230-         context , 
231-         defaultResolve 
232-       ) 
233-     ) ; 
233+       return  entrypointFallback ( ( )  => 
234+         nodeResolveImplementation . defaultResolve ( 
235+           specifier , 
236+           context , 
237+           defaultResolve 
238+         ) 
239+       ) ; 
240+     } ) ; 
234241  } 
235242
236243  // `load` from new loader hook API (See description at the top of this file) 
@@ -245,47 +252,49 @@ export function createEsmHooks(tsNodeService: Service) {
245252    format : NodeLoaderHooksFormat ; 
246253    source : string  |  Buffer  |  undefined ; 
247254  } >  { 
248-     // If we get a format hint from resolve() on the context then use it 
249-     // otherwise call the old getFormat() hook using node's old built-in defaultGetFormat() that ships with ts-node 
250-     const  format  = 
251-       context . format  ?? 
252-       ( await  getFormat ( url ,  context ,  defaultGetFormat ) ) . format ; 
253- 
254-     let  source  =  undefined ; 
255-     if  ( format  !==  'builtin'  &&  format  !==  'commonjs' )  { 
256-       // Call the new defaultLoad() to get the source 
257-       const  {  source : rawSource  }  =  await  defaultLoad ( 
258-         url , 
259-         { 
260-           ...context , 
261-           format, 
262-         } , 
263-         defaultLoad 
264-       ) ; 
255+     return  addShortCircuitFlag ( async  ( )  =>  { 
256+       // If we get a format hint from resolve() on the context then use it 
257+       // otherwise call the old getFormat() hook using node's old built-in defaultGetFormat() that ships with ts-node 
258+       const  format  = 
259+         context . format  ?? 
260+         ( await  getFormat ( url ,  context ,  defaultGetFormat ) ) . format ; 
261+ 
262+       let  source  =  undefined ; 
263+       if  ( format  !==  'builtin'  &&  format  !==  'commonjs' )  { 
264+         // Call the new defaultLoad() to get the source 
265+         const  {  source : rawSource  }  =  await  defaultLoad ( 
266+           url , 
267+           { 
268+             ...context , 
269+             format, 
270+           } , 
271+           defaultLoad 
272+         ) ; 
273+ 
274+         if  ( rawSource  ===  undefined  ||  rawSource  ===  null )  { 
275+           throw  new  Error ( 
276+             `Failed to load raw source: Format was '${ format }  ' and url was '${ url }  ''.` 
277+           ) ; 
278+         } 
265279
266-       if  ( rawSource  ===  undefined  ||  rawSource  ===  null )  { 
267-         throw  new  Error ( 
268-           `Failed to load raw source: Format was '${ format }  ' and url was '${ url }  ''.` 
280+         // Emulate node's built-in old defaultTransformSource() so we can re-use the old transformSource() hook 
281+         const  defaultTransformSource : typeof  transformSource  =  async  ( 
282+           source , 
283+           _context , 
284+           _defaultTransformSource 
285+         )  =>  ( {  source } ) ; 
286+ 
287+         // Call the old hook 
288+         const  {  source : transformedSource  }  =  await  transformSource ( 
289+           rawSource , 
290+           {  url,  format } , 
291+           defaultTransformSource 
269292        ) ; 
293+         source  =  transformedSource ; 
270294      } 
271295
272-       // Emulate node's built-in old defaultTransformSource() so we can re-use the old transformSource() hook 
273-       const  defaultTransformSource : typeof  transformSource  =  async  ( 
274-         source , 
275-         _context , 
276-         _defaultTransformSource 
277-       )  =>  ( {  source } ) ; 
278- 
279-       // Call the old hook 
280-       const  {  source : transformedSource  }  =  await  transformSource ( 
281-         rawSource , 
282-         {  url,  format } , 
283-         defaultTransformSource 
284-       ) ; 
285-       source  =  transformedSource ; 
286-     } 
287- 
288-     return  {  format,  source } ; 
296+       return  {  format,  source } ; 
297+     } ) ; 
289298  } 
290299
291300  async  function  getFormat ( 
@@ -384,3 +393,13 @@ export function createEsmHooks(tsNodeService: Service) {
384393
385394  return  hooksAPI ; 
386395} 
396+ 
397+ async  function  addShortCircuitFlag < T > ( fn : ( )  =>  Promise < T > )  { 
398+   const  ret  =  await  fn ( ) ; 
399+   // Not sure if this is necessary; being lazy.  Can revisit in the future. 
400+   if  ( ret  ==  null )  return  ret ; 
401+   return  { 
402+     ...ret , 
403+     shortCircuit : true , 
404+   } ; 
405+ } 
0 commit comments