From 1139a4e42cad9035b003fd743a1797753e10c4bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Velad=20Galv=C3=A1n?= Date: Tue, 17 Feb 2026 11:03:18 +0100 Subject: [PATCH] fix(UITextDisplayer): avoid ResizeObserver loop warning (#9722) UITextDisplayer was triggering: "ResizeObserver loop completed with undelivered notifications" This happened because updateCaptions_() mutates the DOM inside the ResizeObserver callback, which can cause synchronous layout feedback loops. This change: - Observes videoContainer_ instead of textContainer_ - Defers updateCaptions_() using requestAnimationFrame - Coalesces multiple resize events using a pendingResize_ flag - Ensures updates only run when captions are visible This prevents layout feedback loops while preserving correct caption re-rendering behavior. Fixes https://github.com/shaka-project/shaka-player/issues/9721 --- lib/text/ui_text_displayer.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/text/ui_text_displayer.js b/lib/text/ui_text_displayer.js index 077498cc0..796bb3577 100644 --- a/lib/text/ui_text_displayer.js +++ b/lib/text/ui_text_displayer.js @@ -122,13 +122,32 @@ shaka.text.UITextDisplayer = class { } }); + /** @private {boolean} */ + this.pendingResize_ = false; + /** @private {ResizeObserver} */ this.resizeObserver_ = null; if ('ResizeObserver' in window) { this.resizeObserver_ = new ResizeObserver(() => { - this.updateCaptions_(/* forceUpdate= */ true); + if (this.pendingResize_) { + return; + } + this.pendingResize_ = true; + requestAnimationFrame(() => { + this.pendingResize_ = false; + + if (!this.textContainer_) { + return; + } + + if (this.textContainer_.parentElement && this.isTextVisible_) { + this.updateCaptions_(/* forceUpdate= */ true); + } + }); }); - this.resizeObserver_.observe(this.textContainer_); + goog.asserts.assert(this.videoContainer_, + 'this.videoContainer_ must be non-null'); + this.resizeObserver_.observe(this.videoContainer_); } /** @private {Map} */