Sfoglia il codice sorgente

Fixed `shouldNodeBeSkipped` - added support for symbols and iterable entities.

Maciej Bukowski 6 anni fa
parent
commit
aa74de0558

+ 8 - 6
packages/ckeditor5-watchdog/src/watchdog.js

@@ -294,8 +294,8 @@ mix( Watchdog, EmitterMixin );
 function areElementsConnected( from, searchedElement ) {
 	const nodes = [ from ];
 
-	// Elements are stored to prevent infinite looping.
-	const storedElements = new WeakSet();
+	// Nodes are stored to prevent infinite looping.
+	const storedNodes = new WeakSet();
 
 	while ( nodes.length > 0 ) {
 		// BFS should be faster.
@@ -305,13 +305,14 @@ function areElementsConnected( from, searchedElement ) {
 			return true;
 		}
 
-		if ( storedElements.has( node ) || shouldNodeBeSkipped( node ) ) {
+		if ( storedNodes.has( node ) || shouldNodeBeSkipped( node ) ) {
 			continue;
 		}
 
-		storedElements.add( node );
+		storedNodes.add( node );
 
-		if ( Array.isArray( node ) ) {
+		// Handle arrays, maps, sets, custom collections that implements `[ Symbol.iterator ]()`, etc.
+		if ( node[ Symbol.iterator ] ) {
 			nodes.push( ...node );
 		} else {
 			nodes.push( ...Object.values( node ) );
@@ -328,13 +329,14 @@ function shouldNodeBeSkipped( obj ) {
 		type === '[object Number]' ||
 		type === '[object Boolean]' ||
 		type === '[object String]' ||
+		type === '[object Symbol]' ||
 		type === '[object Function]' ||
 		type === '[object Date]' ||
 
 		obj === undefined ||
 		obj === null ||
 
-		// Skip native DOM objects, e.g. Window, nodes, events, etc.s
+		// Skip native DOM objects, e.g. Window, nodes, events, etc.
 		obj instanceof EventTarget
 	);
 }

+ 10 - 24
packages/ckeditor5-watchdog/tests/watchdog.js

@@ -166,29 +166,6 @@ describe( 'Watchdog', () => {
 				);
 		} );
 
-		it( 'Watchdog should intercept editor errors and restart the editor during the runtime', () => {
-			const watchdog = new Watchdog();
-
-			watchdog.setCreator( ( el, config ) => FakeEditor.create( el, config ) );
-			watchdog.setDestructor( editor => editor.destroy() );
-
-			// sinon.stub( window, 'onerror' ).value( undefined ); and similar don't work.
-			const originalErrorHandler = window.onerror;
-			window.onerror = undefined;
-
-			return watchdog.create( document.createElement( 'div' ) ).then( () => {
-				setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );
-
-				return new Promise( res => {
-					watchdog.on( 'restart', () => {
-						window.onerror = originalErrorHandler;
-
-						watchdog.destroy().then( res );
-					} );
-				} );
-			} );
-		} );
-
 		it( 'Watchdog should not hide intercepted errors', () => {
 			const watchdog = new Watchdog();
 
@@ -344,7 +321,16 @@ describe( 'Watchdog', () => {
 			window.onerror = undefined;
 
 			return watchdog.create( document.createElement( 'div' ) ).then( () => {
-				setTimeout( () => throwCKEditorError( 'foo', { foo: [ 1, 2, 3, { bar: watchdog.editor } ] } ) );
+				setTimeout( () => throwCKEditorError( 'foo', {
+					foo: [ 1, 2, 3, {
+						bar: new Set( [
+							new Map( [
+								[ 'foo', 'bar' ],
+								[ 0, watchdog.editor ]
+							] )
+						] )
+					} ]
+				} ) );
 
 				return new Promise( res => {
 					watchdog.on( 'restart', () => {