11'use strict' ;
22
33const {
4+ Array,
45 ArrayPrototypeJoin,
5- ArrayPrototypePush,
66 ArrayPrototypeSome,
77 FunctionPrototype,
88 ObjectSetPrototypeOf,
@@ -82,31 +82,8 @@ class ModuleJob extends ModuleJobBase {
8282 this . modulePromise = PromiseResolve ( this . modulePromise ) ;
8383 }
8484
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- } ;
10885 // Promise for the list of all dependencyJobs.
109- this . linked = link ( ) ;
86+ this . linked = this . _link ( ) ;
11087 // This promise is awaited later anyway, so silence
11188 // 'unhandled rejection' warnings.
11289 PromisePrototypeThen ( this . linked , undefined , noop ) ;
@@ -116,6 +93,49 @@ class ModuleJob extends ModuleJobBase {
11693 this . instantiated = undefined ;
11794 }
11895
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+
119139 instantiate ( ) {
120140 if ( this . instantiated === undefined ) {
121141 this . instantiated = this . _instantiate ( ) ;
@@ -269,18 +289,20 @@ class ModuleJobSync extends ModuleJobBase {
269289 super ( url , importAttributes , moduleWrap , isMain , inspectBrk , true ) ;
270290 assert ( this . module instanceof ModuleWrap ) ;
271291 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 ) ;
274297 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 ;
282303 }
283- this . linked = linked ;
304+ this . module . link ( specifiers , modules ) ;
305+ this . linked = jobs ;
284306 }
285307
286308 get modulePromise ( ) {
0 commit comments