1
1
// biome-ignore lint/style/useNodejsImportProtocol: use 'events' module instead of node builtin
2
2
import EventEmitter from 'events' ;
3
- import { AsyncSeriesHook } from 'tapable' ;
3
+ import { AsyncSeriesHook , AsyncSeriesWaterfallHook } from 'tapable' ;
4
4
import NativeScriptManager , {
5
5
type NormalizedScriptLocator ,
6
6
} from './NativeScriptManager.js' ;
@@ -55,12 +55,6 @@ export interface ResolverOptions {
55
55
key ?: string ;
56
56
}
57
57
58
- interface ScriptHookParams {
59
- scriptId : string ;
60
- caller ?: string ;
61
- error ?: Error ;
62
- }
63
-
64
58
/**
65
59
* A manager to ease resolution, downloading and executing additional code from:
66
60
* - arbitrary JavaScript scripts
@@ -114,15 +108,49 @@ interface ScriptHookParams {
114
108
* ```
115
109
*/
116
110
export class ScriptManager extends EventEmitter {
117
- hooks : {
118
- beforeResolve : AsyncSeriesHook < [ ScriptHookParams ] > ;
119
- resolve : AsyncSeriesHook < [ ScriptHookParams ] > ;
120
- afterResolve : AsyncSeriesHook < [ ScriptHookParams ] > ;
121
- errorResolve : AsyncSeriesHook < [ ScriptHookParams ] > ;
122
- beforeLoad : AsyncSeriesHook < [ ScriptHookParams ] > ;
123
- load : AsyncSeriesHook < [ ScriptHookParams ] > ;
124
- afterLoad : AsyncSeriesHook < [ ScriptHookParams ] > ;
125
- errorLoad : AsyncSeriesHook < [ ScriptHookParams ] > ;
111
+ private resolvers : Array < [ string , string | number , ScriptLocatorResolver ] > =
112
+ [ ] ;
113
+ protected cache : Cache = { } ;
114
+ private storage ?: StorageApi ;
115
+
116
+ public hooks = {
117
+ beforeResolve : new AsyncSeriesWaterfallHook < {
118
+ scriptId : string ;
119
+ caller ?: string ;
120
+ } > ( [ 'params' ] ) ,
121
+ resolve : new AsyncSeriesHook < { scriptId : string ; caller ?: string } , void > ( [
122
+ 'params' ,
123
+ ] ) ,
124
+ afterResolve : new AsyncSeriesHook <
125
+ { scriptId : string ; caller ?: string } ,
126
+ void
127
+ > ( [ 'params' ] ) ,
128
+ errorResolve : new AsyncSeriesHook <
129
+ {
130
+ scriptId : string ;
131
+ caller ?: string ;
132
+ error : Error ;
133
+ } ,
134
+ void
135
+ > ( [ 'params' ] ) ,
136
+ beforeLoad : new AsyncSeriesHook <
137
+ { scriptId : string ; caller ?: string } ,
138
+ void
139
+ > ( [ 'params' ] ) ,
140
+ load : new AsyncSeriesHook < { scriptId : string ; caller ?: string } , void > ( [
141
+ 'params' ,
142
+ ] ) ,
143
+ afterLoad : new AsyncSeriesHook < { scriptId : string ; caller ?: string } , void > (
144
+ [ 'params' ]
145
+ ) ,
146
+ errorLoad : new AsyncSeriesHook <
147
+ {
148
+ scriptId : string ;
149
+ caller ?: string ;
150
+ error : Error ;
151
+ } ,
152
+ void
153
+ > ( [ 'params' ] ) ,
126
154
} ;
127
155
128
156
static init ( ) {
@@ -135,11 +163,8 @@ export class ScriptManager extends EventEmitter {
135
163
return __webpack_require__ . repack . shared . scriptManager ! ;
136
164
}
137
165
138
- protected cache : Cache = { } ;
139
166
protected scriptsPromises : ScriptsPromises = { } ;
140
167
protected cacheInitialized = false ;
141
- protected resolvers : [ string , number , ScriptLocatorResolver ] [ ] = [ ] ;
142
- protected storage ?: StorageApi ;
143
168
144
169
/**
145
170
* Constructs instance of `ScriptManager`.
@@ -164,17 +189,6 @@ export class ScriptManager extends EventEmitter {
164
189
) ;
165
190
}
166
191
167
- this . hooks = {
168
- beforeResolve : new AsyncSeriesHook < [ ScriptHookParams ] > ( [ 'params' ] ) ,
169
- resolve : new AsyncSeriesHook < [ ScriptHookParams ] > ( [ 'params' ] ) ,
170
- afterResolve : new AsyncSeriesHook < [ ScriptHookParams ] > ( [ 'params' ] ) ,
171
- errorResolve : new AsyncSeriesHook < [ ScriptHookParams ] > ( [ 'params' ] ) ,
172
- beforeLoad : new AsyncSeriesHook < [ ScriptHookParams ] > ( [ 'params' ] ) ,
173
- load : new AsyncSeriesHook < [ ScriptHookParams ] > ( [ 'params' ] ) ,
174
- afterLoad : new AsyncSeriesHook < [ ScriptHookParams ] > ( [ 'params' ] ) ,
175
- errorLoad : new AsyncSeriesHook < [ ScriptHookParams ] > ( [ 'params' ] ) ,
176
- } ;
177
-
178
192
__webpack_require__ . repack . shared . scriptManager = this ;
179
193
}
180
194
@@ -213,7 +227,7 @@ export class ScriptManager extends EventEmitter {
213
227
this . resolvers = this . resolvers
214
228
. filter ( ( [ key ] ) => key !== uniqueKey )
215
229
. concat ( [ [ uniqueKey ?? DEFAULT_RESOLVER_KEY , priority , resolver ] ] )
216
- . sort ( ( [ , a ] , [ , b ] ) => b - a ) ;
230
+ . sort ( ( [ , a ] , [ , b ] ) => Number ( b ) - Number ( a ) ) ;
217
231
}
218
232
219
233
/**
@@ -283,41 +297,67 @@ export class ScriptManager extends EventEmitter {
283
297
webpackContext = getWebpackContext ( ) ,
284
298
referenceUrl ?: string
285
299
) : Promise < Script > {
286
- await this . initCache ( ) ;
300
+ let finalScriptId = scriptId ;
301
+ let finalCaller = caller ;
302
+
287
303
try {
304
+ await this . initCache ( ) ;
305
+
288
306
if ( ! this . resolvers . length ) {
289
- throw new Error (
307
+ const error = new Error (
290
308
'No script resolvers were added. Did you forget to call `ScriptManager.shared.addResolver(...)`?'
291
309
) ;
310
+ await this . hooks . errorResolve . promise ( {
311
+ scriptId : finalScriptId ,
312
+ caller : finalCaller ,
313
+ error,
314
+ } ) ;
315
+ throw error ;
292
316
}
293
317
294
- await this . hooks . beforeResolve . promise ( { scriptId, caller } ) ;
295
- this . emit ( 'resolving' , { scriptId, caller } ) ;
318
+ const hookResult = await this . hooks . beforeResolve . promise ( {
319
+ scriptId,
320
+ caller,
321
+ } ) ;
322
+
323
+ if ( hookResult ) {
324
+ finalScriptId = hookResult . scriptId ;
325
+ finalCaller = hookResult . caller ;
326
+ }
327
+
328
+ this . emit ( 'resolving' , { scriptId : finalScriptId , caller : finalCaller } ) ;
296
329
297
330
// Check if there are any taps in the resolve hook
298
331
const _hasResolveHooks = this . hooks . resolve . taps . length > 0 ;
299
332
300
333
let locator : ScriptLocator | undefined ;
301
334
302
335
// if (hasResolveHooks) {
303
- await this . hooks . resolve . promise ( { scriptId, caller } ) ;
336
+ await this . hooks . resolve . promise ( {
337
+ scriptId : finalScriptId ,
338
+ caller : finalCaller ,
339
+ } ) ;
304
340
// } else {
305
341
for ( const [ , , resolve ] of this . resolvers ) {
306
- const resolvedLocator = await resolve ( scriptId , caller , referenceUrl ) ;
342
+ const resolvedLocator = await resolve (
343
+ finalScriptId ,
344
+ finalCaller ,
345
+ referenceUrl
346
+ ) ;
307
347
if ( resolvedLocator ) {
308
348
locator = resolvedLocator ;
309
349
break ;
310
350
}
351
+ // }
311
352
}
312
- // }
313
353
314
354
if ( ! locator ) {
315
355
const error = new Error (
316
- `No resolver was able to resolve script ${ scriptId } `
356
+ `No resolver was able to resolve script ${ finalScriptId } `
317
357
) ;
318
358
await this . hooks . errorResolve . promise ( {
319
- scriptId,
320
- caller,
359
+ scriptId : finalScriptId ,
360
+ caller : finalCaller ,
321
361
error,
322
362
} ) ;
323
363
throw error ;
@@ -327,15 +367,19 @@ export class ScriptManager extends EventEmitter {
327
367
locator . url = locator . url ( webpackContext ) ;
328
368
}
329
369
330
- const script = Script . from ( { scriptId, caller } , locator , false ) ;
370
+ const script = Script . from (
371
+ { scriptId : finalScriptId , caller : finalCaller } ,
372
+ locator ,
373
+ false
374
+ ) ;
331
375
const cacheKey = script . locator . uniqueId ;
332
376
333
377
// Check if user provided a custom shouldUpdateScript function
334
378
if ( locator . shouldUpdateScript ) {
335
379
// If so, we need to wait for it to resolve
336
380
const fetch = await locator . shouldUpdateScript (
337
- scriptId ,
338
- caller ,
381
+ finalScriptId ,
382
+ finalCaller ,
339
383
script . shouldUpdateCache ( this . cache [ cacheKey ] )
340
384
) ;
341
385
@@ -344,7 +388,7 @@ export class ScriptManager extends EventEmitter {
344
388
script . locator . fetch = true ;
345
389
}
346
390
347
- await this . hooks . resolve . promise ( { scriptId, caller } ) ;
391
+ // await this.hooks.resolve.promise({ scriptId: finalScriptId , caller: finalCaller });
348
392
this . emit ( 'resolved' , script . toObject ( ) ) ;
349
393
350
394
// if it returns false, we don't need to fetch the script
@@ -358,24 +402,23 @@ export class ScriptManager extends EventEmitter {
358
402
script . locator . fetch = true ;
359
403
}
360
404
361
- // Only call resolve hook if it wasn't called during resolution
362
- // if (!hasResolveHooks) {
363
- await this . hooks . resolve . promise ( { scriptId, caller } ) ;
364
- // }
365
- await this . hooks . afterResolve . promise ( { scriptId, caller } ) ;
405
+ await this . hooks . afterResolve . promise ( {
406
+ scriptId : finalScriptId ,
407
+ caller : finalCaller ,
408
+ } ) ;
366
409
this . emit ( 'resolved' , script . toObject ( ) ) ;
367
410
368
411
return script ;
369
412
} catch ( error ) {
370
413
await this . hooks . errorResolve . promise ( {
371
- scriptId,
372
- caller,
414
+ scriptId : finalScriptId ,
415
+ caller : finalCaller ,
373
416
error : error as Error ,
374
417
} ) ;
375
418
this . handleError (
376
419
error ,
377
420
'[ScriptManager] Failed while resolving script locator:' ,
378
- { scriptId, caller }
421
+ { scriptId : finalScriptId , caller : finalCaller }
379
422
) ;
380
423
}
381
424
}
@@ -427,24 +470,30 @@ export class ScriptManager extends EventEmitter {
427
470
) ;
428
471
429
472
try {
430
- await this . hooks . beforeLoad . promise ( { scriptId, caller } ) ;
473
+ await this . hooks . beforeLoad . promise ( {
474
+ scriptId : scriptId ,
475
+ caller : caller ,
476
+ } ) ;
431
477
this . emit ( 'loading' , script . toObject ( ) ) ;
432
478
433
479
const _hasLoadHooks = this . hooks . load . taps . length > 0 ;
434
480
// if (hasLoadHooks) {
435
- await this . hooks . load . promise ( { scriptId, caller } ) ;
481
+ await this . hooks . load . promise ( { scriptId : scriptId , caller : caller } ) ;
436
482
// } else {
437
483
await this . loadScriptWithRetry ( scriptId , script . locator ) ;
438
484
// }
439
485
440
- await this . hooks . afterLoad . promise ( { scriptId, caller } ) ;
486
+ await this . hooks . afterLoad . promise ( {
487
+ scriptId : scriptId ,
488
+ caller : caller ,
489
+ } ) ;
441
490
this . emit ( 'loaded' , script . toObject ( ) ) ;
442
491
await this . updateCache ( script ) ;
443
492
} catch ( error ) {
444
493
const { code } = error as Error & { code : string } ;
445
494
await this . hooks . errorLoad . promise ( {
446
- scriptId,
447
- caller,
495
+ scriptId : scriptId ,
496
+ caller : caller ,
448
497
error : error as Error ,
449
498
} ) ;
450
499
this . handleError (
0 commit comments