@@ -207,6 +207,137 @@ class ShellFileLoader {
207207 }
208208} ;
209209
210+
211+ class BrowserFileLoader {
212+
213+ constructor ( ) {
214+ // TODO: Cleanup / remove / merge `blobDataCache` and `loadCache` vs.
215+ // the global `fileLoader` cache.
216+ this . blobDataCache = { __proto__ : null } ;
217+ this . loadCache = { __proto__ : null } ;
218+ }
219+
220+ async doLoadBlob ( resource ) {
221+ const blobData = this . blobDataCache [ resource ] ;
222+
223+ const compressed = isCompressed ( resource ) ;
224+ if ( compressed && ! JetStreamParams . prefetchResources ) {
225+ resource = uncompressedName ( resource ) ;
226+ }
227+
228+ // If we aren't supposed to prefetch this then set the blobURL to just
229+ // be the resource URL.
230+ if ( ! JetStreamParams . prefetchResources ) {
231+ blobData . blobURL = resource ;
232+ return blobData ;
233+ }
234+
235+ let response ;
236+ let tries = 3 ;
237+ while ( tries -- ) {
238+ let hasError = false ;
239+ try {
240+ response = await fetch ( resource , { cache : "no-store" } ) ;
241+ } catch ( e ) {
242+ hasError = true ;
243+ }
244+ if ( ! hasError && response . ok )
245+ break ;
246+ if ( tries )
247+ continue ;
248+ throw new Error ( "Fetch failed" ) ;
249+ }
250+
251+ // If we need to decompress this, then run it through a decompression
252+ // stream.
253+ if ( compressed ) {
254+ const stream = response . body . pipeThrough ( new DecompressionStream ( "deflate" ) )
255+ response = new Response ( stream ) ;
256+ }
257+
258+ let blob = await response . blob ( ) ;
259+ blobData . blob = blob ;
260+ blobData . blobURL = URL . createObjectURL ( blob ) ;
261+ return blobData ;
262+ }
263+
264+ async loadBlob ( type , prop , resource , incrementRefCount = true ) {
265+ let blobData = this . blobDataCache [ resource ] ;
266+ if ( ! blobData ) {
267+ blobData = {
268+ type : type ,
269+ prop : prop ,
270+ resource : resource ,
271+ blob : null ,
272+ blobURL : null ,
273+ refCount : 0
274+ } ;
275+ this . blobDataCache [ resource ] = blobData ;
276+ }
277+
278+ if ( incrementRefCount )
279+ blobData . refCount ++ ;
280+
281+ let promise = this . loadCache [ resource ] ;
282+ if ( promise )
283+ return promise ;
284+
285+ promise = this . doLoadBlob ( resource ) ;
286+ this . loadCache [ resource ] = promise ;
287+ return promise ;
288+ }
289+
290+ async retryPrefetchResource ( type , prop , file ) {
291+ console . assert ( isInBrowser ) ;
292+
293+ const counter = JetStream . counter ;
294+ const blobData = this . blobDataCache [ file ] ;
295+ if ( blobData . blob ) {
296+ // The same preload blob may be used by multiple subtests. Though the blob is already loaded,
297+ // we still need to check if this subtest failed to load it before. If so, handle accordingly.
298+ if ( type == "preload" ) {
299+ if ( this . failedPreloads && this . failedPreloads [ blobData . prop ] ) {
300+ this . failedPreloads [ blobData . prop ] = false ;
301+ this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
302+ counter . failedPreloadResources -- ;
303+ }
304+ }
305+ return ! counter . failedPreloadResources && counter . loadedResources == counter . totalResources ;
306+ }
307+
308+ // Retry fetching the resource.
309+ this . loadCache [ file ] = null ;
310+ await this . loadBlob ( type , prop , file , false ) . then ( ( blobData ) => {
311+ if ( ! globalThis . allIsGood )
312+ return ;
313+ if ( blobData . type == "preload" )
314+ this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
315+ this . updateCounter ( ) ;
316+ } ) ;
317+
318+ if ( ! blobData . blob ) {
319+ globalThis . allIsGood = false ;
320+ throw new Error ( "Fetch failed" ) ;
321+ }
322+
323+ return ! counter . failedPreloadResources && counter . loadedResources == counter . totalResources ;
324+ }
325+
326+ free ( files ) {
327+ for ( const file of files ) {
328+ const blobData = this . blobDataCache [ file ] ;
329+ // If we didn't prefetch this resource, then no need to free it
330+ if ( ! blobData . blob ) {
331+ continue
332+ }
333+ blobData . refCount -- ;
334+ if ( ! blobData . refCount )
335+ this . blobDataCache [ file ] = undefined ;
336+ }
337+ }
338+ }
339+
340+ const browserFileLoader = new BrowserFileLoader ( ) ;
210341const shellFileLoader = new ShellFileLoader ( ) ;
211342
212343class Driver {
@@ -218,10 +349,6 @@ class Driver {
218349 this . benchmarks = Array . from ( new Set ( benchmarks ) ) ;
219350 this . benchmarks . sort ( ( a , b ) => a . plan . name . toLowerCase ( ) < b . plan . name . toLowerCase ( ) ? 1 : - 1 ) ;
220351 console . assert ( this . benchmarks . length , "No benchmarks selected" ) ;
221- // TODO: Cleanup / remove / merge `blobDataCache` and `loadCache` vs.
222- // the global `fileLoader` cache.
223- this . blobDataCache = { } ;
224- this . loadCache = { } ;
225352 this . counter = { } ;
226353 this . counter . loadedResources = 0 ;
227354 this . counter . totalResources = 0 ;
@@ -254,17 +381,7 @@ class Driver {
254381 benchmark . updateUIAfterRun ( ) ;
255382
256383 if ( isInBrowser ) {
257- const cache = JetStream . blobDataCache ;
258- for ( const file of benchmark . files ) {
259- const blobData = cache [ file ] ;
260- // If we didn't prefetch this resource, then no need to free it
261- if ( ! blobData . blob ) {
262- continue
263- }
264- blobData . refCount -- ;
265- if ( ! blobData . refCount )
266- cache [ file ] = undefined ;
267- }
384+ browserFileLoader . free ( benchmark . files ) ;
268385 }
269386 }
270387 performance . measure ( "runner update-ui" , "update-ui-start" ) ;
@@ -428,12 +545,12 @@ class Driver {
428545
429546 // TODO: Cleanup the browser path of the preloading below and in
430547 // `prefetchResourcesForBrowser` / `retryPrefetchResourcesForBrowser`.
548+ const counter = JetStream . counter ;
431549 const promises = [ ] ;
432550 for ( const benchmark of this . benchmarks )
433- promises . push ( benchmark . prefetchResourcesForBrowser ( ) ) ;
551+ promises . push ( benchmark . prefetchResourcesForBrowser ( counter ) ) ;
434552 await Promise . all ( promises ) ;
435553
436- const counter = JetStream . counter ;
437554 if ( counter . failedPreloadResources || counter . loadedResources != counter . totalResources ) {
438555 for ( const benchmark of this . benchmarks ) {
439556 const allFilesLoaded = await benchmark . retryPrefetchResourcesForBrowser ( counter ) ;
@@ -749,6 +866,7 @@ class BrowserScripts extends Scripts {
749866 }
750867}
751868
869+
752870class Benchmark {
753871 constructor ( plan )
754872 {
@@ -946,7 +1064,7 @@ class Benchmark {
9461064 for ( const text of this . scripts )
9471065 scripts . add ( text ) ;
9481066 } else {
949- const cache = JetStream . blobDataCache ;
1067+ const cache = browserFileLoader . blobDataCache ;
9501068 for ( const file of this . plan . files ) {
9511069 scripts . addWithURL ( cache [ file ] . blobURL ) ;
9521070 }
@@ -997,75 +1115,6 @@ class Benchmark {
9971115 Realm . dispose ( magicFrame ) ;
9981116 }
9991117
1000- async doLoadBlob ( resource ) {
1001- const blobData = JetStream . blobDataCache [ resource ] ;
1002-
1003- const compressed = isCompressed ( resource ) ;
1004- if ( compressed && ! JetStreamParams . prefetchResources ) {
1005- resource = uncompressedName ( resource ) ;
1006- }
1007-
1008- // If we aren't supposed to prefetch this then set the blobURL to just
1009- // be the resource URL.
1010- if ( ! JetStreamParams . prefetchResources ) {
1011- blobData . blobURL = resource ;
1012- return blobData ;
1013- }
1014-
1015- let response ;
1016- let tries = 3 ;
1017- while ( tries -- ) {
1018- let hasError = false ;
1019- try {
1020- response = await fetch ( resource , { cache : "no-store" } ) ;
1021- } catch ( e ) {
1022- hasError = true ;
1023- }
1024- if ( ! hasError && response . ok )
1025- break ;
1026- if ( tries )
1027- continue ;
1028- throw new Error ( "Fetch failed" ) ;
1029- }
1030-
1031- // If we need to decompress this, then run it through a decompression
1032- // stream.
1033- if ( compressed ) {
1034- const stream = response . body . pipeThrough ( new DecompressionStream ( "deflate" ) )
1035- response = new Response ( stream ) ;
1036- }
1037-
1038- let blob = await response . blob ( ) ;
1039- blobData . blob = blob ;
1040- blobData . blobURL = URL . createObjectURL ( blob ) ;
1041- return blobData ;
1042- }
1043-
1044- async loadBlob ( type , prop , resource , incrementRefCount = true ) {
1045- let blobData = JetStream . blobDataCache [ resource ] ;
1046- if ( ! blobData ) {
1047- blobData = {
1048- type : type ,
1049- prop : prop ,
1050- resource : resource ,
1051- blob : null ,
1052- blobURL : null ,
1053- refCount : 0
1054- } ;
1055- JetStream . blobDataCache [ resource ] = blobData ;
1056- }
1057-
1058- if ( incrementRefCount )
1059- blobData . refCount ++ ;
1060-
1061- let promise = JetStream . loadCache [ resource ] ;
1062- if ( promise )
1063- return promise ;
1064-
1065- promise = this . doLoadBlob ( resource ) ;
1066- JetStream . loadCache [ resource ] = promise ;
1067- return promise ;
1068- }
10691118
10701119 updateCounter ( ) {
10711120 const counter = JetStream . counter ;
@@ -1074,10 +1123,10 @@ class Benchmark {
10741123 statusElement . innerHTML = `Loading ${ counter . loadedResources } of ${ counter . totalResources } ...` ;
10751124 }
10761125
1077- prefetchResourcesForBrowser ( ) {
1126+ prefetchResourcesForBrowser ( counter ) {
10781127 console . assert ( isInBrowser ) ;
10791128
1080- const promises = this . plan . files . map ( ( file ) => this . loadBlob ( "file" , null , file ) . then ( ( blobData ) => {
1129+ const promises = this . plan . files . map ( ( file ) => browserFileLoader . loadBlob ( "file" , null , file ) . then ( ( blobData ) => {
10811130 if ( ! globalThis . allIsGood )
10821131 return ;
10831132 this . updateCounter ( ) ;
@@ -1087,7 +1136,7 @@ class Benchmark {
10871136
10881137 if ( this . plan . preload ) {
10891138 for ( const [ name , resource ] of Object . entries ( this . plan . preload ) ) {
1090- promises . push ( this . loadBlob ( "preload" , name , resource ) . then ( ( blobData ) => {
1139+ promises . push ( browserFileLoader . loadBlob ( "preload" , name , resource ) . then ( ( blobData ) => {
10911140 if ( ! globalThis . allIsGood )
10921141 return ;
10931142 this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
@@ -1097,7 +1146,7 @@ class Benchmark {
10971146 if ( ! this . failedPreloads )
10981147 this . failedPreloads = { } ;
10991148 this . failedPreloads [ name ] = true ;
1100- JetStream . counter . failedPreloadResources ++ ;
1149+ counter . failedPreloadResources ++ ;
11011150 } ) ) ;
11021151 }
11031152 }
@@ -1106,55 +1155,20 @@ class Benchmark {
11061155 return Promise . all ( promises ) ;
11071156 }
11081157
1109- async retryPrefetchResource ( type , prop , file ) {
1110- console . assert ( isInBrowser ) ;
1111-
1112- const counter = JetStream . counter ;
1113- const blobData = JetStream . blobDataCache [ file ] ;
1114- if ( blobData . blob ) {
1115- // The same preload blob may be used by multiple subtests. Though the blob is already loaded,
1116- // we still need to check if this subtest failed to load it before. If so, handle accordingly.
1117- if ( type == "preload" ) {
1118- if ( this . failedPreloads && this . failedPreloads [ blobData . prop ] ) {
1119- this . failedPreloads [ blobData . prop ] = false ;
1120- this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
1121- counter . failedPreloadResources -- ;
1122- }
1123- }
1124- return ! counter . failedPreloadResources && counter . loadedResources == counter . totalResources ;
1125- }
1126-
1127- // Retry fetching the resource.
1128- JetStream . loadCache [ file ] = null ;
1129- await this . loadBlob ( type , prop , file , false ) . then ( ( blobData ) => {
1130- if ( ! globalThis . allIsGood )
1131- return ;
1132- if ( blobData . type == "preload" )
1133- this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
1134- this . updateCounter ( ) ;
1135- } ) ;
1136-
1137- if ( ! blobData . blob ) {
1138- globalThis . allIsGood = false ;
1139- throw new Error ( "Fetch failed" ) ;
1140- }
1141-
1142- return ! counter . failedPreloadResources && counter . loadedResources == counter . totalResources ;
1143- }
1144-
1145- async retryPrefetchResourcesForBrowser ( ) {
1158+ async retryPrefetchResourcesForBrowser ( counter ) {
1159+ // FIXME: Move to BrowserFileLoader.
11461160 console . assert ( isInBrowser ) ;
11471161
1148- const counter = JetStream . counter ;
11491162 for ( const resource of this . plan . files ) {
1150- const allDone = await this . retryPrefetchResource ( "file" , null , resource ) ;
1163+ const allDone = await browserFileLoader . retryPrefetchResource ( "file" , null , resource ) ;
1164+
11511165 if ( allDone )
11521166 return true ; // All resources loaded, nothing more to do.
11531167 }
11541168
11551169 if ( this . plan . preload ) {
11561170 for ( const [ name , resource ] of Object . entries ( this . plan . preload ) ) {
1157- const allDone = await this . retryPrefetchResource ( "preload" , name , resource ) ;
1171+ const allDone = await browserFileLoader . retryPrefetchResource ( "preload" , name , resource ) ;
11581172 if ( allDone )
11591173 return true ; // All resources loaded, nothing more to do.
11601174 }
@@ -1163,6 +1177,7 @@ class Benchmark {
11631177 }
11641178
11651179 prefetchResourcesForShell ( ) {
1180+ // FIXME: move to ShellFileLoader.
11661181 console . assert ( ! isInBrowser ) ;
11671182
11681183 console . assert ( this . scripts === null , "This initialization should be called only once." ) ;
@@ -1316,14 +1331,14 @@ class GroupedBenchmark extends Benchmark {
13161331 this . benchmarks = benchmarks ;
13171332 }
13181333
1319- async prefetchResourcesForBrowser ( ) {
1334+ async prefetchResourcesForBrowser ( counter ) {
13201335 for ( const benchmark of this . benchmarks )
1321- await benchmark . prefetchResourcesForBrowser ( ) ;
1336+ await benchmark . prefetchResourcesForBrowser ( counter ) ;
13221337 }
13231338
1324- async retryPrefetchResourcesForBrowser ( ) {
1339+ async retryPrefetchResourcesForBrowser ( counter ) {
13251340 for ( const benchmark of this . benchmarks )
1326- await benchmark . retryPrefetchResourcesForBrowser ( ) ;
1341+ await benchmark . retryPrefetchResourcesForBrowser ( counter ) ;
13271342 }
13281343
13291344 prefetchResourcesForShell ( ) {
0 commit comments