@@ -10,20 +10,29 @@ let _stripBasename: boolean = false;
1010// Required because window.location hasn't updated yet when handlers are invoked.
1111// Uses a stack to handle overlapping navigations correctly (LIFO semantics).
1212interface NavigationContext {
13- targetPath : string ;
13+ targetPath : string | undefined ;
1414 span : Span | undefined ;
1515}
1616
1717const _navigationContextStack : NavigationContext [ ] = [ ] ;
18+ const MAX_CONTEXT_STACK_SIZE = 10 ;
1819
1920/** Pushes a navigation context before invoking patchRoutesOnNavigation. */
20- export function setNavigationContext ( targetPath : string , span : Span | undefined ) : void {
21+ export function setNavigationContext ( targetPath : string | undefined , span : Span | undefined ) : void {
22+ // Prevent unbounded stack growth from cleanup failures or rapid navigations
23+ if ( _navigationContextStack . length >= MAX_CONTEXT_STACK_SIZE ) {
24+ _navigationContextStack . shift ( ) ; // Remove oldest
25+ }
2126 _navigationContextStack . push ( { targetPath, span } ) ;
2227}
2328
24- /** Pops the most recent navigation context after patchRoutesOnNavigation completes. */
25- export function clearNavigationContext ( ) : void {
26- _navigationContextStack . pop ( ) ;
29+ /** Pops the navigation context for the given span after patchRoutesOnNavigation completes. */
30+ export function clearNavigationContext ( span : Span | undefined ) : void {
31+ // Only pop if top of stack matches this span to prevent corruption from mismatched calls
32+ const top = _navigationContextStack [ _navigationContextStack . length - 1 ] ;
33+ if ( top ?. span === span ) {
34+ _navigationContextStack . pop ( ) ;
35+ }
2736}
2837
2938/** Gets the current (most recent) navigation context if inside a patchRoutesOnNavigation call. */
0 commit comments