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