@@ -5,11 +5,15 @@ const {
55 ArrayIsArray,
66 ArrayPrototypeForEach,
77 ArrayPrototypeIndexOf,
8+ ArrayPrototypeMap,
9+ ArrayPrototypePush,
810 ArrayPrototypeSome,
911 ObjectDefineProperty,
1012 ObjectFreeze,
1113 ObjectGetPrototypeOf,
1214 ObjectSetPrototypeOf,
15+ PromiseResolve,
16+ PromisePrototypeThen,
1317 ReflectApply,
1418 SafePromiseAllReturnVoid,
1519 Symbol,
@@ -306,27 +310,40 @@ class SourceTextModule extends Module {
306310 this [ kLink ] = async ( linker ) => {
307311 this . #statusOverride = 'linking' ;
308312
309- const promises = this [ kWrap ] . link ( async ( identifier , attributes ) => {
310- const module = await linker ( identifier , this , { attributes, assert : attributes } ) ;
311- if ( module [ kWrap ] === undefined ) {
312- throw new ERR_VM_MODULE_NOT_MODULE ( ) ;
313- }
314- if ( module . context !== this . context ) {
315- throw new ERR_VM_MODULE_DIFFERENT_CONTEXT ( ) ;
316- }
317- if ( module . status === 'errored' ) {
318- throw new ERR_VM_MODULE_LINK_FAILURE ( `request for '${ identifier } ' resolved to an errored module` , module . error ) ;
319- }
320- if ( module . status === 'unlinked' ) {
321- await module [ kLink ] ( linker ) ;
322- }
323- return module [ kWrap ] ;
324- } ) ;
313+ // Iterates the module requests and links with the linker.
314+ const promises = [ ] ;
315+ // Iterate with index to avoid calling into userspace with `Symbol.iterator`.
316+ const moduleRequestsLength = this [ kWrap ] . moduleRequests . length ;
317+ for ( let idx = 0 ; idx < moduleRequestsLength ; idx ++ ) {
318+ const { specifier, attributes } = this [ kWrap ] . moduleRequests [ idx ] ;
319+
320+ const linkerResult = linker ( specifier , this , {
321+ attributes,
322+ assert : attributes ,
323+ } ) ;
324+ const promise = PromisePrototypeThen (
325+ PromiseResolve ( linkerResult ) , async ( module ) => {
326+ if ( module [ kWrap ] === undefined ) {
327+ throw new ERR_VM_MODULE_NOT_MODULE ( ) ;
328+ }
329+ if ( module . context !== this . context ) {
330+ throw new ERR_VM_MODULE_DIFFERENT_CONTEXT ( ) ;
331+ }
332+ if ( module . status === 'errored' ) {
333+ throw new ERR_VM_MODULE_LINK_FAILURE ( `request for '${ specifier } ' resolved to an errored module` , module . error ) ;
334+ }
335+ if ( module . status === 'unlinked' ) {
336+ await module [ kLink ] ( linker ) ;
337+ }
338+ return module [ kWrap ] ;
339+ } ) ;
340+
341+ this [ kWrap ] . linkModule ( specifier , promise , /** finished */ idx === moduleRequestsLength - 1 ) ;
342+ ArrayPrototypePush ( promises , promise ) ;
343+ }
325344
326345 try {
327- if ( promises !== undefined ) {
328- await SafePromiseAllReturnVoid ( promises ) ;
329- }
346+ await SafePromiseAllReturnVoid ( promises ) ;
330347 } catch ( e ) {
331348 this . #error = e ;
332349 throw e ;
@@ -342,7 +359,8 @@ class SourceTextModule extends Module {
342359 if ( this [ kWrap ] === undefined ) {
343360 throw new ERR_VM_MODULE_NOT_MODULE ( ) ;
344361 }
345- this [ kDependencySpecifiers ] ??= ObjectFreeze ( this [ kWrap ] . getStaticDependencySpecifiers ( ) ) ;
362+ this [ kDependencySpecifiers ] ??= ObjectFreeze (
363+ ArrayPrototypeMap ( this [ kWrap ] . moduleRequests , ( request ) => request . specifier ) ) ;
346364 return this [ kDependencySpecifiers ] ;
347365 }
348366
@@ -409,9 +427,7 @@ class SyntheticModule extends Module {
409427 identifier,
410428 } ) ;
411429
412- this [ kLink ] = ( ) => this [ kWrap ] . link ( ( ) => {
413- assert . fail ( 'link callback should not be called' ) ;
414- } ) ;
430+ this [ kLink ] = ( ) => this [ kWrap ] . markLinked ( ) ;
415431 }
416432
417433 setExport ( name , value ) {
0 commit comments