From 0567641fbe4bdbea54b5de0bcc2c937dfb52e088 Mon Sep 17 00:00:00 2001
From: senky <87317406+jaksenko@users.noreply.github.com>
Date: Thu, 10 Feb 2022 09:51:53 +0100
Subject: [PATCH] fix(core): wrap resize observer callback in
 requestAnimationFrame (#5441)

Fast browser window resize produces `Error: ResizeObserver loop limit
exceeded`. The error isn't visible in browser console, doesn't affect
functionality, but degrades performance of slider. Solution is taken
from https://stackoverflow.com/a/58701523/17278571.

Fixes #5440
---
 src/core/modules/resize/resize.js | 34 ++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/src/core/modules/resize/resize.js b/src/core/modules/resize/resize.js
index 8b27b14bd..b1f359054 100644
--- a/src/core/modules/resize/resize.js
+++ b/src/core/modules/resize/resize.js
@@ -3,6 +3,7 @@ import { getWindow } from 'ssr-window';
 export default function Resize({ swiper, on, emit }) {
   const window = getWindow();
   let observer = null;
+  let animationFrame = null;
 
   const resizeHandler = () => {
     if (!swiper || swiper.destroyed || !swiper.initialized) return;
@@ -13,26 +14,31 @@ export default function Resize({ swiper, on, emit }) {
   const createObserver = () => {
     if (!swiper || swiper.destroyed || !swiper.initialized) return;
     observer = new ResizeObserver((entries) => {
-      const { width, height } = swiper;
-      let newWidth = width;
-      let newHeight = height;
-      entries.forEach(({ contentBoxSize, contentRect, target }) => {
-        if (target && target !== swiper.el) return;
-        newWidth = contentRect
-          ? contentRect.width
-          : (contentBoxSize[0] || contentBoxSize).inlineSize;
-        newHeight = contentRect
-          ? contentRect.height
-          : (contentBoxSize[0] || contentBoxSize).blockSize;
+      animationFrame = window.requestAnimationFrame(() => {
+        const { width, height } = swiper;
+        let newWidth = width;
+        let newHeight = height;
+        entries.forEach(({ contentBoxSize, contentRect, target }) => {
+          if (target && target !== swiper.el) return;
+          newWidth = contentRect
+            ? contentRect.width
+            : (contentBoxSize[0] || contentBoxSize).inlineSize;
+          newHeight = contentRect
+            ? contentRect.height
+            : (contentBoxSize[0] || contentBoxSize).blockSize;
+        });
+        if (newWidth !== width || newHeight !== height) {
+          resizeHandler();
+        }
       });
-      if (newWidth !== width || newHeight !== height) {
-        resizeHandler();
-      }
     });
     observer.observe(swiper.el);
   };
 
   const removeObserver = () => {
+    if (animationFrame) {
+      window.cancelAnimationFrame(animationFrame);
+    }
     if (observer && observer.unobserve && swiper.el) {
       observer.unobserve(swiper.el);
       observer = null;