@@ -413,6 +413,7 @@ export class ElementObserverManager {
413413 private resizeObserver : ResizeObserver
414414 private mutationObserver : MutationObserver
415415 private observedElements : Map < HTMLElement , ( ) => void >
416+ private pendingReconnectFrame : number | undefined
416417
417418 private constructor ( ) {
418419 this . observedElements = new Map ( )
@@ -467,40 +468,58 @@ export class ElementObserverManager {
467468
468469 this . observedElements . set ( element , callback )
469470 this . resizeObserver . observe ( element )
470- this . mutationObserver . observe ( element , {
471- childList : true ,
472- subtree : true ,
473- attributes : true ,
474- characterData : true ,
475- } )
471+ if ( ! this . pendingReconnectFrame ) {
472+ this . mutationObserver . observe ( element , {
473+ childList : true ,
474+ subtree : true ,
475+ attributes : true ,
476+ characterData : true ,
477+ } )
478+ }
476479 }
477480
478481 public unobserve ( element : HTMLElement ) : void {
479482 if ( ! element ) return
480483 this . observedElements . delete ( element )
481484 this . resizeObserver . unobserve ( element )
482485
483- // Disconnect and reconnect mutation observer to refresh the list of observed elements
484- this . mutationObserver . disconnect ( )
485- for ( const observedElement of this . observedElements . keys ( ) ) {
486- if ( ! document . contains ( observedElement ) ) {
487- this . observedElements . delete ( observedElement )
488- this . resizeObserver . unobserve ( observedElement )
489- }
490- }
491-
492486 if ( this . observedElements . size === 0 ) {
487+ if ( this . pendingReconnectFrame ) {
488+ window . cancelAnimationFrame ( this . pendingReconnectFrame )
489+ this . pendingReconnectFrame = undefined
490+ }
491+ this . mutationObserver . disconnect ( )
493492 this . resizeObserver . disconnect ( )
494493 return
495494 }
496495
497- this . observedElements . forEach ( ( _ , el ) => {
498- this . mutationObserver . observe ( el , {
499- childList : true ,
500- subtree : true ,
501- attributes : true ,
502- characterData : true ,
496+ if ( ! this . pendingReconnectFrame ) {
497+ this . pendingReconnectFrame = window . requestAnimationFrame ( ( ) => {
498+ this . pendingReconnectFrame = undefined
499+
500+ // MutationObserver has no per-element unobserve, so we reconnect once per frame.
501+ this . mutationObserver . disconnect ( )
502+ for ( const observedElement of this . observedElements . keys ( ) ) {
503+ if ( ! document . contains ( observedElement ) ) {
504+ this . observedElements . delete ( observedElement )
505+ this . resizeObserver . unobserve ( observedElement )
506+ }
507+ }
508+
509+ if ( this . observedElements . size === 0 ) {
510+ this . resizeObserver . disconnect ( )
511+ return
512+ }
513+
514+ this . observedElements . forEach ( ( _ , el ) => {
515+ this . mutationObserver . observe ( el , {
516+ childList : true ,
517+ subtree : true ,
518+ attributes : true ,
519+ characterData : true ,
520+ } )
521+ } )
503522 } )
504- } )
523+ }
505524 }
506525}
0 commit comments