@@ -23,6 +23,26 @@ export function* apiRequest(method: PropertyKey, params: unknown): Generator<{ m
2323 return yield { method, params } ;
2424}
2525const deferredGeneratorMarker : unique symbol = Symbol ( ) ;
26+ // Marks executed generators on the generator itself: a WeakSet holding every generator of a long-running batch is
27+ // costly to grow and to process during GC
28+ const executedMarker : unique symbol = Symbol ( ) ;
29+ interface ExecutedGenerator {
30+ [ executedMarker ] ?: true ;
31+ }
32+ const executedNonExtensibleGenerators = new WeakSet < AnyAPIRequestGenerator > ( ) ;
33+
34+ /** Marks the generator as executed, returning false if it already was. */
35+ function markExecuted ( generator : AnyAPIRequestGenerator ) : boolean {
36+ if ( ! Object . isExtensible ( generator ) ) {
37+ if ( executedNonExtensibleGenerators . has ( generator ) ) return false ;
38+ executedNonExtensibleGenerators . add ( generator ) ;
39+ return true ;
40+ }
41+ const target = generator as ExecutedGenerator ;
42+ if ( target [ executedMarker ] ) return false ;
43+ target [ executedMarker ] = true ;
44+ return true ;
45+ }
2646const allGeneratorMarker : unique symbol = Symbol ( ) ;
2747interface DeferredAPIRequest {
2848 readonly method : "__defer" ;
@@ -125,7 +145,6 @@ export function executeRequestGenerators<T extends readonly AnyAPIRequestGenerat
125145 requestGenerators : T ,
126146 executeRequests : ( requests : APIRequest [ ] ) => readonly GeneratorResponse [ ] ,
127147) : ExecutedGeneratorsResults < T > {
128- const registeredGenerators = new WeakSet < AnyAPIRequestGenerator > ( ) ;
129148 let firstGenerator : GeneratorState | undefined ;
130149 let lastGenerator : GeneratorState | undefined ;
131150 const root = startGroup ( requestGenerators ) ;
@@ -220,13 +239,12 @@ export function executeRequestGenerators<T extends readonly AnyAPIRequestGenerat
220239 }
221240
222241 function addGenerator ( generator : AnyAPIRequestGenerator , parent ?: GeneratorGroup ) : void {
223- if ( registeredGenerators . has ( generator ) ) {
242+ if ( ! markExecuted ( generator ) ) {
224243 const error = new Error ( "Cannot execute the same generator instance more than once" ) ;
225244 if ( ! parent ) throw error ;
226245 failGroup ( parent , error ) ;
227246 return ;
228247 }
229- registeredGenerators . add ( generator ) ;
230248 const next = parent ?. parent ;
231249 const previous = next ? next . previous : lastGenerator ;
232250 const state : GeneratorState = {
@@ -265,12 +283,11 @@ export function executeRequestGenerators<T extends readonly AnyAPIRequestGenerat
265283 const wrapper = generator as AllRequestGenerator < unknown > ;
266284 const pending = wrapper . generators ;
267285 if ( ! pending ) break ;
268- if ( registeredGenerators . has ( wrapper ) ) {
286+ if ( ! markExecuted ( wrapper ) ) {
269287 failGroup ( group , new Error ( "Cannot execute the same generator instance more than once" ) ) ;
270288 group . initializing = false ;
271289 return group ;
272290 }
273- registeredGenerators . add ( wrapper ) ;
274291 wrapper . next ( ) ;
275292 ( group . wrappers ??= [ ] ) . push ( wrapper ) ;
276293 generators = pending ;
0 commit comments