@@ -202,6 +202,137 @@ class ShellFileLoader {
202202 }
203203} ;
204204
205+
206+ class BrowserFileLoader {
207+
208+ constructor ( ) {
209+ // TODO: Cleanup / remove / merge `blobDataCache` and `loadCache` vs.
210+ // the global `fileLoader` cache.
211+ this . blobDataCache = { __proto__ : null } ;
212+ this . loadCache = { __proto__ : null } ;
213+ }
214+
215+ async doLoadBlob ( resource ) {
216+ const blobData = this . blobDataCache [ resource ] ;
217+
218+ const compressed = isCompressed ( resource ) ;
219+ if ( compressed && ! JetStreamParams . prefetchResources ) {
220+ resource = uncompressedName ( resource ) ;
221+ }
222+
223+ // If we aren't supposed to prefetch this then set the blobURL to just
224+ // be the resource URL.
225+ if ( ! JetStreamParams . prefetchResources ) {
226+ blobData . blobURL = resource ;
227+ return blobData ;
228+ }
229+
230+ let response ;
231+ let tries = 3 ;
232+ while ( tries -- ) {
233+ let hasError = false ;
234+ try {
235+ response = await fetch ( resource , { cache : "no-store" } ) ;
236+ } catch ( e ) {
237+ hasError = true ;
238+ }
239+ if ( ! hasError && response . ok )
240+ break ;
241+ if ( tries )
242+ continue ;
243+ throw new Error ( "Fetch failed" ) ;
244+ }
245+
246+ // If we need to decompress this, then run it through a decompression
247+ // stream.
248+ if ( compressed ) {
249+ const stream = response . body . pipeThrough ( new DecompressionStream ( "deflate" ) )
250+ response = new Response ( stream ) ;
251+ }
252+
253+ let blob = await response . blob ( ) ;
254+ blobData . blob = blob ;
255+ blobData . blobURL = URL . createObjectURL ( blob ) ;
256+ return blobData ;
257+ }
258+
259+ async loadBlob ( type , prop , resource , incrementRefCount = true ) {
260+ let blobData = this . blobDataCache [ resource ] ;
261+ if ( ! blobData ) {
262+ blobData = {
263+ type : type ,
264+ prop : prop ,
265+ resource : resource ,
266+ blob : null ,
267+ blobURL : null ,
268+ refCount : 0
269+ } ;
270+ this . blobDataCache [ resource ] = blobData ;
271+ }
272+
273+ if ( incrementRefCount )
274+ blobData . refCount ++ ;
275+
276+ let promise = this . loadCache [ resource ] ;
277+ if ( promise )
278+ return promise ;
279+
280+ promise = this . doLoadBlob ( resource ) ;
281+ this . loadCache [ resource ] = promise ;
282+ return promise ;
283+ }
284+
285+ async retryPrefetchResource ( type , prop , file ) {
286+ console . assert ( isInBrowser ) ;
287+
288+ const counter = JetStream . counter ;
289+ const blobData = this . blobDataCache [ file ] ;
290+ if ( blobData . blob ) {
291+ // The same preload blob may be used by multiple subtests. Though the blob is already loaded,
292+ // we still need to check if this subtest failed to load it before. If so, handle accordingly.
293+ if ( type == "preload" ) {
294+ if ( this . failedPreloads && this . failedPreloads [ blobData . prop ] ) {
295+ this . failedPreloads [ blobData . prop ] = false ;
296+ this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
297+ counter . failedPreloadResources -- ;
298+ }
299+ }
300+ return ! counter . failedPreloadResources && counter . loadedResources == counter . totalResources ;
301+ }
302+
303+ // Retry fetching the resource.
304+ this . loadCache [ file ] = null ;
305+ await this . loadBlob ( type , prop , file , false ) . then ( ( blobData ) => {
306+ if ( ! globalThis . allIsGood )
307+ return ;
308+ if ( blobData . type == "preload" )
309+ this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
310+ this . updateCounter ( ) ;
311+ } ) ;
312+
313+ if ( ! blobData . blob ) {
314+ globalThis . allIsGood = false ;
315+ throw new Error ( "Fetch failed" ) ;
316+ }
317+
318+ return ! counter . failedPreloadResources && counter . loadedResources == counter . totalResources ;
319+ }
320+
321+ free ( files ) {
322+ for ( const file of files ) {
323+ const blobData = this . blobDataCache [ file ] ;
324+ // If we didn't prefetch this resource, then no need to free it
325+ if ( ! blobData . blob ) {
326+ continue
327+ }
328+ blobData . refCount -- ;
329+ if ( ! blobData . refCount )
330+ this . blobDataCache [ file ] = undefined ;
331+ }
332+ }
333+ }
334+
335+ const browserFileLoader = new BrowserFileLoader ( ) ;
205336const shellFileLoader = new ShellFileLoader ( ) ;
206337
207338class Driver {
@@ -213,10 +344,6 @@ class Driver {
213344 this . benchmarks = Array . from ( new Set ( benchmarks ) ) ;
214345 this . benchmarks . sort ( ( a , b ) => a . plan . name . toLowerCase ( ) < b . plan . name . toLowerCase ( ) ? 1 : - 1 ) ;
215346 console . assert ( this . benchmarks . length , "No benchmarks selected" ) ;
216- // TODO: Cleanup / remove / merge `blobDataCache` and `loadCache` vs.
217- // the global `fileLoader` cache.
218- this . blobDataCache = { } ;
219- this . loadCache = { } ;
220347 this . counter = { } ;
221348 this . counter . loadedResources = 0 ;
222349 this . counter . totalResources = 0 ;
@@ -249,17 +376,7 @@ class Driver {
249376 benchmark . updateUIAfterRun ( ) ;
250377
251378 if ( isInBrowser ) {
252- const cache = JetStream . blobDataCache ;
253- for ( const file of benchmark . files ) {
254- const blobData = cache [ file ] ;
255- // If we didn't prefetch this resource, then no need to free it
256- if ( ! blobData . blob ) {
257- continue
258- }
259- blobData . refCount -- ;
260- if ( ! blobData . refCount )
261- cache [ file ] = undefined ;
262- }
379+ browserFileLoader . free ( benchmark . files ) ;
263380 }
264381 }
265382 performance . measure ( "runner update-ui" , "update-ui-start" ) ;
@@ -423,12 +540,12 @@ class Driver {
423540
424541 // TODO: Cleanup the browser path of the preloading below and in
425542 // `prefetchResourcesForBrowser` / `retryPrefetchResourcesForBrowser`.
543+ const counter = JetStream . counter ;
426544 const promises = [ ] ;
427545 for ( const benchmark of this . benchmarks )
428- promises . push ( benchmark . prefetchResourcesForBrowser ( ) ) ;
546+ promises . push ( benchmark . prefetchResourcesForBrowser ( counter ) ) ;
429547 await Promise . all ( promises ) ;
430548
431- const counter = JetStream . counter ;
432549 if ( counter . failedPreloadResources || counter . loadedResources != counter . totalResources ) {
433550 for ( const benchmark of this . benchmarks ) {
434551 const allFilesLoaded = await benchmark . retryPrefetchResourcesForBrowser ( counter ) ;
@@ -744,6 +861,7 @@ class BrowserScripts extends Scripts {
744861 }
745862}
746863
864+
747865class Benchmark {
748866 constructor ( plan )
749867 {
@@ -933,7 +1051,7 @@ class Benchmark {
9331051 for ( const text of this . scripts )
9341052 scripts . add ( text ) ;
9351053 } else {
936- const cache = JetStream . blobDataCache ;
1054+ const cache = browserFileLoader . blobDataCache ;
9371055 for ( const file of this . plan . files ) {
9381056 scripts . addWithURL ( cache [ file ] . blobURL ) ;
9391057 }
@@ -984,75 +1102,6 @@ class Benchmark {
9841102 Realm . dispose ( magicFrame ) ;
9851103 }
9861104
987- async doLoadBlob ( resource ) {
988- const blobData = JetStream . blobDataCache [ resource ] ;
989-
990- const compressed = isCompressed ( resource ) ;
991- if ( compressed && ! JetStreamParams . prefetchResources ) {
992- resource = uncompressedName ( resource ) ;
993- }
994-
995- // If we aren't supposed to prefetch this then set the blobURL to just
996- // be the resource URL.
997- if ( ! JetStreamParams . prefetchResources ) {
998- blobData . blobURL = resource ;
999- return blobData ;
1000- }
1001-
1002- let response ;
1003- let tries = 3 ;
1004- while ( tries -- ) {
1005- let hasError = false ;
1006- try {
1007- response = await fetch ( resource , { cache : "no-store" } ) ;
1008- } catch ( e ) {
1009- hasError = true ;
1010- }
1011- if ( ! hasError && response . ok )
1012- break ;
1013- if ( tries )
1014- continue ;
1015- throw new Error ( "Fetch failed" ) ;
1016- }
1017-
1018- // If we need to decompress this, then run it through a decompression
1019- // stream.
1020- if ( compressed ) {
1021- const stream = response . body . pipeThrough ( new DecompressionStream ( "deflate" ) )
1022- response = new Response ( stream ) ;
1023- }
1024-
1025- let blob = await response . blob ( ) ;
1026- blobData . blob = blob ;
1027- blobData . blobURL = URL . createObjectURL ( blob ) ;
1028- return blobData ;
1029- }
1030-
1031- async loadBlob ( type , prop , resource , incrementRefCount = true ) {
1032- let blobData = JetStream . blobDataCache [ resource ] ;
1033- if ( ! blobData ) {
1034- blobData = {
1035- type : type ,
1036- prop : prop ,
1037- resource : resource ,
1038- blob : null ,
1039- blobURL : null ,
1040- refCount : 0
1041- } ;
1042- JetStream . blobDataCache [ resource ] = blobData ;
1043- }
1044-
1045- if ( incrementRefCount )
1046- blobData . refCount ++ ;
1047-
1048- let promise = JetStream . loadCache [ resource ] ;
1049- if ( promise )
1050- return promise ;
1051-
1052- promise = this . doLoadBlob ( resource ) ;
1053- JetStream . loadCache [ resource ] = promise ;
1054- return promise ;
1055- }
10561105
10571106 updateCounter ( ) {
10581107 const counter = JetStream . counter ;
@@ -1061,10 +1110,10 @@ class Benchmark {
10611110 statusElement . innerHTML = `Loading ${ counter . loadedResources } of ${ counter . totalResources } ...` ;
10621111 }
10631112
1064- prefetchResourcesForBrowser ( ) {
1113+ prefetchResourcesForBrowser ( counter ) {
10651114 console . assert ( isInBrowser ) ;
10661115
1067- const promises = this . plan . files . map ( ( file ) => this . loadBlob ( "file" , null , file ) . then ( ( blobData ) => {
1116+ const promises = this . plan . files . map ( ( file ) => browserFileLoader . loadBlob ( "file" , null , file ) . then ( ( blobData ) => {
10681117 if ( ! globalThis . allIsGood )
10691118 return ;
10701119 this . updateCounter ( ) ;
@@ -1074,7 +1123,7 @@ class Benchmark {
10741123
10751124 if ( this . plan . preload ) {
10761125 for ( const [ name , resource ] of Object . entries ( this . plan . preload ) ) {
1077- promises . push ( this . loadBlob ( "preload" , name , resource ) . then ( ( blobData ) => {
1126+ promises . push ( browserFileLoader . loadBlob ( "preload" , name , resource ) . then ( ( blobData ) => {
10781127 if ( ! globalThis . allIsGood )
10791128 return ;
10801129 this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
@@ -1084,7 +1133,7 @@ class Benchmark {
10841133 if ( ! this . failedPreloads )
10851134 this . failedPreloads = { } ;
10861135 this . failedPreloads [ name ] = true ;
1087- JetStream . counter . failedPreloadResources ++ ;
1136+ counter . failedPreloadResources ++ ;
10881137 } ) ) ;
10891138 }
10901139 }
@@ -1093,55 +1142,20 @@ class Benchmark {
10931142 return Promise . all ( promises ) ;
10941143 }
10951144
1096- async retryPrefetchResource ( type , prop , file ) {
1097- console . assert ( isInBrowser ) ;
1098-
1099- const counter = JetStream . counter ;
1100- const blobData = JetStream . blobDataCache [ file ] ;
1101- if ( blobData . blob ) {
1102- // The same preload blob may be used by multiple subtests. Though the blob is already loaded,
1103- // we still need to check if this subtest failed to load it before. If so, handle accordingly.
1104- if ( type == "preload" ) {
1105- if ( this . failedPreloads && this . failedPreloads [ blobData . prop ] ) {
1106- this . failedPreloads [ blobData . prop ] = false ;
1107- this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
1108- counter . failedPreloadResources -- ;
1109- }
1110- }
1111- return ! counter . failedPreloadResources && counter . loadedResources == counter . totalResources ;
1112- }
1113-
1114- // Retry fetching the resource.
1115- JetStream . loadCache [ file ] = null ;
1116- await this . loadBlob ( type , prop , file , false ) . then ( ( blobData ) => {
1117- if ( ! globalThis . allIsGood )
1118- return ;
1119- if ( blobData . type == "preload" )
1120- this . preloads . push ( { name : blobData . prop , resource : blobData . resource , blobURLOrPath : blobData . blobURL } ) ;
1121- this . updateCounter ( ) ;
1122- } ) ;
1123-
1124- if ( ! blobData . blob ) {
1125- globalThis . allIsGood = false ;
1126- throw new Error ( "Fetch failed" ) ;
1127- }
1128-
1129- return ! counter . failedPreloadResources && counter . loadedResources == counter . totalResources ;
1130- }
1131-
1132- async retryPrefetchResourcesForBrowser ( ) {
1145+ async retryPrefetchResourcesForBrowser ( counter ) {
1146+ // FIXME: Move to BrowserFileLoader.
11331147 console . assert ( isInBrowser ) ;
11341148
1135- const counter = JetStream . counter ;
11361149 for ( const resource of this . plan . files ) {
1137- const allDone = await this . retryPrefetchResource ( "file" , null , resource ) ;
1150+ const allDone = await browserFileLoader . retryPrefetchResource ( "file" , null , resource ) ;
1151+
11381152 if ( allDone )
11391153 return true ; // All resources loaded, nothing more to do.
11401154 }
11411155
11421156 if ( this . plan . preload ) {
11431157 for ( const [ name , resource ] of Object . entries ( this . plan . preload ) ) {
1144- const allDone = await this . retryPrefetchResource ( "preload" , name , resource ) ;
1158+ const allDone = await browserFileLoader . retryPrefetchResource ( "preload" , name , resource ) ;
11451159 if ( allDone )
11461160 return true ; // All resources loaded, nothing more to do.
11471161 }
@@ -1150,6 +1164,7 @@ class Benchmark {
11501164 }
11511165
11521166 prefetchResourcesForShell ( ) {
1167+ // FIXME: move to ShellFileLoader.
11531168 console . assert ( ! isInBrowser ) ;
11541169
11551170 console . assert ( this . scripts === null , "This initialization should be called only once." ) ;
@@ -1303,14 +1318,14 @@ class GroupedBenchmark extends Benchmark {
13031318 this . benchmarks = benchmarks ;
13041319 }
13051320
1306- async prefetchResourcesForBrowser ( ) {
1321+ async prefetchResourcesForBrowser ( counter ) {
13071322 for ( const benchmark of this . benchmarks )
1308- await benchmark . prefetchResourcesForBrowser ( ) ;
1323+ await benchmark . prefetchResourcesForBrowser ( counter ) ;
13091324 }
13101325
1311- async retryPrefetchResourcesForBrowser ( ) {
1326+ async retryPrefetchResourcesForBrowser ( counter ) {
13121327 for ( const benchmark of this . benchmarks )
1313- await benchmark . retryPrefetchResourcesForBrowser ( ) ;
1328+ await benchmark . retryPrefetchResourcesForBrowser ( counter ) ;
13141329 }
13151330
13161331 prefetchResourcesForShell ( ) {
0 commit comments