Skip to content

Commit

Permalink
fix: Avoid ResizeObserver loop limit exceeded.
Browse files Browse the repository at this point in the history
Since ResizeObserver seems to be firing the callback immediately after observe() is called, this causes an infinite loop. Wrap ResizeObserver callback in requestAnimationFrame.

Fixes #40
  • Loading branch information
Marshal27 committed Sep 29, 2023
1 parent c34d546 commit 6132cde
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 10 deletions.
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,6 @@ The polyfill uses the CSS [`:where()`](https://developer.mozilla.org/en-US/docs/

This is to ensure the specificity of your rules never changes (e.g. while the polyfill is loading, or on browsers with native support for container queries). On browsers without `:where()` supports, rules without the dummy will be ignored.

## ResizeObserver Loop Errors

When using the polyfill, you may observe reports of errors like `ResizeObserver loop completed with undelivered notifications` or `ResizeObserver loop limit exceeded`. These are expected, and may safely be ignored.

## License

[Apache 2.0](LICENSE)
24 changes: 18 additions & 6 deletions src/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,25 @@ export function initializePolyfill(updateCallback: () => void) {
// TODO: implement monkeypatch for CSSStyleSheet.prototype.insertRule and CSSStyleSheet.prototype.deleteRule
// as they currently are not handled.

const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
const instance = getOrCreateInstance(entry.target);
instance.resize();
let animationFrameId: number;

const originalUnobserve = ResizeObserver.prototype.unobserve;
ResizeObserver.prototype.unobserve = function (target: Element) {
if (animationFrameId) {
window.cancelAnimationFrame(animationFrameId);
}
getOrCreateInstance(documentElement).update(computeRootState());
updateCallback();
return originalUnobserve.apply(this, [target]);
}

const resizeObserver = new ResizeObserver(entries => {
animationFrameId = window.requestAnimationFrame(() => {
for (const entry of entries) {
const instance = getOrCreateInstance(entry.target);
instance.resize();
}
getOrCreateInstance(documentElement).update(computeRootState());
updateCallback();
});
});

const rootController = new NodeController(documentElement);
Expand Down

0 comments on commit 6132cde

Please sign in to comment.