1
1
import type Module = require( 'module' ) ;
2
2
import type { Service } from '.' ;
3
+ import { isRelativeSpecifier } from './util' ;
3
4
4
5
/** @internal */
5
6
export type ModuleConstructorWithInternals = typeof Module & {
@@ -19,6 +20,10 @@ interface ModuleResolveFilenameOptions {
19
20
20
21
/**
21
22
* @internal
23
+ *
24
+ * If any features of this service require patching Module._resolveFilename,
25
+ * then install our hook. Logic within the hook conditionally implements
26
+ * multiple resolver behaviors.
22
27
*/
23
28
export function installCommonjsResolveHookIfNecessary ( tsNodeService : Service ) {
24
29
const Module = require ( 'module' ) as ModuleConstructorWithInternals ;
@@ -35,7 +40,7 @@ export function installCommonjsResolveHookIfNecessary(tsNodeService: Service) {
35
40
options ?: ModuleResolveFilenameOptions ,
36
41
...rest : any [ ]
37
42
) : string {
38
- if ( ! tsNodeService . enabled ( ) )
43
+ function defer ( this : any ) {
39
44
return originalResolveFilename . call (
40
45
this ,
41
46
request ,
@@ -44,16 +49,48 @@ export function installCommonjsResolveHookIfNecessary(tsNodeService: Service) {
44
49
options ,
45
50
...rest
46
51
) ;
52
+ }
53
+ if ( ! tsNodeService . enabled ( ) )
54
+ return defer ( ) ;
47
55
56
+ // Map from emit to source extensions
57
+ if ( ! isMain && canReplaceJsWithTsExt ( tsNodeService , request , parent ?. filename ) ) {
58
+ try {
59
+ return originalResolveFilename . call (
60
+ this ,
61
+ request . slice ( 0 , - 3 ) ,
62
+ parent , isMain , options , ...rest
63
+ ) ;
64
+ } catch ( e ) {
65
+ const mainFile = defer ( ) ;
66
+ if ( mainFile . endsWith ( '.js' ) ) {
67
+ //re-resolve with configured extension preference
68
+ return originalResolveFilename . call (
69
+ this ,
70
+ mainFile . slice ( 0 , - 3 ) ,
71
+ parent , isMain , options , ...rest
72
+ ) ;
73
+ }
74
+ return mainFile ;
75
+ }
76
+ }
48
77
// This is a stub to support other pull requests that will be merged in the near future
49
78
// Right now, it does nothing.
50
- return originalResolveFilename . call (
51
- this ,
52
- request ,
53
- parent ,
54
- isMain ,
55
- options ,
56
- ...rest
57
- ) ;
79
+ return defer ( ) ;
80
+ }
81
+ }
82
+
83
+ function canReplaceJsWithTsExt ( service : Service , request : string , parentPath ?: string ) {
84
+ if ( ! parentPath || service . ignored ( parentPath ) ) return false ;
85
+ if ( isRelativeSpecifier ( request ) && request . slice ( - 3 ) === '.js' ) {
86
+ if ( ! parentPath ) return true ;
87
+ const paths = require . main ?. paths || [ ] ;
88
+ // This logic is intending to exclude node_modules
89
+ for ( let i = 0 ; i < paths . length ; i ++ ) {
90
+ if ( parentPath . startsWith ( paths [ i ] ) ) {
91
+ return false ;
92
+ }
93
+ }
94
+ return true ;
58
95
}
59
96
}
0 commit comments