@@ -31,21 +31,26 @@ class ModuleJob {
3131 this . isMain = isMain ;
3232 this . inspectBrk = inspectBrk ;
3333
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 ) ;
3734 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 ) ;
3838
3939 // Wait for the ModuleWrap instance being linked with all dependencies.
4040 const link = async ( ) => {
4141 this . module = await this . modulePromise ;
4242 assert ( this . module instanceof ModuleWrap ) ;
4343
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.
4448 const dependencyJobs = [ ] ;
4549 const promises = this . module . link ( async ( specifier ) => {
4650 const jobPromise = this . loader . getModuleJob ( specifier , url ) ;
4751 dependencyJobs . push ( jobPromise ) ;
48- return ( await jobPromise ) . modulePromise ;
52+ const job = await jobPromise ;
53+ return job . modulePromise ;
4954 } ) ;
5055
5156 if ( promises !== undefined )
@@ -59,25 +64,20 @@ class ModuleJob {
5964 // 'unhandled rejection' warnings.
6065 this . linked . catch ( noop ) ;
6166
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.
6469 this . instantiated = undefined ;
6570 }
6671
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 ( ) ;
7075 }
71- await this . instantiated ;
72- return this . module ;
76+ return this . instantiated ;
7377 }
7478
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.
7879 async _instantiate ( ) {
7980 const jobsInGraph = new SafeSet ( ) ;
80-
8181 const addJobsToDependencyGraph = async ( moduleJob ) => {
8282 if ( jobsInGraph . has ( moduleJob ) ) {
8383 return ;
@@ -87,6 +87,7 @@ class ModuleJob {
8787 return PromiseAll ( dependencyJobs . map ( addJobsToDependencyGraph ) ) ;
8888 } ;
8989 await addJobsToDependencyGraph ( this ) ;
90+
9091 try {
9192 if ( ! hasPausedEntry && this . inspectBrk ) {
9293 hasPausedEntry = true ;
@@ -122,19 +123,20 @@ class ModuleJob {
122123 }
123124 throw e ;
124125 }
126+
125127 for ( const dependencyJob of jobsInGraph ) {
126128 // Calling `this.module.instantiate()` instantiates not only the
127129 // ModuleWrap in this module, but all modules in the graph.
128130 dependencyJob . instantiated = resolvedPromise ;
129131 }
130- return this . module ;
131132 }
132133
133134 async run ( ) {
134- const module = await this . instantiate ( ) ;
135+ await this . instantiate ( ) ;
135136 const timeout = - 1 ;
136137 const breakOnSigint = false ;
137- return { module, result : module . evaluate ( timeout , breakOnSigint ) } ;
138+ await this . module . evaluate ( timeout , breakOnSigint ) ;
139+ return { module : this . module } ;
138140 }
139141}
140142ObjectSetPrototypeOf ( ModuleJob . prototype , null ) ;
0 commit comments