@@ -303,6 +303,38 @@ describe('Function: deepMerge', () => {
303303 expect ( ( result . arr as unknown [ ] ) [ 1 ] ) . toBe ( 2 ) ;
304304 } ) ;
305305
306+ it ( 'skips array that references an ancestor array' , ( ) => {
307+ // Prepare - an array contains an object whose property points back to the array
308+ const arr : unknown [ ] = [ ] ;
309+ const inner : Record < string , unknown > = { backRef : arr } ;
310+ arr . push ( inner ) ;
311+ const target = { arr : [ { a : 1 } ] } ;
312+ const source = { arr } ;
313+
314+ // Act
315+ const result = deepMerge ( target , source ) ;
316+
317+ // Assess - inner.backRef is the same array that's in the ancestor chain,
318+ // so the circular array reference is skipped during mergeRecursive
319+ expect ( result . arr ) . toBeDefined ( ) ;
320+ expect ( ( result . arr as Record < string , unknown > [ ] ) [ 0 ] ) . not . toHaveProperty (
321+ 'backRef'
322+ ) ;
323+ } ) ;
324+
325+ it ( 'skips circular plain objects inside arrays' , ( ) => {
326+ // Prepare
327+ const target = { arr : [ { a : 1 } ] } ;
328+ const source : Record < string , unknown > = { b : 2 } ;
329+ source . arr = [ source ] ;
330+
331+ // Act
332+ const result = deepMerge ( target , source ) ;
333+
334+ // Assess - source inside its own array is a circular ref and is skipped
335+ expect ( result ) . toEqual ( { arr : [ { a : 1 } ] , b : 2 } ) ;
336+ } ) ;
337+
306338 it ( 'merges shared array references into all properties' , ( ) => {
307339 // Prepare
308340 const target = { } ;
0 commit comments