@@ -11,30 +11,35 @@ export { DeepnoteBlock, DeepnoteNotebook, DeepnoteOutput, DeepnoteFile } from '.
1111
1212/**
1313 * Deep clones an object while removing circular references.
14- * Circular references are replaced with undefined to make the object serializable .
14+ * Uses a recursion stack pattern to only drop true cycles, preserving shared references .
1515 */
16- function cloneWithoutCircularRefs < T > ( obj : T , seen = new WeakSet ( ) ) : T {
16+ function cloneWithoutCircularRefs < T > ( obj : T , seen = new WeakSet < object > ( ) ) : T {
1717 if ( obj === null || typeof obj !== 'object' ) {
1818 return obj ;
1919 }
2020
21- if ( seen . has ( obj ) ) {
21+ if ( seen . has ( obj as object ) ) {
22+ // True circular reference on the current path - drop it
2223 return undefined as T ;
2324 }
2425
25- seen . add ( obj ) ;
26+ seen . add ( obj as object ) ;
2627
27- if ( Array . isArray ( obj ) ) {
28- return obj . map ( ( item ) => cloneWithoutCircularRefs ( item , seen ) ) as T ;
29- }
28+ try {
29+ if ( Array . isArray ( obj ) ) {
30+ return obj . map ( ( item ) => cloneWithoutCircularRefs ( item , seen ) ) as T ;
31+ }
3032
31- const clone : Record < string , unknown > = { } ;
33+ const clone : Record < string , unknown > = { } ;
3234
33- for ( const key of Object . keys ( obj ) ) {
34- clone [ key ] = cloneWithoutCircularRefs ( ( obj as Record < string , unknown > ) [ key ] , seen ) ;
35- }
35+ for ( const key of Object . keys ( obj as Record < string , unknown > ) ) {
36+ clone [ key ] = cloneWithoutCircularRefs ( ( obj as Record < string , unknown > ) [ key ] , seen ) ;
37+ }
3638
37- return clone as T ;
39+ return clone as T ;
40+ } finally {
41+ seen . delete ( obj as object ) ;
42+ }
3843}
3944
4045/**
0 commit comments