11'use strict' ;
22
33const {
4+ Array,
45 ArrayPrototypeJoin,
5- ArrayPrototypePush,
66 ArrayPrototypeSome,
77 FunctionPrototype,
88 ObjectSetPrototypeOf,
@@ -87,31 +87,8 @@ class ModuleJob extends ModuleJobBase {
8787 this . modulePromise = PromiseResolve ( this . modulePromise ) ;
8888 }
8989
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- } ;
11390 // Promise for the list of all dependencyJobs.
114- this . linked = link ( ) ;
91+ this . linked = this . _link ( ) ;
11592 // This promise is awaited later anyway, so silence
11693 // 'unhandled rejection' warnings.
11794 PromisePrototypeThen ( this . linked , undefined , noop ) ;
@@ -121,6 +98,49 @@ class ModuleJob extends ModuleJobBase {
12198 this . instantiated = undefined ;
12299 }
123100
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+
124144 instantiate ( ) {
125145 if ( this . instantiated === undefined ) {
126146 this . instantiated = this . _instantiate ( ) ;
@@ -277,18 +297,20 @@ class ModuleJobSync extends ModuleJobBase {
277297 super ( url , importAttributes , moduleWrap , isMain , inspectBrk , true ) ;
278298 assert ( this . module instanceof ModuleWrap ) ;
279299 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 ) ;
282305 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 ;
290311 }
291- this . linked = linked ;
312+ this . module . link ( specifiers , modules ) ;
313+ this . linked = jobs ;
292314 }
293315
294316 get modulePromise ( ) {
0 commit comments