@@ -31,21 +31,26 @@ class ModuleJob {
31
31
this . isMain = isMain ;
32
32
this . inspectBrk = inspectBrk ;
33
33
34
- // This is a Promise<{ module, reflect }>, whose fields will be copied
35
- // onto `this` by `link()` below once it has been resolved.
36
- this . modulePromise = moduleProvider . call ( loader , url , isMain ) ;
37
34
this . module = undefined ;
35
+ // Expose the promise to the ModuleWrap directly for linking below.
36
+ // `this.module` is also filled in below.
37
+ this . modulePromise = moduleProvider . call ( loader , url , isMain ) ;
38
38
39
39
// Wait for the ModuleWrap instance being linked with all dependencies.
40
40
const link = async ( ) => {
41
41
this . module = await this . modulePromise ;
42
42
assert ( this . module instanceof ModuleWrap ) ;
43
43
44
+ // Explicitly keeping track of dependency jobs is needed in order
45
+ // to flatten out the dependency graph below in `_instantiate()`,
46
+ // so that circular dependencies can't cause a deadlock by two of
47
+ // these `link` callbacks depending on each other.
44
48
const dependencyJobs = [ ] ;
45
49
const promises = this . module . link ( async ( specifier ) => {
46
50
const jobPromise = this . loader . getModuleJob ( specifier , url ) ;
47
51
dependencyJobs . push ( jobPromise ) ;
48
- return ( await jobPromise ) . modulePromise ;
52
+ const job = await jobPromise ;
53
+ return job . modulePromise ;
49
54
} ) ;
50
55
51
56
if ( promises !== undefined )
@@ -59,25 +64,20 @@ class ModuleJob {
59
64
// 'unhandled rejection' warnings.
60
65
this . linked . catch ( noop ) ;
61
66
62
- // instantiated == deep dependency jobs wrappers instantiated,
63
- // module wrapper instantiated
67
+ // instantiated == deep dependency jobs wrappers are instantiated,
68
+ // and module wrapper is instantiated.
64
69
this . instantiated = undefined ;
65
70
}
66
71
67
- async instantiate ( ) {
68
- if ( ! this . instantiated ) {
69
- return this . instantiated = this . _instantiate ( ) ;
72
+ instantiate ( ) {
73
+ if ( this . instantiated === undefined ) {
74
+ this . instantiated = this . _instantiate ( ) ;
70
75
}
71
- await this . instantiated ;
72
- return this . module ;
76
+ return this . instantiated ;
73
77
}
74
78
75
- // This method instantiates the module associated with this job and its
76
- // entire dependency graph, i.e. creates all the module namespaces and the
77
- // exported/imported variables.
78
79
async _instantiate ( ) {
79
80
const jobsInGraph = new SafeSet ( ) ;
80
-
81
81
const addJobsToDependencyGraph = async ( moduleJob ) => {
82
82
if ( jobsInGraph . has ( moduleJob ) ) {
83
83
return ;
@@ -87,6 +87,7 @@ class ModuleJob {
87
87
return PromiseAll ( dependencyJobs . map ( addJobsToDependencyGraph ) ) ;
88
88
} ;
89
89
await addJobsToDependencyGraph ( this ) ;
90
+
90
91
try {
91
92
if ( ! hasPausedEntry && this . inspectBrk ) {
92
93
hasPausedEntry = true ;
@@ -122,19 +123,20 @@ class ModuleJob {
122
123
}
123
124
throw e ;
124
125
}
126
+
125
127
for ( const dependencyJob of jobsInGraph ) {
126
128
// Calling `this.module.instantiate()` instantiates not only the
127
129
// ModuleWrap in this module, but all modules in the graph.
128
130
dependencyJob . instantiated = resolvedPromise ;
129
131
}
130
- return this . module ;
131
132
}
132
133
133
134
async run ( ) {
134
- const module = await this . instantiate ( ) ;
135
+ await this . instantiate ( ) ;
135
136
const timeout = - 1 ;
136
137
const breakOnSigint = false ;
137
- return { module, result : module . evaluate ( timeout , breakOnSigint ) } ;
138
+ await this . module . evaluate ( timeout , breakOnSigint ) ;
139
+ return { module : this . module } ;
138
140
}
139
141
}
140
142
ObjectSetPrototypeOf ( ModuleJob . prototype , null ) ;
0 commit comments