@@ -28,6 +28,7 @@ const SNAPSHOT_CHAR_LIMIT = 50_000;
2828const DEFAULT_SNAPSHOT_DEPTH = 15 ;
2929const FIND_MATCH_LIMIT = 20 ;
3030const REF_LIMIT_PER_TARGET = 1000 ;
31+ const FRAME_STATE_LIMIT = 1000 ;
3132const SCROLL_NOTCH_PX = 120 ;
3233const EXPECTATION_TIMEOUT_MS = 2_000 ;
3334const EXPECTATION_POLL_MS = 50 ;
@@ -414,7 +415,9 @@ export class BrowserExecutor {
414415 if ( [ ...generations ] . some ( ( [ frameKey , generation ] ) => this . generation ( frameKey ) !== generation ) ) {
415416 throw new ObservationChangedError ( ) ;
416417 }
417- this . pruneFrameState ( targetId , new Set ( generations . keys ( ) ) ) ;
418+ const observedFrames = new Set ( generations . keys ( ) ) ;
419+ if ( complete ) this . pruneFrameState ( targetId , observedFrames ) ;
420+ else this . boundFrameState ( observedFrames ) ;
418421 return {
419422 targetId,
420423 tree,
@@ -1346,6 +1349,36 @@ export class BrowserExecutor {
13461349 }
13471350 }
13481351
1352+ private boundFrameState ( observed : ReadonlySet < string > ) : void {
1353+ const protectedFrames = new Set ( observed ) ;
1354+ for ( const frameId of this . frameSessions . keys ( ) ) protectedFrames . add ( frameId ) ;
1355+ for ( const entry of this . refs . values ( ) ) {
1356+ protectedFrames . add ( entry . frameId ) ;
1357+ if ( entry . sessionTargetId ) protectedFrames . add ( entry . sessionTargetId ) ;
1358+ }
1359+ let added = true ;
1360+ while ( added ) {
1361+ added = false ;
1362+ for ( const [ child , parent ] of this . frameParents ) {
1363+ if ( protectedFrames . has ( child ) && ! protectedFrames . has ( parent ) ) {
1364+ protectedFrames . add ( parent ) ;
1365+ added = true ;
1366+ }
1367+ }
1368+ }
1369+ for ( const frameId of this . frameParents . keys ( ) ) {
1370+ if ( this . frameParents . size <= FRAME_STATE_LIMIT ) break ;
1371+ if ( ! protectedFrames . has ( frameId ) ) {
1372+ this . frameParents . delete ( frameId ) ;
1373+ this . generations . delete ( frameId ) ;
1374+ }
1375+ }
1376+ for ( const frameId of this . generations . keys ( ) ) {
1377+ if ( this . generations . size <= FRAME_STATE_LIMIT ) break ;
1378+ if ( ! protectedFrames . has ( frameId ) ) this . generations . delete ( frameId ) ;
1379+ }
1380+ }
1381+
13491382 private pruneFrameState ( targetId : string , observed : ReadonlySet < string > ) : void {
13501383 const stale = new Set < string > ( ) ;
13511384 for ( const frameId of this . frameParents . keys ( ) ) {
0 commit comments