1
1
'use strict' ;
2
2
3
3
const {
4
+ Array,
4
5
ArrayPrototypeJoin,
5
- ArrayPrototypePush,
6
6
ArrayPrototypeSome,
7
7
FunctionPrototype,
8
8
ObjectSetPrototypeOf,
@@ -87,31 +87,8 @@ class ModuleJob extends ModuleJobBase {
87
87
this . modulePromise = PromiseResolve ( this . modulePromise ) ;
88
88
}
89
89
90
- // Wait for the ModuleWrap instance being linked with all dependencies.
91
- const link = async ( ) => {
92
- this . module = await this . modulePromise ;
93
- assert ( this . module instanceof ModuleWrap ) ;
94
-
95
- // Explicitly keeping track of dependency jobs is needed in order
96
- // to flatten out the dependency graph below in `_instantiate()`,
97
- // so that circular dependencies can't cause a deadlock by two of
98
- // these `link` callbacks depending on each other.
99
- const dependencyJobs = [ ] ;
100
- const promises = this . module . link ( async ( specifier , attributes ) => {
101
- const job = await this . #loader. getModuleJob ( specifier , url , attributes ) ;
102
- debug ( `async link() ${ this . url } -> ${ specifier } ` , job ) ;
103
- ArrayPrototypePush ( dependencyJobs , job ) ;
104
- return job . modulePromise ;
105
- } ) ;
106
-
107
- if ( promises !== undefined ) {
108
- await SafePromiseAllReturnVoid ( promises ) ;
109
- }
110
-
111
- return SafePromiseAllReturnArrayLike ( dependencyJobs ) ;
112
- } ;
113
90
// Promise for the list of all dependencyJobs.
114
- this . linked = link ( ) ;
91
+ this . linked = this . _link ( ) ;
115
92
// This promise is awaited later anyway, so silence
116
93
// 'unhandled rejection' warnings.
117
94
PromisePrototypeThen ( this . linked , undefined , noop ) ;
@@ -121,6 +98,49 @@ class ModuleJob extends ModuleJobBase {
121
98
this . instantiated = undefined ;
122
99
}
123
100
101
+ /**
102
+ * Iterates the module requests and links with the loader.
103
+ * @returns {Promise<ModuleJob[]> } Dependency module jobs.
104
+ */
105
+ async _link ( ) {
106
+ this . module = await this . modulePromise ;
107
+ assert ( this . module instanceof ModuleWrap ) ;
108
+
109
+ const moduleRequests = this . module . getModuleRequests ( ) ;
110
+ // Explicitly keeping track of dependency jobs is needed in order
111
+ // to flatten out the dependency graph below in `_instantiate()`,
112
+ // so that circular dependencies can't cause a deadlock by two of
113
+ // these `link` callbacks depending on each other.
114
+ // Create an ArrayLike to avoid calling into userspace with `.then`
115
+ // when returned from the async function.
116
+ const dependencyJobs = Array ( moduleRequests . length ) ;
117
+ ObjectSetPrototypeOf ( dependencyJobs , null ) ;
118
+
119
+ // Specifiers should be aligned with the moduleRequests array in order.
120
+ const specifiers = Array ( moduleRequests . length ) ;
121
+ const modulePromises = Array ( moduleRequests . length ) ;
122
+ // Iterate with index to avoid calling into userspace with `Symbol.iterator`.
123
+ for ( let idx = 0 ; idx < moduleRequests . length ; idx ++ ) {
124
+ const { specifier, attributes } = moduleRequests [ idx ] ;
125
+
126
+ const dependencyJobPromise = this . #loader. getModuleJob (
127
+ specifier , this . url , attributes ,
128
+ ) ;
129
+ const modulePromise = PromisePrototypeThen ( dependencyJobPromise , ( job ) => {
130
+ debug ( `async link() ${ this . url } -> ${ specifier } ` , job ) ;
131
+ dependencyJobs [ idx ] = job ;
132
+ return job . modulePromise ;
133
+ } ) ;
134
+ modulePromises [ idx ] = modulePromise ;
135
+ specifiers [ idx ] = specifier ;
136
+ }
137
+
138
+ const modules = await SafePromiseAllReturnArrayLike ( modulePromises ) ;
139
+ this . module . link ( specifiers , modules ) ;
140
+
141
+ return dependencyJobs ;
142
+ }
143
+
124
144
instantiate ( ) {
125
145
if ( this . instantiated === undefined ) {
126
146
this . instantiated = this . _instantiate ( ) ;
@@ -277,18 +297,20 @@ class ModuleJobSync extends ModuleJobBase {
277
297
super ( url , importAttributes , moduleWrap , isMain , inspectBrk , true ) ;
278
298
assert ( this . module instanceof ModuleWrap ) ;
279
299
this . #loader = loader ;
280
- const moduleRequests = this . module . getModuleRequestsSync ( ) ;
281
- const linked = [ ] ;
300
+ const moduleRequests = this . module . getModuleRequests ( ) ;
301
+ // Specifiers should be aligned with the moduleRequests array in order.
302
+ const specifiers = Array ( moduleRequests . length ) ;
303
+ const modules = Array ( moduleRequests . length ) ;
304
+ const jobs = Array ( moduleRequests . length ) ;
282
305
for ( let i = 0 ; i < moduleRequests . length ; ++ i ) {
283
- const { 0 : specifier , 1 : attributes } = moduleRequests [ i ] ;
284
- const job = this . #loader. getModuleWrapForRequire ( specifier , url , attributes ) ;
285
- const isLast = ( i === moduleRequests . length - 1 ) ;
286
- // TODO(joyeecheung): make the resolution callback deal with both promisified
287
- // an raw module wraps, then we don't need to wrap it with a promise here.
288
- this . module . cacheResolvedWrapsSync ( specifier , PromiseResolve ( job . module ) , isLast ) ;
289
- ArrayPrototypePush ( linked , job ) ;
306
+ const { specifier, attributes } = moduleRequests [ i ] ;
307
+ const job = this . #loader. getModuleJobForRequire ( specifier , url , attributes ) ;
308
+ specifiers [ i ] = specifier ;
309
+ modules [ i ] = job . module ;
310
+ jobs [ i ] = job ;
290
311
}
291
- this . linked = linked ;
312
+ this . module . link ( specifiers , modules ) ;
313
+ this . linked = jobs ;
292
314
}
293
315
294
316
get modulePromise ( ) {
0 commit comments