@@ -3,10 +3,44 @@ import { addListener } from './listener.js';
33// import { profiler } from './profiler.js';
44import { getNode } from './svelte.js' ;
55
6+ const propClones = new Map ( ) ;
7+
8+ /**
9+ * @param {* } orig
10+ * @param {* } value
11+ * @returns {any }
12+ */
13+ function updateProp ( orig , value , seen = new Map ( ) ) {
14+ switch ( typeof value ) {
15+ case 'object' : {
16+ if ( value === window || value === null ) return null ;
17+ if ( Array . isArray ( value ) ) return value . map ( ( o , index ) => updateProp ( orig [ index ] , o , seen ) ) ;
18+ if ( seen . has ( value ) ) return seen . get ( value ) ;
19+
20+ /** @type {Record<string, any> } */
21+ const o = { } ;
22+ seen . set ( value , o ) ;
23+ for ( const [ key , v ] of Object . entries ( value ) ) {
24+ orig [ key ] = updateProp ( orig [ key ] , v , seen ) ;
25+ }
26+
27+ return orig ;
28+ }
29+ default :
30+ return value ;
31+ }
32+ }
33+
634// @ts -ignore - possibly find an alternative
735window . __svelte_devtools_inject_state = function ( id , key , value ) {
836 const { detail : component } = getNode ( id ) || { } ;
9- component && component . $inject_state ( { [ key ] : value } ) ;
37+ if ( component ) {
38+ const clone = updateProp ( propClones . get ( id ) [ key ] , value ) ;
39+
40+ component . $inject_state ( {
41+ [ key ] : clone ,
42+ } ) ;
43+ }
1044} ;
1145
1246// @ts -ignore - possibly find an alternative
@@ -131,19 +165,38 @@ function serialize(node) {
131165 switch ( node . type ) {
132166 case 'component' : {
133167 const { $$ : internal = { } } = node . detail ;
134- const ctx = clone ( node . detail . $capture_state ?. ( ) || { } ) ;
168+ const nodeState = node . detail . $capture_state ?. ( ) || { } ;
135169 const bindings = Object . values ( internal . bound || { } ) . map (
136170 /** @param {Function } f */ ( f ) => f . name ,
137171 ) ;
172+
173+ /** @type {Record<string, any> } */
174+ // clone original prop objects for update
175+ const _propClones = { } ;
138176 const props = Object . keys ( internal . props || { } ) . flatMap ( ( key ) => {
139- const value = ctx [ key ] ;
140- delete ctx [ key ] ; // deduplicate for ctx
177+ const prop = nodeState [ key ] ;
178+
179+ if ( prop ) {
180+ const prototypeDescriptors = Object . getOwnPropertyDescriptors (
181+ Object . getPrototypeOf ( nodeState [ key ] ) ,
182+ ) ;
183+ const protoClone = Object . create ( null , prototypeDescriptors ) ;
184+ const clone = Object . create ( protoClone , Object . getOwnPropertyDescriptors ( prop ) ) ;
185+ _propClones [ key ] = clone ;
186+ }
187+
188+ const value = clone ( prop ) ;
189+ delete nodeState [ key ] ; // deduplicate for ctx
141190 if ( value === undefined ) return [ ] ;
142191
143192 const bounded = bindings . some ( ( f ) => f . includes ( key ) ) ;
144193 return { key, value, bounded } ;
145194 } ) ;
146195
196+ propClones . set ( res . id , _propClones ) ;
197+
198+ const ctx = clone ( nodeState ) ;
199+
147200 res . detail = {
148201 attributes : props ,
149202 listeners : Object . entries ( internal . callbacks || { } ) . flatMap ( ( [ event , value ] ) =>
0 commit comments