Bladeren bron

Fix: Do not execute ResizeObserver's callbacks when the resized element is invisible.

Aleksander Nowodzinski 5 jaren geleden
bovenliggende
commit
fb6b0dc993

+ 6 - 0
packages/ckeditor5-utils/src/dom/resizeobserver.js

@@ -168,6 +168,12 @@ export default class ResizeObserver {
 
 		ResizeObserver._observerInstance = new ObserverConstructor( entries => {
 			for ( const entry of entries ) {
+				// Do not execute callbacks for elements that are invisible.
+				// https://github.com/ckeditor/ckeditor5/issues/6570
+				if ( !entry.target.offsetParent ) {
+					continue;
+				}
+
 				const callbacks = ResizeObserver._getElementCallbacks( entry.target );
 
 				if ( callbacks ) {

+ 61 - 0
packages/ckeditor5-utils/tests/dom/resizeobserver.js

@@ -27,12 +27,18 @@ describe( 'ResizeObserver()', () => {
 		elementA.id = 'A';
 		elementB = document.createElement( 'div' );
 		elementB.id = 'B';
+
+		document.body.appendChild( elementA );
+		document.body.appendChild( elementB );
 	} );
 
 	afterEach( () => {
 		// Make it look like the module was loaded from scratch.
 		ResizeObserver._observerInstance = null;
 		ResizeObserver._elementCallbacks = null;
+
+		elementA.remove();
+		elementB.remove();
 	} );
 
 	describe( 'constructor()', () => {
@@ -108,6 +114,61 @@ describe( 'ResizeObserver()', () => {
 			observerA.destroy();
 		} );
 
+		it( 'should not react to resizing of an element if element is invisible', () => {
+			const callbackA = sinon.spy();
+			let resizeCallback;
+
+			testUtils.sinon.stub( global.window, 'ResizeObserver' ).callsFake( callback => {
+				resizeCallback = callback;
+
+				return {
+					observe() {},
+					unobserve() {}
+				};
+			} );
+
+			const observerA = new ResizeObserver( elementA, callbackA );
+
+			elementA.style.display = 'none';
+
+			resizeCallback( [
+				{ target: elementA }
+			] );
+
+			sinon.assert.notCalled( callbackA );
+
+			observerA.destroy();
+		} );
+
+		it( 'should not react to resizing of an element if element\'s parent is invisible', () => {
+			const callbackA = sinon.spy();
+			let resizeCallback;
+
+			testUtils.sinon.stub( global.window, 'ResizeObserver' ).callsFake( callback => {
+				resizeCallback = callback;
+
+				return {
+					observe() {},
+					unobserve() {}
+				};
+			} );
+
+			const observerA = new ResizeObserver( elementA, callbackA );
+			const parent = document.createElement( 'div' );
+			document.body.appendChild( parent );
+			parent.appendChild( elementA );
+			parent.style.display = 'none';
+
+			resizeCallback( [
+				{ target: elementA }
+			] );
+
+			sinon.assert.notCalled( callbackA );
+
+			parent.remove();
+			observerA.destroy();
+		} );
+
 		it( 'should be able to observe the same element along with other observers', () => {
 			const callbackA = sinon.spy();
 			const callbackB = sinon.spy();