@@ -348,28 +348,30 @@ const gtmObserver = new MutationObserver(() => {
348348gtmObserver . observe ( document . documentElement , { childList : true , subtree : true } )
349349
350350// #region History/submit wrapper override
351- const originalMethodsCalledInCurrentChain = new Set < Function > ( )
351+ const skippedWrappedListenerGenerations = new Map < Function , number > ( )
352+ let nextWrappedListenerGeneration = 0
352353
353- function callOriginalMethod ( this : unknown , originalMethod : Function , args : unknown [ ] ) {
354- if ( originalMethodsCalledInCurrentChain . has ( originalMethod ) ) return
355- originalMethod . apply ( this , args )
356- }
357-
358- function withOriginalMethodAlreadyCalled ( originalMethod : Function , callback : VoidFunction ) {
359- const alreadyMarked = originalMethodsCalledInCurrentChain . has ( originalMethod )
360- originalMethodsCalledInCurrentChain . add ( originalMethod )
354+ function withOlderWrappedListenersSkipped ( originalMethod : Function , generation : number , callback : VoidFunction ) {
355+ const previousSkippedGeneration = skippedWrappedListenerGenerations . get ( originalMethod )
356+ skippedWrappedListenerGenerations . set (
357+ originalMethod ,
358+ previousSkippedGeneration === undefined ? generation : Math . max ( previousSkippedGeneration , generation )
359+ )
361360 try {
362361 callback ( )
363362 } finally {
364- if ( ! alreadyMarked ) {
365- originalMethodsCalledInCurrentChain . delete ( originalMethod )
363+ if ( previousSkippedGeneration === undefined ) {
364+ skippedWrappedListenerGenerations . delete ( originalMethod )
365+ } else {
366+ skippedWrappedListenerGenerations . set ( originalMethod , previousSkippedGeneration )
366367 }
367368 }
368369}
369370
370- function wrapListener ( originalMethod : Function , value : Function ) {
371+ function wrapListener ( originalMethod : Function , value ?: Function ) {
372+ const generation = nextWrappedListenerGeneration ++
371373 // the function syntax is important here so we keep the correct `this`.
372- return function yieldingListener ( this : unknown , ...args : unknown [ ] ) {
374+ function yieldingListener ( this : unknown , ...args : unknown [ ] ) {
373375 if ( DEBUG ) {
374376 console . log ( "Yielding for" , originalMethod )
375377 console . timeStamp ( originalMethod as unknown as string )
@@ -378,29 +380,31 @@ function wrapListener(originalMethod: Function, value: Function) {
378380 // We first call the original: This optimizes for UX & correctness of React components.
379381 // e.g., for pushState, when a component renders on a new route, it might set state and/or read from the URL. If the URL isn't
380382 // accurate, it might lead to wrong behavior.
381- // We don't want to call the underlying native method twice if an override calls a previously captured wrapper.
382- callOriginalMethod . call ( this , originalMethod , args )
383+ // If an override calls a previously captured wrapper, that older wrapper skips the native method;
384+ // fresh calls through the current getter still update history/submit normally.
385+ const skippedGeneration = skippedWrappedListenerGenerations . get ( originalMethod )
386+ if ( skippedGeneration === undefined || generation >= skippedGeneration ) {
387+ originalMethod . apply ( this , args )
388+ }
389+
390+ if ( ! value ) return
383391
384392 // If `method` is overriden N times, it creates N yield points (as overrides might be chained)
385393 yieldUnlessUrgent ( ( ) => {
386394 // The arrow FN is important here so we keep the correct `this`.
387- withOriginalMethodAlreadyCalled ( originalMethod , ( ) => {
395+ withOlderWrappedListenersSkipped ( originalMethod , generation , ( ) => {
388396 value . apply ( this , args )
389397 } )
390398 } )
391399 }
400+
401+ return yieldingListener
392402}
393403function overrideListener < T extends object > ( target : T , method : keyof T ) {
394404 // @ts -expect-error TS(2339): Prototype chain call. We try __proto__ first, as this will usually be the original method.
395405 const originalMethod : Function = ( target . __proto__ as unknown as T ) [ method ] ?? ( target [ method ] as Function )
396406
397- let mostRecentWrapper : Function | undefined = wrapListener (
398- originalMethod ,
399- // The function syntax is important here so we keep the correct `this`.
400- function firstOverride ( this : unknown , ...args : unknown [ ] ) {
401- callOriginalMethod . call ( this , originalMethod , args )
402- } ,
403- )
407+ let mostRecentWrapper : Function | undefined = wrapListener ( originalMethod )
404408
405409 Object . defineProperty ( target , method , {
406410 enumerable : true ,
0 commit comments