@@ -4,91 +4,14 @@ import { lineBuffered } from './util.js';
44
55export  {  Exit  }  from  './wasi-virt.js' ; 
66
7- async  function  fetchObject ( obj ,  fetchFn )  { 
8-     // Mutate the object being fetched, to avoid re-fetches within the same session. 
9-     // Do this in parallel to avoid head-of-line blocking. 
10-     const  promises  =  [ ] ; 
11-     for  ( const  [ key ,  value ]  of  Object . entries ( obj ) )  { 
12-         if  ( typeof  value  ===  "string"  ||  value  instanceof  Uint8Array )  { 
13-             promises . push ( Promise . resolve ( [ key ,  value ] ) ) ; 
14-         }  else  if  ( value  instanceof  URL )  { 
15-             promises . push ( fetchFn ( value ) . then ( ( fetched )  =>  [ key ,  fetched ] ) ) ; 
16-         }  else  if  ( value  instanceof  Function )  { 
17-             promises . push ( await  value ( fetchFn ) . then ( ( fetched )  =>  [ key ,  fetched ] ) ) ; 
18-         }  else  { 
19-             promises . push ( fetchObject ( value ,  fetchFn ) . then ( ( fetched )  =>  [ key ,  fetched ] ) ) ; 
20-         } 
21-     } 
22-     for  ( const  [ key ,  value ]  of  await  Promise . all ( promises ) ) 
23-         obj [ key ]  =  value ; 
24-     return  obj ; 
25- } 
26- 
27- function  fetchWebAssembly ( url ,  monitorProgress )  { 
28-     const  response  =  fetch ( url ) . then ( monitorProgress ) ; 
29-     if  ( WebAssembly . compileStreaming  !==  undefined )  { 
30-         return  response . then ( WebAssembly . compileStreaming ) ; 
31-     }  else  { 
32-         // Node doesn't have `{compile,instantiate}Streaming`. 
33-         return  response . then ( ( resp )  =>  resp . arrayBuffer ( ) ) . then ( WebAssembly . compile ) ; 
34-     } 
35- } 
36- 
37- function  fetchUint8Array ( url ,  monitorProgress )  { 
38-     const  response  =  fetch ( url ) . then ( monitorProgress ) ; 
39-     return  response . then ( ( resp )  =>  resp . arrayBuffer ( ) ) . then ( ( buf )  =>  new  Uint8Array ( buf ) ) ; 
40- } 
41- 
42- function  fetchResources ( {  modules,  filesystem } ,  fetchProgress ,  application )  { 
43-     /** @type  {(response: Response) => Response } */ 
44-     let  monitorProgress  =  ( response )  =>  response ; 
45-     if  ( fetchProgress  !==  undefined )  { 
46-         const  progress  =  new  Map ( ) ; 
47-         const  notifyProgress  =  ( )  =>  { 
48-             let  cumTotalLength  =  0 ,  cumDoneLength  =  0 ; 
49-             for  ( const  {  totalLength,  doneLength }  of  progress . values ( ) )  { 
50-                 cumTotalLength  +=  totalLength ; 
51-                 cumDoneLength  +=  doneLength ; 
52-             } 
53-             fetchProgress ( { 
54-                 source : application , 
55-                 totalLength : cumTotalLength , 
56-                 doneLength : cumDoneLength 
57-             } ) ; 
58-         } ; 
59-         monitorProgress  =  ( response )  =>  { 
60-             let  totalLength  =  + response . headers . get ( 'content-length' ) ; 
61-             let  doneLength  =  0 ; 
62-             progress . set ( response ,  {  totalLength,  doneLength } ) ; 
63-             notifyProgress ( ) ; 
64-             /** @type  {TransformStream<Uint8Array, Uint8Array> } */ 
65-             const  monitorStream  =  new  TransformStream ( { 
66-                 transform ( chunk ,  controller )  { 
67-                     controller . enqueue ( chunk ) ; 
68-                     doneLength  +=  chunk . length ; 
69-                     progress . set ( response ,  {  totalLength,  doneLength } ) ; 
70-                     notifyProgress ( ) ; 
71-                 } 
72-             } ) ; 
73-             return  new  Response ( response . body . pipeThrough ( monitorStream ) ,  response ) ; 
74-         } ; 
75-     } 
76-     return  Promise . all ( [ 
77-         fetchObject ( modules ,  ( url )  =>  fetchWebAssembly ( url ,  monitorProgress ) ) , 
78-         fetchObject ( filesystem ,  ( url )  =>  fetchUint8Array ( url ,  monitorProgress ) ) 
79-     ] ) . then ( ( [ modules ,  filesystem ] )  =>  { 
80-         return  {  modules,  filesystem } ; 
81-     } ) ; 
82- } 
83- 
847export  class  Application  { 
85-     #resources ; 
8+     #resourceModule ; 
869    #resourceData; 
8710    #instantiate; 
8811    #argv0; 
8912
90-     constructor ( resources ,  instantiate ,  argv0 )  { 
91-         this . #resources  =  resources ; 
13+     constructor ( resourceModule ,  instantiate ,  argv0 )  { 
14+         this . #resourceModule  =  resourceModule ; 
9215        this . #resourceData =  null ; 
9316        this . #instantiate =  instantiate ; 
9417        this . #argv0 =  argv0 ; 
@@ -98,6 +21,29 @@ export class Application {
9821        return  this . #argv0; 
9922    } 
10023
24+     async  #fetchResources( fetchProgress )  { 
25+         const  resourceModule  =  await  this . #resourceModule; 
26+         let  fetchFn  =  fetch ; 
27+         if  ( fetchProgress  !==  undefined )  { 
28+             const  status  =  {  source : this ,  totalLength : resourceModule . totalSize ,  doneLength : 0  } ; 
29+             fetchProgress ( status ) ; 
30+             fetchFn  =  ( input ,  init )  =>  fetch ( input ,  init ) . then ( ( response )  =>  { 
31+                 return  new  Response ( response . body . pipeThrough ( new  TransformStream ( { 
32+                     transform ( chunk ,  controller )  { 
33+                         controller . enqueue ( chunk ) ; 
34+                         status . doneLength  +=  chunk . length ; 
35+                         fetchProgress ( status ) ; 
36+                     } 
37+                 } ) ) ,  response ) ; 
38+             } ) ; 
39+         } 
40+         const  [ modules ,  filesystem ]  =  await  Promise . all ( [ 
41+             resourceModule . modules ( fetchFn ) , 
42+             resourceModule . filesystem ( fetchFn ) , 
43+         ] ) ; 
44+         this . #resourceData =  {  modules,  filesystem } ; 
45+     } 
46+ 
10147    // The `printLine` option is deprecated and not documented but still accepted for compatibility. 
10248    run ( args  =  null ,  files  =  { } ,  options  =  { } )  { 
10349        if  ( this . #resourceData ===  null )  { 
@@ -110,14 +56,9 @@ export class Application {
11056                const  percent  =  ( 100  *  doneLength  /  totalLength ) . toFixed ( 0 ) ; 
11157                console . log ( `${ source . argv0 }  : fetched ${ percent }  % (${ doneLength }   / ${ totalLength }  )` ) ; 
11258            } ; 
113-             const  fetchProgress  =  options . fetchProgress  ??  defaultFetchProgress ; 
114-             return  this . #resources( ) 
115-                 . then ( ( resourceObject )  => 
116-                     fetchResources ( resourceObject ,  fetchProgress ,  this ) ) 
117-                 . then ( ( resourceData )  =>  { 
118-                     this . #resourceData =  resourceData ; 
119-                     return  this . run ( args ,  files ,  options ) ; 
120-                 } ) ; 
59+             return  this . #fetchResources( options . fetchProgress  ??  defaultFetchProgress ) . then ( ( )  =>  { 
60+                 return  this . run ( args ,  files ,  options ) ; 
61+             } ) ; 
12162        } 
12263
12364        if  ( args  ===  null ) 
0 commit comments