r-state-tree 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,8 +17,6 @@ var CommonCfgTypes = /* @__PURE__ */ ((CommonCfgTypes2) => {
17
17
  })(CommonCfgTypes || {});
18
18
  var ModelCfgTypes = /* @__PURE__ */ ((ModelCfgTypes2) => {
19
19
  ModelCfgTypes2["state"] = "state";
20
- ModelCfgTypes2["stateShallow"] = "stateShallow";
21
- ModelCfgTypes2["stateSignal"] = "stateSignal";
22
20
  ModelCfgTypes2["id"] = "id";
23
21
  ModelCfgTypes2["modelRef"] = "modelRef";
24
22
  return ModelCfgTypes2;
@@ -28,9 +26,6 @@ var StoreCfgTypes = /* @__PURE__ */ ((StoreCfgTypes2) => {
28
26
  return StoreCfgTypes2;
29
27
  })(StoreCfgTypes || {});
30
28
  var ObservableCfgTypes = /* @__PURE__ */ ((ObservableCfgTypes2) => {
31
- ObservableCfgTypes2["observable"] = "observable";
32
- ObservableCfgTypes2["observableShallow"] = "observableShallow";
33
- ObservableCfgTypes2["observableSignal"] = "observableSignal";
34
29
  ObservableCfgTypes2["computed"] = "computed";
35
30
  return ObservableCfgTypes2;
36
31
  })(ObservableCfgTypes || {});
@@ -47,14 +42,6 @@ const stateType = {
47
42
  type: "state"
48
43
  /* state */
49
44
  };
50
- const stateShallowType = {
51
- type: "stateShallow"
52
- /* stateShallow */
53
- };
54
- const stateSignalType = {
55
- type: "stateSignal"
56
- /* stateSignal */
57
- };
58
45
  const modelRefType = Object.assign(
59
46
  function(childType2) {
60
47
  return { type: "modelRef", childType: childType2 };
@@ -79,32 +66,29 @@ function isPropertyKey(val) {
79
66
  return typeof val === "string" || typeof val === "number" || typeof val === "symbol";
80
67
  }
81
68
  function getPropertyType(key, obj) {
82
- const hasMetadata = obj.constructor[Symbol.metadata] !== void 0;
69
+ const ctor = obj.constructor;
70
+ const hasMetadata = ctor != null && ctor[Symbol.metadata] !== void 0;
83
71
  const descriptor = getPropertyDescriptor$1(obj, key);
84
72
  if (descriptor?.value && typeof descriptor.value === "function") {
85
73
  return "action";
86
74
  }
87
- const isGetter = descriptor && (typeof descriptor.get === "function" || typeof descriptor.set === "function");
75
+ const isAccessor = descriptor && (typeof descriptor.get === "function" || typeof descriptor.set === "function");
88
76
  if (!hasMetadata) {
89
- if (isGetter) {
77
+ if (descriptor?.get) {
90
78
  return "computed";
91
79
  }
80
+ if (isAccessor) {
81
+ return null;
82
+ }
92
83
  return "observable";
93
84
  }
94
85
  const metadata = obj.constructor[Symbol.metadata];
95
- if (metadata && metadata[key]) {
96
- const config = metadata[key];
86
+ const config = metadata?.[key];
87
+ if (config) {
97
88
  switch (config.type) {
98
89
  case ObservableCfgTypes.computed:
99
90
  return "computed";
100
- case ObservableCfgTypes.observableShallow:
101
- case ModelCfgTypes.stateShallow:
102
- return "observableShallow";
103
- case ObservableCfgTypes.observableSignal:
104
- case ModelCfgTypes.stateSignal:
105
- return "observableSignal";
106
91
  case ModelCfgTypes.state:
107
- case ObservableCfgTypes.observable:
108
92
  case ModelCfgTypes.id:
109
93
  case ModelCfgTypes.modelRef:
110
94
  case CommonCfgTypes.child:
@@ -112,7 +96,7 @@ function getPropertyType(key, obj) {
112
96
  return "observable";
113
97
  }
114
98
  }
115
- return null;
99
+ return isAccessor ? null : "observable";
116
100
  }
117
101
  function getPropertyDescriptor$1(obj, key) {
118
102
  let node = obj;
@@ -141,7 +125,7 @@ class Administration {
141
125
  atom;
142
126
  valuesMap;
143
127
  isObserved = false;
144
- forceObservedAtoms;
128
+ forceObservedAtom;
145
129
  constructor(source2) {
146
130
  this.atom = createObservedAtom();
147
131
  this.source = source2;
@@ -151,13 +135,9 @@ class Administration {
151
135
  );
152
136
  }
153
137
  flushChange() {
154
- if (this.forceObservedAtoms?.length) {
155
- signalsCore.batch(() => {
156
- for (let i = 0; i < this.forceObservedAtoms.length; i++) {
157
- this.forceObservedAtoms[i].reportChanged();
158
- }
159
- });
160
- this.forceObservedAtoms = void 0;
138
+ if (this.forceObservedAtom) {
139
+ this.forceObservedAtom.reportChanged();
140
+ this.forceObservedAtom = void 0;
161
141
  }
162
142
  }
163
143
  getNode() {
@@ -166,9 +146,7 @@ class Administration {
166
146
  reportChanged() {
167
147
  this.atom.reportChanged();
168
148
  }
169
- reportObserveDeep() {
170
- }
171
- reportObserved(deep = false) {
149
+ reportObserved() {
172
150
  const entry = circularRefSet == null;
173
151
  if (entry) {
174
152
  circularRefSet = /* @__PURE__ */ new WeakSet();
@@ -176,15 +154,10 @@ class Administration {
176
154
  return;
177
155
  }
178
156
  circularRefSet.add(this);
179
- const atom = createAtom();
180
- if (!this.forceObservedAtoms) {
181
- this.forceObservedAtoms = [];
182
- }
183
- this.forceObservedAtoms.push(atom);
184
- atom.reportObserved();
185
- if (deep) {
186
- this.reportObserveDeep();
157
+ if (!this.forceObservedAtom) {
158
+ this.forceObservedAtom = createAtom();
187
159
  }
160
+ this.forceObservedAtom.reportObserved();
188
161
  if (entry) {
189
162
  circularRefSet = null;
190
163
  }
@@ -247,6 +220,9 @@ class NodeMap {
247
220
  reportChanged(key, value) {
248
221
  return this.get(key)?.reportChanged(value);
249
222
  }
223
+ keys() {
224
+ return this.map?.keys() ?? [];
225
+ }
250
226
  }
251
227
  class AtomMap extends NodeMap {
252
228
  createNode() {
@@ -264,31 +240,34 @@ class ObjectAdministration extends Administration {
264
240
  valuesMap;
265
241
  computedMap;
266
242
  types;
243
+ isWriting = false;
267
244
  static proxyTraps = {
268
245
  has(target, name) {
269
246
  const adm = getAdministration(target);
270
- if (!(name in Object.prototype) && isPropertyKey(name))
247
+ if (isPropertyKey(name) && (!(name in Object.prototype) || Object.prototype.hasOwnProperty.call(adm.source, name)))
271
248
  return adm.has(name);
272
249
  return Reflect.has(adm.source, name);
273
250
  },
274
251
  get(target, name) {
275
252
  const adm = getAdministration(target);
276
- if (!(name in Object.prototype) && isPropertyKey(name) && (typeof adm.source !== "function" || name !== "prototype")) {
277
- return adm.read(name);
253
+ if (isPropertyKey(name) && (!(name in Object.prototype) || Object.prototype.hasOwnProperty.call(adm.source, name)) && (typeof adm.source !== "function" || name !== "prototype")) {
254
+ return adm.read(name, arguments[2]);
278
255
  }
279
- return Reflect.get(adm.source, name, adm.proxy);
256
+ return Reflect.get(adm.source, name, arguments[2]);
280
257
  },
281
258
  set(target, name, value) {
282
259
  if (!isPropertyKey(name)) return false;
283
260
  const adm = getAdministration(target);
284
- adm.write(name, value);
285
- return true;
261
+ const receiver = arguments[3];
262
+ if (receiver === adm.proxy) {
263
+ return adm.write(name, value);
264
+ }
265
+ return Reflect.set(adm.source, name, value, receiver);
286
266
  },
287
267
  deleteProperty(target, name) {
288
268
  if (!isPropertyKey(name)) return false;
289
269
  const adm = getAdministration(target);
290
- adm.remove(name);
291
- return true;
270
+ return adm.remove(name);
292
271
  },
293
272
  ownKeys(target) {
294
273
  const adm = getAdministration(target);
@@ -297,21 +276,47 @@ class ObjectAdministration extends Administration {
297
276
  adm.atom.reportObserved();
298
277
  });
299
278
  return Reflect.ownKeys(adm.source);
279
+ },
280
+ defineProperty(target, name, descriptor) {
281
+ const adm = getAdministration(target);
282
+ if (adm.isWriting) {
283
+ return Reflect.defineProperty(adm.source, name, descriptor);
284
+ }
285
+ const result = Reflect.defineProperty(adm.source, name, descriptor);
286
+ if (result) {
287
+ signalsCore.batch(() => {
288
+ adm.types.delete(name);
289
+ adm.flushChange();
290
+ adm.keysAtom.reportChanged();
291
+ adm.hasMap.reportChanged(name);
292
+ if ("value" in descriptor) {
293
+ if (isObservable(descriptor.value)) {
294
+ adm.explicitObservables.add(name);
295
+ } else {
296
+ adm.explicitObservables.delete(name);
297
+ }
298
+ adm.valuesMap.reportChanged(name, descriptor.value);
299
+ } else {
300
+ adm.valuesMap.reportChanged(name, void 0);
301
+ }
302
+ });
303
+ }
304
+ return result;
300
305
  }
301
306
  };
302
307
  constructor(source2 = {}) {
303
308
  super(source2);
304
309
  this.keysAtom = createAtom();
305
310
  this.hasMap = new AtomMap(this.atom);
306
- this.valuesMap = new SignalMap();
311
+ this.valuesMap = new SignalMap(this.atom);
307
312
  this.types = /* @__PURE__ */ new Map();
308
313
  }
309
314
  get(key) {
310
315
  return Reflect.get(this.source, key, this.proxy);
311
316
  }
312
317
  set(key, value) {
313
- signalsCore.batch(() => {
314
- Reflect.set(this.source, key, value, this.proxy);
318
+ return signalsCore.batch(() => {
319
+ return Reflect.set(this.source, key, value, this.proxy);
315
320
  });
316
321
  }
317
322
  getComputed(key) {
@@ -339,17 +344,6 @@ class ObjectAdministration extends Administration {
339
344
  }
340
345
  return type;
341
346
  }
342
- reportObserveDeep() {
343
- Object.getOwnPropertyNames(this.source).forEach((name) => {
344
- const type = this.getType(name);
345
- if (type === "observable") {
346
- const value = this.source[name];
347
- if (value && typeof value === "object") {
348
- getAdministration(getObservable(value))?.reportObserved();
349
- }
350
- }
351
- });
352
- }
353
347
  reportChanged() {
354
348
  this.types.clear();
355
349
  super.reportChanged();
@@ -364,14 +358,13 @@ class ObjectAdministration extends Administration {
364
358
  }
365
359
  return resolveNode(this.valuesMap.getOrCreate(key, this.source[key]));
366
360
  }
367
- read(key) {
361
+ read(key, receiver = this.proxy) {
368
362
  const type = this.getType(key);
369
363
  if (type === null) {
370
- return this.get(key);
364
+ return Reflect.get(this.source, key, receiver);
371
365
  }
372
366
  switch (type) {
373
367
  case "observable":
374
- case "observableShallow":
375
368
  case "action": {
376
369
  if (key in this.source) {
377
370
  this.valuesMap.reportObserved(key, this.source[key]);
@@ -381,48 +374,66 @@ class ObjectAdministration extends Administration {
381
374
  this.hasMap.reportObserved(key);
382
375
  }
383
376
  if (type === "observable") {
384
- return getObservable(this.get(key));
385
- }
386
- if (type === "observableShallow") {
387
- return getShallowObservable(this.get(key));
377
+ const value = Reflect.get(this.source, key, receiver);
378
+ const shouldWrap = this.explicitObservables.has(key) || isObservable(value);
379
+ if (shouldWrap && value && typeof value === "object" && !Object.isFrozen(value)) {
380
+ const desc = getPropertyDescriptor$1(this.source, key);
381
+ if (desc && !desc.configurable && !desc.writable) {
382
+ return value;
383
+ }
384
+ const existingAdm = getAdministration(value);
385
+ if (existingAdm) {
386
+ return existingAdm.proxy;
387
+ }
388
+ }
389
+ return value;
388
390
  }
389
- return getAction(this.get(key));
391
+ return getAction(
392
+ Reflect.get(this.source, key, receiver)
393
+ );
390
394
  }
391
- case "observableSignal": {
392
- if (key in this.source) {
393
- this.valuesMap.reportObserved(key, this.source[key]);
395
+ case "computed": {
396
+ if (receiver === this.proxy) {
397
+ return this.callComputed(key);
394
398
  }
395
399
  this.atom.reportObserved();
396
- if (this.atom.observing) {
397
- this.hasMap.reportObserved(key);
398
- }
399
- return this.get(key);
400
- }
401
- case "computed": {
402
- return this.callComputed(key);
400
+ return Reflect.get(this.source, key, receiver);
403
401
  }
404
402
  default:
405
403
  throw new Error(`unknown type passed to configure`);
406
404
  }
407
405
  }
406
+ explicitObservables = /* @__PURE__ */ new Set();
408
407
  write(key, newValue) {
409
408
  const type = this.getType(key);
410
409
  if (type === null) {
411
- this.set(key, newValue);
412
- return;
410
+ return this.set(key, newValue);
413
411
  }
414
412
  if (type === "computed") {
415
- signalsCore.batch(() => this.set(key, newValue));
416
- return;
413
+ return signalsCore.batch(() => this.set(key, newValue));
417
414
  }
418
415
  const had = key in this.source;
419
416
  const oldValue = this.get(key);
420
417
  const targetValue = getSource(newValue);
418
+ const oldExplicit = this.explicitObservables.has(key);
419
+ const newExplicit = isObservable(newValue);
420
+ if (newExplicit) {
421
+ this.explicitObservables.add(key);
422
+ } else {
423
+ this.explicitObservables.delete(key);
424
+ }
421
425
  if (type === "action" && typeof newValue !== "function" || type === "observable" && typeof newValue === "function") {
422
426
  this.types.delete(key);
423
427
  }
424
- if (!had || (isObservable(oldValue) ? oldValue !== newValue : oldValue !== targetValue)) {
425
- this.set(key, targetValue);
428
+ const changed = !had || !isObservable(oldValue) && oldExplicit !== newExplicit || (isObservable(oldValue) ? oldValue !== newValue : oldValue !== targetValue);
429
+ if (changed) {
430
+ this.isWriting = true;
431
+ try {
432
+ const result = this.set(key, targetValue);
433
+ if (!result) return false;
434
+ } finally {
435
+ this.isWriting = false;
436
+ }
426
437
  signalsCore.batch(() => {
427
438
  this.flushChange();
428
439
  if (!had) {
@@ -431,7 +442,9 @@ class ObjectAdministration extends Administration {
431
442
  }
432
443
  this.valuesMap.reportChanged(key, newValue);
433
444
  });
445
+ return true;
434
446
  }
447
+ return true;
435
448
  }
436
449
  has(key) {
437
450
  this.atom.reportObserved();
@@ -441,33 +454,21 @@ class ObjectAdministration extends Administration {
441
454
  return key in this.source;
442
455
  }
443
456
  remove(key) {
444
- if (!(key in this.source)) return;
445
- delete this.source[key];
446
- signalsCore.batch(() => {
447
- this.flushChange();
448
- this.valuesMap.reportChanged(key, void 0);
449
- this.keysAtom.reportChanged();
450
- this.hasMap.reportChanged(key);
451
- this.valuesMap.delete(key);
452
- });
457
+ if (!(key in this.source)) return true;
458
+ const result = Reflect.deleteProperty(this.source, key);
459
+ if (result) {
460
+ signalsCore.batch(() => {
461
+ this.flushChange();
462
+ this.valuesMap.reportChanged(key, void 0);
463
+ this.keysAtom.reportChanged();
464
+ this.hasMap.reportChanged(key);
465
+ this.valuesMap.delete(key);
466
+ });
467
+ }
468
+ return result;
453
469
  }
454
470
  }
455
471
  class PreactObjectAdministration extends ObjectAdministration {
456
- static proxyTraps = Object.assign(
457
- {},
458
- ObjectAdministration.proxyTraps,
459
- {
460
- get(target, prop, proxy) {
461
- if (!(prop in target) && (typeof prop === "string" || typeof prop === "number") && String(prop)[0] === "$") {
462
- return getSignal(proxy, prop.substring(1));
463
- }
464
- return ObjectAdministration.proxyTraps.get?.apply(
465
- null,
466
- arguments
467
- );
468
- }
469
- }
470
- );
471
472
  }
472
473
  function createObservedAtom() {
473
474
  let value = 0;
@@ -605,31 +606,12 @@ function createComputed(fn, context = null) {
605
606
  }
606
607
  };
607
608
  }
608
- function observableImpl(value, context) {
609
- if (context && typeof context === "object" && "kind" in context) {
610
- context.metadata[context.name] = { type: "observable" };
611
- return value;
612
- }
613
- return getObservable(value);
614
- }
615
- function shallowDecorator(value, context) {
616
- if (context && typeof context === "object" && "kind" in context) {
617
- context.metadata[context.name] = { type: "observableShallow" };
618
- return value;
619
- }
620
- throw new Error("observable.shallow can only be used as a decorator");
609
+ function observable(obj) {
610
+ return getObservable(obj);
621
611
  }
622
- function signalDecorator(value, context) {
623
- if (context && typeof context === "object" && "kind" in context) {
624
- context.metadata[context.name] = { type: "observableSignal" };
625
- return value;
626
- }
627
- throw new Error("observable.signal can only be used as a decorator");
612
+ function signal(value) {
613
+ return signalsCore.signal(value);
628
614
  }
629
- const observable = Object.assign(observableImpl, {
630
- shallow: shallowDecorator,
631
- signal: signalDecorator
632
- });
633
615
  function computed(value, context) {
634
616
  if (context && typeof context === "object" && "kind" in context) {
635
617
  context.metadata[context.name] = { type: "computed" };
@@ -640,19 +622,14 @@ function computed(value, context) {
640
622
  function source(obj) {
641
623
  return getSource(obj);
642
624
  }
643
- class Observable {
644
- constructor() {
645
- return getObservableClassInstance(this);
646
- }
647
- }
648
625
  function reportChanged(obj) {
649
626
  const adm = getAdministration(obj);
650
627
  adm.reportChanged();
651
628
  return obj;
652
629
  }
653
- function reportObserved(obj, opts) {
630
+ function reportObserved(obj) {
654
631
  const adm = getAdministration(obj);
655
- adm.reportObserved(opts?.deep);
632
+ adm.reportObserved();
656
633
  return obj;
657
634
  }
658
635
  const signalMap = /* @__PURE__ */ new WeakMap();
@@ -688,17 +665,36 @@ class CollectionAdministration extends Administration {
688
665
  hasMap;
689
666
  valuesMap;
690
667
  keysAtom;
668
+ isWeak;
669
+ strongTracking = null;
670
+ weakTracking = null;
691
671
  static proxyTraps = {
692
672
  get(target, name) {
693
673
  const adm = getAdministration(target);
694
- if (name === "size" && "size" in adm.source) {
674
+ if (name === "size" && !adm.isWeak && "size" in adm.source) {
695
675
  return adm.size;
696
676
  }
697
677
  const val = adm.source[name];
698
678
  const collectionMethods = adm.constructor.methods;
699
- if (collectionMethods.hasOwnProperty(name) && typeof val === "function") {
679
+ if (collectionMethods.hasOwnProperty(name)) {
680
+ if (adm.isWeak && !isValidWeakMethod(name)) {
681
+ return val;
682
+ }
700
683
  return collectionMethods[name];
701
684
  }
685
+ if (typeof val === "function") {
686
+ return function() {
687
+ if (process.env.NODE_ENV !== "production") {
688
+ console.warn(
689
+ `r-state-tree: Calling uninstrumented collection method "${String(
690
+ name
691
+ )}". Reactivity is not guaranteed for this call.`
692
+ );
693
+ }
694
+ const result = val.apply(adm.source, arguments);
695
+ return result === adm.source ? adm.proxy : result;
696
+ };
697
+ }
702
698
  return val;
703
699
  }
704
700
  };
@@ -713,17 +709,71 @@ class CollectionAdministration extends Administration {
713
709
  entries: createMethod$1("entries"),
714
710
  keys: createMethod$1("keys"),
715
711
  values: createMethod$1("values"),
716
- [Symbol.iterator]: createMethod$1(Symbol.iterator)
712
+ [Symbol.iterator]: createMethod$1(Symbol.iterator),
713
+ // New ES methods
714
+ union: createGenericMethod("union"),
715
+ intersection: createGenericMethod("intersection"),
716
+ difference: createGenericMethod("difference"),
717
+ symmetricDifference: createGenericMethod("symmetricDifference"),
718
+ isSubsetOf: createGenericMethod("isSubsetOf"),
719
+ isSupersetOf: createGenericMethod("isSupersetOf"),
720
+ isDisjointFrom: createGenericMethod("isDisjointFrom")
717
721
  };
718
722
  constructor(source2) {
719
723
  super(source2);
720
724
  this.hasMap = new AtomMap(this.atom);
721
- this.valuesMap = new SignalMap();
725
+ this.valuesMap = new SignalMap(this.atom);
722
726
  this.keysAtom = createAtom();
723
727
  this.isMap = typeof source2.set === "function" && typeof source2.get === "function";
728
+ this.isWeak = source2 instanceof WeakMap || source2 instanceof WeakSet;
729
+ if (this.isWeak) {
730
+ this.weakTracking = /* @__PURE__ */ new WeakSet();
731
+ } else {
732
+ this.strongTracking = /* @__PURE__ */ new Set();
733
+ }
734
+ }
735
+ trackExplicitObservable(key) {
736
+ if (this.isWeak) {
737
+ if (isNonPrimitive(key)) {
738
+ this.weakTracking.add(key);
739
+ }
740
+ } else {
741
+ this.strongTracking.add(key);
742
+ }
743
+ }
744
+ untrackExplicitObservable(key) {
745
+ if (this.isWeak) {
746
+ if (isNonPrimitive(key)) {
747
+ this.weakTracking.delete(key);
748
+ }
749
+ } else {
750
+ this.strongTracking.delete(key);
751
+ }
752
+ }
753
+ hasExplicitObservable(key) {
754
+ if (this.isWeak) {
755
+ return isNonPrimitive(key) && this.weakTracking.has(key);
756
+ }
757
+ return this.strongTracking.has(key);
758
+ }
759
+ getProxyVariant(key) {
760
+ if (!isNonPrimitive(key)) return void 0;
761
+ const adm = getAdministration(key);
762
+ if (adm && adm.proxy && adm.proxy !== key) {
763
+ return adm.proxy;
764
+ }
765
+ return void 0;
766
+ }
767
+ getExistingKey(key) {
768
+ const target = getSource(key);
769
+ if (this.source.has(target)) return target;
770
+ if (this.source.has(key)) return key;
771
+ const proxy = this.getProxyVariant(key);
772
+ if (proxy !== void 0 && this.source.has(proxy)) return proxy;
773
+ return void 0;
724
774
  }
725
775
  hasEntry(key) {
726
- return this.source.has(getSource(key)) || this.source.has(key);
776
+ return this.getExistingKey(key) !== void 0;
727
777
  }
728
778
  onCollectionChange(key) {
729
779
  signalsCore.batch(() => {
@@ -732,13 +782,6 @@ class CollectionAdministration extends Administration {
732
782
  this.flushChange();
733
783
  });
734
784
  }
735
- reportObserveDeep() {
736
- this.source.forEach?.((value) => {
737
- if (value && typeof value === "object") {
738
- getAdministration(getObservable(value))?.reportObserved();
739
- }
740
- });
741
- }
742
785
  getNode(key) {
743
786
  if (key == null) {
744
787
  return resolveNode(this.atom);
@@ -759,13 +802,12 @@ class CollectionAdministration extends Administration {
759
802
  this.keysAtom.reportObserved();
760
803
  this.atom.reportObserved();
761
804
  this.source.forEach((value, key) => {
762
- const observed = getObservable(this.isMap ? key : value);
763
- callbackFn.call(
764
- thisArg,
765
- this.isMap ? this.get(key) : observed,
766
- observed,
767
- this.proxy
768
- );
805
+ if (this.isMap) {
806
+ callbackFn.call(thisArg, this.get(key), key, this.proxy);
807
+ return;
808
+ }
809
+ const wrapped = this.wrapSetValue(key);
810
+ callbackFn.call(thisArg, wrapped, wrapped, this.proxy);
769
811
  });
770
812
  }
771
813
  get size() {
@@ -774,43 +816,68 @@ class CollectionAdministration extends Administration {
774
816
  return this.source.size;
775
817
  }
776
818
  add(value) {
819
+ const target = getSource(value);
820
+ if (isObservable(value)) {
821
+ this.trackExplicitObservable(target);
822
+ } else {
823
+ this.untrackExplicitObservable(target);
824
+ this.untrackExplicitObservable(value);
825
+ }
777
826
  if (!this.hasEntry(value)) {
778
- const target = getSource(value);
779
827
  this.source.add(target);
780
828
  this.onCollectionChange(target);
781
829
  }
782
830
  return this;
783
831
  }
784
832
  delete(value) {
785
- if (this.hasEntry(value)) {
786
- const target = getSource(value);
787
- this.source.delete(target);
788
- this.source.delete(value);
789
- this.onCollectionChange(target);
790
- return true;
833
+ const existingKey = this.getExistingKey(value);
834
+ if (existingKey === void 0) return false;
835
+ const target = getSource(value);
836
+ this.untrackExplicitObservable(target);
837
+ this.untrackExplicitObservable(value);
838
+ const proxy = this.getProxyVariant(value);
839
+ if (proxy !== void 0) this.untrackExplicitObservable(proxy);
840
+ this.source.delete(existingKey);
841
+ this.source.delete(target);
842
+ this.source.delete(value);
843
+ if (proxy !== void 0) this.source.delete(proxy);
844
+ this.onCollectionChange(target);
845
+ return true;
846
+ }
847
+ wrapSetValue(value) {
848
+ if (this.hasExplicitObservable(value)) {
849
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
850
+ const existingAdm = getAdministration(value);
851
+ if (existingAdm) return existingAdm.proxy;
852
+ }
791
853
  }
792
- return false;
854
+ return value;
793
855
  }
794
856
  has(value) {
795
857
  this.atom.reportObserved();
796
- if (this.atom.observing || true) {
797
- const target = getSource(value);
798
- this.hasMap.reportObserved(target);
799
- }
858
+ const target = getSource(value);
859
+ this.hasMap.reportObserved(target);
800
860
  return this.hasEntry(value);
801
861
  }
802
862
  entries() {
863
+ this.keysAtom.reportObserved();
864
+ this.atom.reportObserved();
803
865
  const self = this;
804
- const keys = this.keys();
866
+ const iterator = this.source.entries();
805
867
  return {
806
868
  [Symbol.iterator]: function() {
807
869
  return this;
808
870
  },
809
871
  next() {
810
- const { done, value } = keys.next();
872
+ const { done, value } = iterator.next();
873
+ if (done) return { done: true, value: void 0 };
874
+ const [key, val] = value;
811
875
  return {
812
- done,
813
- value: done ? void 0 : [value, self.isMap ? self.get(value) : value]
876
+ done: false,
877
+ value: [
878
+ self.isMap ? key : self.wrapSetValue(key),
879
+ self.isMap ? self.get(key) : self.wrapSetValue(val)
880
+ ]
814
881
  };
815
882
  }
816
883
  };
@@ -818,19 +885,19 @@ class CollectionAdministration extends Administration {
818
885
  keys() {
819
886
  this.keysAtom.reportObserved();
820
887
  this.atom.reportObserved();
821
- let nextIndex = 0;
822
- const observableKeys = Array.from(this.source.keys()).map(
823
- (o) => getObservable(o)
824
- );
888
+ const self = this;
889
+ const iterator = this.source.keys();
825
890
  return {
826
891
  [Symbol.iterator]: function() {
827
892
  return this;
828
893
  },
829
894
  next() {
830
- return nextIndex < observableKeys.length ? {
831
- value: observableKeys[nextIndex++],
832
- done: false
833
- } : { done: true, value: void 0 };
895
+ const { done, value } = iterator.next();
896
+ if (done) return { done: true, value: void 0 };
897
+ return {
898
+ done: false,
899
+ value: self.isMap ? value : self.wrapSetValue(value)
900
+ };
834
901
  }
835
902
  };
836
903
  }
@@ -838,31 +905,54 @@ class CollectionAdministration extends Administration {
838
905
  const targetKey = getSource(key);
839
906
  const sourceMap = this.source;
840
907
  const has = this.has(key);
841
- const value = sourceMap.get(targetKey) ?? sourceMap.get(key);
842
- if (has) {
908
+ if (!has) return void 0;
909
+ const existingKey = this.getExistingKey(key);
910
+ const value = sourceMap.get(existingKey);
911
+ this.valuesMap.reportObserved(targetKey, value);
912
+ if (key !== targetKey) {
843
913
  this.valuesMap.reportObserved(key, value);
844
- if (isShallowObservable(this.proxy)) {
845
- return value;
914
+ }
915
+ const proxyKey = this.getProxyVariant(key);
916
+ if (proxyKey !== void 0 && proxyKey !== key && proxyKey !== targetKey) {
917
+ this.valuesMap.reportObserved(proxyKey, value);
918
+ }
919
+ if (this.hasExplicitObservable(targetKey) || this.hasExplicitObservable(key) || proxyKey !== void 0 && this.hasExplicitObservable(proxyKey)) {
920
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
921
+ const existingAdm = getAdministration(value);
922
+ if (existingAdm) return existingAdm.proxy;
846
923
  }
847
- return getObservable(value);
848
924
  }
849
- return void 0;
925
+ return value;
850
926
  }
851
927
  set(key, value) {
852
928
  const targetKey = getSource(key);
853
929
  const targetValue = getSource(value);
854
930
  const sourceMap = this.source;
855
- const hasKey = this.hasEntry(key);
856
- const oldValue = sourceMap.get(targetKey) ?? sourceMap.get(key);
857
- if (!hasKey || isObservable(oldValue) ? oldValue !== value : oldValue !== targetValue) {
931
+ if (isObservable(value)) {
932
+ this.trackExplicitObservable(targetKey);
933
+ } else {
934
+ this.untrackExplicitObservable(targetKey);
935
+ this.untrackExplicitObservable(key);
936
+ }
937
+ const existingKey = this.getExistingKey(key);
938
+ const hasKey = existingKey !== void 0;
939
+ const oldValue = hasKey ? sourceMap.get(existingKey) : void 0;
940
+ if (!hasKey || (isObservable(oldValue) ? oldValue !== value : oldValue !== targetValue)) {
858
941
  signalsCore.batch(() => {
859
942
  this.flushChange();
860
- if (sourceMap.has(key)) {
861
- sourceMap.set(key, targetValue);
943
+ if (existingKey !== void 0) {
944
+ sourceMap.set(existingKey, targetValue);
862
945
  } else {
863
946
  sourceMap.set(targetKey, targetValue);
864
947
  }
865
- this.valuesMap.reportChanged(key, value);
948
+ this.valuesMap.reportChanged(targetKey, value);
949
+ if (key !== targetKey) {
950
+ this.valuesMap.reportChanged(key, value);
951
+ }
952
+ const proxyKey = this.getProxyVariant(key);
953
+ if (proxyKey !== void 0 && proxyKey !== key && proxyKey !== targetKey) {
954
+ this.valuesMap.reportChanged(proxyKey, value);
955
+ }
866
956
  if (!hasKey) {
867
957
  this.hasMap.reportChanged(targetKey);
868
958
  this.keysAtom.reportChanged();
@@ -872,20 +962,22 @@ class CollectionAdministration extends Administration {
872
962
  return this;
873
963
  }
874
964
  values() {
875
- const self = this;
876
- const keys = this.keys();
965
+ this.keysAtom.reportObserved();
966
+ this.atom.reportObserved();
877
967
  if (!this.isMap) {
878
- return keys;
968
+ return this.keys();
879
969
  }
970
+ const entries = this.entries();
880
971
  return {
881
972
  [Symbol.iterator]: function() {
882
973
  return this;
883
974
  },
884
975
  next() {
885
- const { done, value } = keys.next();
976
+ const { done, value } = entries.next();
977
+ if (done) return { done: true, value: void 0 };
886
978
  return {
887
- done,
888
- value: done ? void 0 : self.get(value)
979
+ done: false,
980
+ value: value[1]
889
981
  };
890
982
  }
891
983
  };
@@ -895,53 +987,177 @@ class CollectionAdministration extends Administration {
895
987
  }
896
988
  [Symbol.toStringTag] = "Set";
897
989
  }
990
+ function isValidWeakMethod(name) {
991
+ const n = name;
992
+ return n === "get" || n === "set" || n === "add" || n === "has" || n === "delete";
993
+ }
994
+ function createGenericMethod(name) {
995
+ return function() {
996
+ const adm = getAdministration(this);
997
+ const method = adm.source[name];
998
+ if (typeof method !== "function") return method;
999
+ if (["union", "intersection", "difference", "symmetricDifference"].includes(
1000
+ name
1001
+ )) {
1002
+ const other = arguments[0];
1003
+ const result2 = /* @__PURE__ */ new Set();
1004
+ if (name === "union") {
1005
+ for (const item of this) result2.add(item);
1006
+ for (const item of other) result2.add(item);
1007
+ } else if (name === "intersection") {
1008
+ for (const item of this) {
1009
+ if (other.has(item)) result2.add(item);
1010
+ }
1011
+ } else if (name === "difference") {
1012
+ for (const item of this) {
1013
+ if (!other.has(item)) result2.add(item);
1014
+ }
1015
+ } else if (name === "symmetricDifference") {
1016
+ for (const item of this) {
1017
+ if (!other.has(item)) result2.add(item);
1018
+ }
1019
+ for (const item of other) {
1020
+ if (!this.has(item)) result2.add(item);
1021
+ }
1022
+ }
1023
+ return result2;
1024
+ }
1025
+ adm.keysAtom.reportObserved();
1026
+ adm.atom.reportObserved();
1027
+ const args = new Array(arguments.length);
1028
+ for (let i = 0; i < arguments.length; i++) {
1029
+ const arg = arguments[i];
1030
+ args[i] = getSource(arg);
1031
+ if (isObservable(arg)) {
1032
+ reportObserved(arg);
1033
+ }
1034
+ }
1035
+ const result = method.apply(adm.source, args);
1036
+ if (result === adm.source) return adm.proxy;
1037
+ return result;
1038
+ };
1039
+ }
898
1040
  function createMethod$1(method) {
899
1041
  return function() {
900
1042
  const adm = getAdministration(this);
901
- return adm[method].apply(adm, arguments);
1043
+ const result = adm[method].apply(adm, arguments);
1044
+ if (method === "add" || method === "set") {
1045
+ return this;
1046
+ }
1047
+ return result;
902
1048
  };
903
1049
  }
1050
+ function isArrayIndexKey(key) {
1051
+ if (typeof key === "symbol") return false;
1052
+ const keyStr = String(key);
1053
+ const num = Number(keyStr);
1054
+ return Number.isInteger(num) && num >= 0 && num < 4294967295 && // 2^32 - 1
1055
+ String(num) === keyStr;
1056
+ }
904
1057
  class ArrayAdministration extends Administration {
905
1058
  valuesMap;
906
1059
  keysAtom;
1060
+ explicitObservables = /* @__PURE__ */ new Set();
1061
+ syncExplicitObservablesFromSource() {
1062
+ for (let i = 0; i < this.source.length; i++) {
1063
+ const value = this.source[i];
1064
+ if (isObservable(value)) {
1065
+ this.explicitObservables.add(i);
1066
+ }
1067
+ }
1068
+ }
907
1069
  static proxyTraps = {
908
- get(target, name) {
1070
+ get(target, name, receiver) {
909
1071
  const adm = getAdministration(target);
910
1072
  if (name === "length") {
911
1073
  return adm.getArrayLength();
912
1074
  }
913
- if (typeof name === "number") {
914
- return adm.get(name);
915
- }
916
- if (typeof name === "string" && String(parseInt(name)) === name) {
917
- return adm.get(parseInt(name));
1075
+ if (isArrayIndexKey(name)) {
1076
+ return adm.get(Number(name));
918
1077
  }
919
1078
  const arrayMethods = adm.constructor.methods;
920
1079
  if (arrayMethods.hasOwnProperty(name)) {
921
1080
  return arrayMethods[name];
922
1081
  }
923
- return adm.source[name];
1082
+ return Reflect.get(adm.source, name, receiver);
924
1083
  },
925
1084
  set(target, name, value) {
926
1085
  const adm = getAdministration(target);
927
1086
  if (name === "length") {
928
- adm.setArrayLength(value);
929
- } else if (typeof name === "number") {
930
- adm.set(name, value);
931
- } else if (typeof name === "string" && String(parseInt(name)) === name) {
932
- adm.set(parseInt(name), value);
1087
+ return adm.setArrayLength(value);
1088
+ } else if (isArrayIndexKey(name)) {
1089
+ return adm.set(Number(name), value);
933
1090
  } else {
934
- adm.source[name] = value;
1091
+ return Reflect.set(adm.source, name, value, arguments[3]);
935
1092
  }
936
- return true;
1093
+ },
1094
+ defineProperty(target, name, descriptor) {
1095
+ const adm = getAdministration(target);
1096
+ const result = Reflect.defineProperty(adm.source, name, descriptor);
1097
+ if (result) {
1098
+ signalsCore.batch(() => {
1099
+ adm.flushChange();
1100
+ if (name === "length") {
1101
+ adm.keysAtom.reportChanged();
1102
+ adm.atom.reportChanged();
1103
+ } else if (isArrayIndexKey(name)) {
1104
+ const index = Number(name);
1105
+ adm.keysAtom.reportChanged();
1106
+ adm.onArrayChanged(false, index, 1);
1107
+ } else {
1108
+ adm.atom.reportChanged();
1109
+ }
1110
+ });
1111
+ }
1112
+ return result;
1113
+ },
1114
+ deleteProperty(target, name) {
1115
+ const adm = getAdministration(target);
1116
+ const isIndex = isArrayIndexKey(name);
1117
+ const had = name in adm.source;
1118
+ const result = Reflect.deleteProperty(adm.source, name);
1119
+ if (result && had && isIndex) {
1120
+ const index = Number(name);
1121
+ adm.onArrayChanged(true, index, 1);
1122
+ adm.explicitObservables.delete(index);
1123
+ }
1124
+ return result;
1125
+ },
1126
+ ownKeys(target) {
1127
+ const adm = getAdministration(target);
1128
+ signalsCore.batch(() => {
1129
+ adm.keysAtom.reportObserved();
1130
+ adm.atom.reportObserved();
1131
+ });
1132
+ return Reflect.ownKeys(adm.source);
1133
+ },
1134
+ has(target, name) {
1135
+ const adm = getAdministration(target);
1136
+ if (isArrayIndexKey(name)) {
1137
+ const index = Number(name);
1138
+ adm.atom.reportObserved();
1139
+ adm.valuesMap.reportObserved(index, adm.source[index]);
1140
+ return index in adm.source;
1141
+ }
1142
+ return Reflect.has(adm.source, name);
937
1143
  }
938
1144
  };
939
1145
  static methods = {
940
1146
  fill(value, start, end) {
941
1147
  const adm = getAdministration(this);
942
- const oldLength = adm.source.length;
943
- adm.source.fill(value, start, end);
944
- adm.onArrayChanged(oldLength !== adm.source.length, start, end);
1148
+ const shouldTrack = isObservable(value);
1149
+ const targetValue = getSource(value);
1150
+ adm.source.fill(targetValue, start, end);
1151
+ const length = adm.source.length;
1152
+ const from = start == null ? 0 : start < 0 ? Math.max(length + start, 0) : start;
1153
+ const to = end == null ? length : end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
1154
+ for (let i = from; i < to; i++) {
1155
+ if (shouldTrack) adm.explicitObservables.add(i);
1156
+ else adm.explicitObservables.delete(i);
1157
+ }
1158
+ if (from < to) {
1159
+ adm.onArrayChanged(false, from, to - from);
1160
+ }
945
1161
  return this;
946
1162
  },
947
1163
  splice(index, deleteCount, ...newItems) {
@@ -977,16 +1193,43 @@ class ArrayAdministration extends Administration {
977
1193
  },
978
1194
  reverse() {
979
1195
  const adm = getAdministration(this);
1196
+ adm.syncExplicitObservablesFromSource();
1197
+ const flags = new Array(adm.source.length);
1198
+ for (let i = 0; i < flags.length; i++) {
1199
+ flags[i] = adm.explicitObservables.has(i);
1200
+ }
980
1201
  adm.source.reverse();
1202
+ flags.reverse();
1203
+ adm.explicitObservables.clear();
1204
+ for (let i = 0; i < flags.length; i++) {
1205
+ if (flags[i]) adm.explicitObservables.add(i);
1206
+ }
981
1207
  adm.onArrayChanged(false, 0, adm.source.length);
982
1208
  return this;
983
1209
  },
984
1210
  sort(compareFn) {
985
1211
  const adm = getAdministration(this);
986
- adm.onArrayChanged();
987
- adm.source.sort(
988
- compareFn && ((a, b) => compareFn(getObservable(a), getObservable(b)))
989
- );
1212
+ adm.syncExplicitObservablesFromSource();
1213
+ const pairs = new Array(adm.source.length);
1214
+ for (let i = 0; i < adm.source.length; i++) {
1215
+ pairs[i] = {
1216
+ value: this[i],
1217
+ stored: adm.source[i],
1218
+ observed: adm.explicitObservables.has(i)
1219
+ };
1220
+ }
1221
+ const comparator = compareFn ?? ((a, b) => {
1222
+ const as = String(a);
1223
+ const bs = String(b);
1224
+ return as < bs ? -1 : as > bs ? 1 : 0;
1225
+ });
1226
+ pairs.sort((a, b) => comparator(a.value, b.value));
1227
+ adm.explicitObservables.clear();
1228
+ for (let i = 0; i < pairs.length; i++) {
1229
+ adm.source[i] = pairs[i].stored;
1230
+ if (pairs[i].observed) adm.explicitObservables.add(i);
1231
+ }
1232
+ adm.onArrayChanged(false, 0, adm.source.length);
990
1233
  return this;
991
1234
  },
992
1235
  join: createStringMethod("join"),
@@ -998,7 +1241,22 @@ class ArrayAdministration extends Administration {
998
1241
  slice: createCopyMethod("slice"),
999
1242
  concat: createCopyMethod("concat"),
1000
1243
  flat: createCopyMethod("flat"),
1001
- copyWithin: createCopyMethod("copyWithin"),
1244
+ copyWithin(target, start, end) {
1245
+ const adm = getAdministration(this);
1246
+ adm.syncExplicitObservablesFromSource();
1247
+ const flags = new Array(adm.source.length);
1248
+ for (let i = 0; i < flags.length; i++) {
1249
+ flags[i] = adm.explicitObservables.has(i);
1250
+ }
1251
+ adm.source.copyWithin(target, start, end);
1252
+ flags.copyWithin(target, start, end);
1253
+ adm.explicitObservables.clear();
1254
+ for (let i = 0; i < flags.length; i++) {
1255
+ if (flags[i]) adm.explicitObservables.add(i);
1256
+ }
1257
+ adm.onArrayChanged(false, 0, adm.source.length);
1258
+ return this;
1259
+ },
1002
1260
  every: createMapMethod("every"),
1003
1261
  forEach: createMapMethod("forEach"),
1004
1262
  map: createMapMethod("map"),
@@ -1012,17 +1270,9 @@ class ArrayAdministration extends Administration {
1012
1270
  };
1013
1271
  constructor(source2 = []) {
1014
1272
  super(source2);
1015
- this.valuesMap = new SignalMap();
1273
+ this.valuesMap = new SignalMap(this.atom);
1016
1274
  this.keysAtom = createAtom();
1017
1275
  }
1018
- reportObserveDeep() {
1019
- for (let i = 0; i < this.source.length; i++) {
1020
- const value = this.source[i];
1021
- if (value && typeof value === "object") {
1022
- getAdministration(getObservable(value))?.reportObserved();
1023
- }
1024
- }
1025
- }
1026
1276
  getNode(key) {
1027
1277
  if (key == null) {
1028
1278
  return this.atom;
@@ -1032,52 +1282,98 @@ class ArrayAdministration extends Administration {
1032
1282
  get(index) {
1033
1283
  this.atom.reportObserved();
1034
1284
  this.valuesMap.reportObserved(index, this.source[index]);
1035
- if (isShallowObservable(this.proxy)) {
1036
- return this.source[index];
1285
+ return this._getEffectiveValue(index);
1286
+ }
1287
+ _getEffectiveValue(index) {
1288
+ const value = this.source[index];
1289
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
1290
+ if (this.explicitObservables.has(index)) {
1291
+ const existingAdm = getAdministration(value);
1292
+ if (existingAdm) {
1293
+ if (existingAdm.proxy !== value) {
1294
+ const desc = Object.getOwnPropertyDescriptor(this.source, index);
1295
+ if (desc && !desc.configurable && !desc.writable) {
1296
+ if (process.env.NODE_ENV !== "production") {
1297
+ console.warn(
1298
+ `r-state-tree: cannot return an observable proxy for arr[${index}] because it is a non-configurable, non-writable data property; returning the raw value to uphold Proxy invariants.`
1299
+ );
1300
+ }
1301
+ this.explicitObservables.delete(index);
1302
+ return value;
1303
+ }
1304
+ }
1305
+ return existingAdm.proxy;
1306
+ }
1307
+ }
1037
1308
  }
1038
- return getObservable(this.source[index]);
1309
+ return value;
1039
1310
  }
1040
1311
  set(index, newValue) {
1041
1312
  const values = this.source;
1042
1313
  const targetValue = getSource(newValue);
1043
- if (index < values.length) {
1314
+ const oldLength = values.length;
1315
+ let changed = true;
1316
+ if (index < oldLength) {
1044
1317
  const oldValue = values[index];
1045
- const changed = isObservable(oldValue) ? newValue !== oldValue : targetValue !== oldValue;
1046
- if (changed) {
1047
- values[index] = targetValue;
1048
- this.onArrayChanged(false, index, 1);
1049
- }
1050
- } else if (index === values.length) {
1051
- this.spliceWithArray(index, 0, [newValue]);
1318
+ const oldExplicit = this.explicitObservables.has(index);
1319
+ const newExplicit = isObservable(newValue);
1320
+ changed = !isObservable(oldValue) && oldExplicit !== newExplicit || (isObservable(oldValue) ? newValue !== oldValue : targetValue !== oldValue);
1321
+ }
1322
+ if (!changed) return true;
1323
+ const result = Reflect.set(values, index, targetValue);
1324
+ if (!result) return false;
1325
+ const newLength = values.length;
1326
+ const lengthChanged = newLength !== oldLength;
1327
+ if (isObservable(newValue)) {
1328
+ this.explicitObservables.add(index);
1052
1329
  } else {
1053
- throw new Error(
1054
- `Index out of bounds, ${index} is larger than ${values.length}`
1055
- );
1330
+ this.explicitObservables.delete(index);
1056
1331
  }
1332
+ this.onArrayChanged(lengthChanged, index, 1);
1333
+ return true;
1057
1334
  }
1058
1335
  getArrayLength() {
1059
1336
  this.atom.reportObserved();
1060
1337
  this.keysAtom.reportObserved();
1061
1338
  return this.source.length;
1062
1339
  }
1063
- setArrayLength(newLength) {
1064
- if (typeof newLength !== "number" || newLength < 0)
1065
- throw new Error("Out of range: " + newLength);
1340
+ setArrayLength(input) {
1341
+ const num = Number(input);
1342
+ const coerced = num >>> 0;
1343
+ if (coerced !== num) {
1344
+ throw new RangeError("Invalid array length");
1345
+ }
1346
+ const newLength = coerced;
1066
1347
  const currentLength = this.source.length;
1067
- if (newLength === currentLength) return;
1068
- else if (newLength > currentLength) {
1069
- const newItems = new Array(newLength - currentLength);
1070
- for (let i = 0; i < newLength - currentLength; i++)
1071
- newItems[i] = void 0;
1072
- this.spliceWithArray(currentLength, 0, newItems);
1073
- } else this.spliceWithArray(newLength, currentLength - newLength);
1348
+ if (newLength === currentLength) return true;
1349
+ const result = Reflect.set(this.source, "length", newLength);
1350
+ if (!result) return false;
1351
+ if (newLength < currentLength) {
1352
+ const toRemove = [];
1353
+ for (const index of this.explicitObservables) {
1354
+ if (index >= newLength) {
1355
+ toRemove.push(index);
1356
+ }
1357
+ }
1358
+ for (const index of toRemove) {
1359
+ this.explicitObservables.delete(index);
1360
+ }
1361
+ this.onArrayChanged(true, newLength, currentLength - newLength);
1362
+ } else {
1363
+ this.onArrayChanged(true, currentLength, newLength - currentLength);
1364
+ }
1365
+ return true;
1074
1366
  }
1075
1367
  spliceWithArray(index, deleteCount, newItems) {
1076
1368
  const length = this.source.length;
1077
1369
  const newTargetItems = [];
1370
+ const newObservableIndices = [];
1078
1371
  if (newItems) {
1079
1372
  for (let i = 0; i < newItems.length; i++) {
1080
1373
  newTargetItems[i] = getSource(newItems[i]);
1374
+ if (isObservable(newItems[i])) {
1375
+ newObservableIndices.push(i);
1376
+ }
1081
1377
  }
1082
1378
  }
1083
1379
  if (index === void 0) index = 0;
@@ -1086,15 +1382,39 @@ class ArrayAdministration extends Administration {
1086
1382
  if (arguments.length === 1) deleteCount = length - index;
1087
1383
  else if (deleteCount === void 0 || deleteCount === null) deleteCount = 0;
1088
1384
  else deleteCount = Math.max(0, Math.min(deleteCount, length - index));
1089
- const res = this.spliceItemsIntoValues(index, deleteCount, newTargetItems);
1385
+ const removedItems = [];
1386
+ for (let i = index; i < index + deleteCount; i++) {
1387
+ removedItems.push(this._getEffectiveValue(i));
1388
+ }
1389
+ for (let i = index; i < index + deleteCount; i++) {
1390
+ this.explicitObservables.delete(i);
1391
+ }
1392
+ const shift = (newItems?.length ?? 0) - deleteCount;
1393
+ if (shift !== 0) {
1394
+ const newExplicitObservables = /* @__PURE__ */ new Set();
1395
+ for (const idx of this.explicitObservables) {
1396
+ if (idx < index) {
1397
+ newExplicitObservables.add(idx);
1398
+ } else if (idx >= index + deleteCount) {
1399
+ newExplicitObservables.add(idx + shift);
1400
+ }
1401
+ }
1402
+ this.explicitObservables.clear();
1403
+ for (const idx of newExplicitObservables) {
1404
+ this.explicitObservables.add(idx);
1405
+ }
1406
+ }
1407
+ for (const relativeIdx of newObservableIndices) {
1408
+ this.explicitObservables.add(index + relativeIdx);
1409
+ }
1410
+ this.spliceItemsIntoValues(index, deleteCount, newTargetItems);
1090
1411
  if (deleteCount !== 0 || newTargetItems.length !== 0) {
1091
- this.onArrayChanged(
1092
- length !== this.source.length,
1093
- index,
1094
- Math.max(deleteCount ?? 0, newItems?.length ?? 0)
1095
- );
1412
+ const shift2 = (newItems?.length ?? 0) - deleteCount;
1413
+ const reindexing = shift2 !== 0 && index + deleteCount < length;
1414
+ const count = reindexing ? Number.POSITIVE_INFINITY : Math.max(deleteCount ?? 0, newItems?.length ?? 0);
1415
+ this.onArrayChanged(length !== this.source.length, index, count);
1096
1416
  }
1097
- return res;
1417
+ return removedItems;
1098
1418
  }
1099
1419
  spliceItemsIntoValues(index, deleteCount, newItems) {
1100
1420
  return this.source.splice.apply(
@@ -1109,9 +1429,16 @@ class ArrayAdministration extends Administration {
1109
1429
  }
1110
1430
  if (index == null) {
1111
1431
  this.atom.reportChanged();
1112
- } else {
1113
- for (let i = index; i < index + count; i++) {
1114
- this.valuesMap.reportChanged(i, this.source[i]);
1432
+ } else if (count !== void 0 && count > 0) {
1433
+ const observedKeys = this.valuesMap.keys();
1434
+ const end = index + count;
1435
+ for (const key of observedKeys) {
1436
+ if (typeof key === "number" && key >= index && key < end) {
1437
+ const node = this.valuesMap.get(key);
1438
+ if (node) {
1439
+ node.reportChanged(this._getEffectiveValue(key));
1440
+ }
1441
+ }
1115
1442
  }
1116
1443
  }
1117
1444
  this.flushChange();
@@ -1127,7 +1454,7 @@ function createMethod(method, func) {
1127
1454
  function createStringMethod(method) {
1128
1455
  return createMethod(method, function() {
1129
1456
  const adm = getAdministration(this);
1130
- adm.reportObserved(false);
1457
+ adm.reportObserved();
1131
1458
  const sourceArr = getSource(this);
1132
1459
  return sourceArr[method].apply(sourceArr, arguments);
1133
1460
  });
@@ -1135,7 +1462,7 @@ function createStringMethod(method) {
1135
1462
  function createSearchMethod(method) {
1136
1463
  return createMethod(method, function() {
1137
1464
  const adm = getAdministration(this);
1138
- adm.reportObserved(false);
1465
+ adm.reportObserved();
1139
1466
  const target = arguments[0];
1140
1467
  const source2 = getSource(target);
1141
1468
  const sourceArr = getSource(this);
@@ -1151,10 +1478,38 @@ function createSearchMethod(method) {
1151
1478
  function createCopyMethod(method) {
1152
1479
  return createMethod(method, function() {
1153
1480
  const adm = getAdministration(this);
1154
- adm.reportObserved(false);
1155
- return getObservable(
1156
- adm.source[method].apply(adm.source, arguments)
1157
- );
1481
+ adm.reportObserved();
1482
+ const observedInput = [];
1483
+ observedInput.length = adm.source.length;
1484
+ const keys = Object.keys(adm.source);
1485
+ for (let i = 0; i < keys.length; i++) {
1486
+ const key = keys[i];
1487
+ const idx = Number(key);
1488
+ if (!Number.isNaN(idx)) {
1489
+ observedInput[idx] = this[idx];
1490
+ }
1491
+ }
1492
+ const args = Array.from(arguments);
1493
+ if (method === "concat") {
1494
+ for (let i = 0; i < args.length; i++) {
1495
+ const arg = args[i];
1496
+ if (Array.isArray(arg) && isObservable(arg)) {
1497
+ const argAdm = getAdministration(arg);
1498
+ const argObserved = [];
1499
+ argObserved.length = argAdm.source.length;
1500
+ const argKeys = Object.keys(argAdm.source);
1501
+ for (let j = 0; j < argKeys.length; j++) {
1502
+ const argKey = argKeys[j];
1503
+ const argIdx = Number(argKey);
1504
+ if (!Number.isNaN(argIdx)) {
1505
+ argObserved[argIdx] = arg[argIdx];
1506
+ }
1507
+ }
1508
+ args[i] = argObserved;
1509
+ }
1510
+ }
1511
+ }
1512
+ return Array.prototype[method].apply(observedInput, args);
1158
1513
  });
1159
1514
  }
1160
1515
  function createMapMethod(method) {
@@ -1162,14 +1517,9 @@ function createMapMethod(method) {
1162
1517
  method,
1163
1518
  function(callback, thisArg) {
1164
1519
  const adm = getAdministration(this);
1165
- adm.reportObserved(false);
1166
- return adm.source[method]((element, index) => {
1167
- return callback.call(
1168
- thisArg,
1169
- element && typeof element === "object" ? getObservable(element) : element,
1170
- index,
1171
- this
1172
- );
1520
+ adm.reportObserved();
1521
+ return adm.source[method]((_element, index) => {
1522
+ return callback.call(thisArg, this[index], index, this);
1173
1523
  });
1174
1524
  }
1175
1525
  );
@@ -1179,28 +1529,17 @@ function createFilterMethod(method) {
1179
1529
  method,
1180
1530
  function(callback, thisArg) {
1181
1531
  const adm = getAdministration(this);
1182
- adm.reportObserved(false);
1183
- return getObservable(
1184
- adm.source[method]((element, index) => {
1185
- return callback.call(
1186
- thisArg,
1187
- element && typeof element === "object" ? getObservable(element) : element,
1188
- index,
1189
- this
1190
- );
1191
- })
1192
- );
1532
+ adm.reportObserved();
1533
+ return adm.source[method]((_element, index) => {
1534
+ return callback.call(thisArg, this[index], index, this);
1535
+ });
1193
1536
  }
1194
1537
  );
1195
1538
  }
1196
1539
  function createReduceMethod(method) {
1197
1540
  return createMethod(method, function() {
1198
1541
  const adm = getAdministration(this);
1199
- adm.reportObserved(false);
1200
- const callback = arguments[0];
1201
- arguments[0] = (accumulator, currentValue, index) => {
1202
- return callback(accumulator, getObservable(currentValue), index, this);
1203
- };
1542
+ adm.reportObserved();
1204
1543
  return adm.source[method].apply(adm.source, arguments);
1205
1544
  });
1206
1545
  }
@@ -1227,6 +1566,7 @@ function addDateSetMethod(method) {
1227
1566
  const adm = getAdministration(this);
1228
1567
  const res = adm.source[method].apply(adm.source, arguments);
1229
1568
  adm.atom.reportChanged();
1569
+ adm.flushChange();
1230
1570
  return res;
1231
1571
  };
1232
1572
  }
@@ -1262,9 +1602,15 @@ function getAction(fn) {
1262
1602
  }
1263
1603
  function getObservableClassInstance(value) {
1264
1604
  const adm = new PreactObjectAdministration(value);
1605
+ administrationMap.set(adm.proxy, adm);
1265
1606
  administrationMap.set(adm.source, adm);
1266
1607
  return adm.proxy;
1267
1608
  }
1609
+ class Observable {
1610
+ constructor() {
1611
+ return getObservableClassInstance(this);
1612
+ }
1613
+ }
1268
1614
  function createObservableWithCustomAdministration(value, Adm) {
1269
1615
  const adm = new Adm(value);
1270
1616
  administrationMap.set(adm.proxy, adm);
@@ -1272,40 +1618,6 @@ function createObservableWithCustomAdministration(value, Adm) {
1272
1618
  return adm.proxy;
1273
1619
  }
1274
1620
  function getObservable(value) {
1275
- if (!value) {
1276
- return value;
1277
- }
1278
- const adm = getAdministration(value);
1279
- if (adm) {
1280
- return adm.proxy;
1281
- }
1282
- if ((typeof value === "object" || typeof value === "function") && !Object.isFrozen(value)) {
1283
- const obj = value;
1284
- let Adm = PreactObjectAdministration;
1285
- if (Array.isArray(obj)) {
1286
- Adm = ArrayAdministration;
1287
- } else if (obj instanceof Map || obj instanceof WeakMap) {
1288
- Adm = CollectionAdministration;
1289
- } else if (obj instanceof Set || obj instanceof WeakSet) {
1290
- Adm = CollectionAdministration;
1291
- } else if (obj instanceof Date) {
1292
- Adm = DateAdministration;
1293
- } else if (!isPlainObject(value)) {
1294
- return value;
1295
- }
1296
- const adm2 = new Adm(obj);
1297
- administrationMap.set(adm2.proxy, adm2);
1298
- administrationMap.set(adm2.source, adm2);
1299
- return adm2.proxy;
1300
- }
1301
- return value;
1302
- }
1303
- const shallowObservables = /* @__PURE__ */ new WeakSet();
1304
- function isShallowObservable(obj) {
1305
- if (!obj || typeof obj !== "object") return false;
1306
- return shallowObservables.has(obj);
1307
- }
1308
- function getShallowObservable(value) {
1309
1621
  if (!value) {
1310
1622
  return value;
1311
1623
  }
@@ -1313,23 +1625,43 @@ function getShallowObservable(value) {
1313
1625
  if (existingAdm) {
1314
1626
  return existingAdm.proxy;
1315
1627
  }
1316
- if ((typeof value === "object" || typeof value === "function") && !Object.isFrozen(value)) {
1628
+ if (typeof value === "function") {
1629
+ if (process.env.NODE_ENV !== "production") {
1630
+ console.warn(
1631
+ `r-state-tree: functions are not observable containers. The function will be returned unchanged. Note: functions read from observable objects are still automatically batched as actions.`
1632
+ );
1633
+ }
1634
+ return value;
1635
+ }
1636
+ if (typeof value === "object") {
1317
1637
  const obj = value;
1318
1638
  let Adm = null;
1319
- if (Array.isArray(obj)) {
1320
- Adm = ArrayAdministration;
1321
- } else if (obj instanceof Map || obj instanceof WeakMap) {
1639
+ if (obj instanceof Map || obj instanceof WeakMap) {
1322
1640
  Adm = CollectionAdministration;
1323
1641
  } else if (obj instanceof Set || obj instanceof WeakSet) {
1324
1642
  Adm = CollectionAdministration;
1643
+ } else if (obj instanceof Date) {
1644
+ Adm = DateAdministration;
1645
+ } else if (!Object.isFrozen(obj)) {
1646
+ if (Array.isArray(obj)) {
1647
+ Adm = ArrayAdministration;
1648
+ } else if (isPlainObject(obj)) {
1649
+ Adm = PreactObjectAdministration;
1650
+ }
1325
1651
  }
1326
1652
  if (Adm) {
1327
1653
  const adm = new Adm(obj);
1328
1654
  administrationMap.set(adm.proxy, adm);
1329
1655
  administrationMap.set(adm.source, adm);
1330
- shallowObservables.add(adm.proxy);
1331
1656
  return adm.proxy;
1332
1657
  }
1658
+ if (process.env.NODE_ENV !== "production" && !Object.isFrozen(obj)) {
1659
+ const proto = Object.getPrototypeOf(obj);
1660
+ const typeName = proto?.constructor?.name && proto.constructor.name !== "Object" ? `instance of ${proto.constructor.name}` : "non-plain object";
1661
+ console.warn(
1662
+ `r-state-tree: observable() was called with a ${typeName}. This object will NOT be made observable because proxying arbitrary class instances can break #private fields and built-in brand checks. To make a class observable, use 'class MyClass extends Observable'.`
1663
+ );
1664
+ }
1333
1665
  }
1334
1666
  return value;
1335
1667
  }
@@ -1358,19 +1690,77 @@ function getPropertyDescriptor(obj, key) {
1358
1690
  }
1359
1691
  return void 0;
1360
1692
  }
1361
- function clone(val) {
1362
- if (Array.isArray(val)) {
1363
- return val.map((v) => clone(v));
1364
- } else if (val && typeof val === "object") {
1365
- const keys = Object.keys(val);
1366
- const cloned = {};
1367
- for (let i = 0; i < keys.length; i++) {
1368
- const key = keys[i];
1369
- cloned[key] = clone(val[key]);
1693
+ function clone(val, path = "") {
1694
+ if (val === null || val === void 0) {
1695
+ return val;
1696
+ }
1697
+ if (typeof val !== "object") {
1698
+ if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
1699
+ return val;
1700
+ }
1701
+ const atPath = path ? ` at path "${path}"` : "";
1702
+ if (typeof val === "bigint") {
1703
+ throw new Error(
1704
+ `r-state-tree: snapshots do not support bigint${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1705
+ );
1370
1706
  }
1371
- return cloned;
1707
+ if (typeof val === "symbol") {
1708
+ throw new Error(
1709
+ `r-state-tree: snapshots do not support symbol${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1710
+ );
1711
+ }
1712
+ if (typeof val === "function") {
1713
+ throw new Error(
1714
+ `r-state-tree: snapshots do not support function${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1715
+ );
1716
+ }
1717
+ throw new Error(
1718
+ `r-state-tree: snapshots do not support ${typeof val}${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1719
+ );
1720
+ }
1721
+ if (val instanceof signalsCore.Signal) {
1722
+ return clone(
1723
+ val.value,
1724
+ path
1725
+ );
1726
+ }
1727
+ if (val instanceof Date) {
1728
+ return val.toISOString();
1729
+ }
1730
+ if (Array.isArray(val)) {
1731
+ return val.map(
1732
+ (v, i) => clone(v, path ? `${path}[${i}]` : `[${i}]`)
1733
+ );
1734
+ }
1735
+ if (!isPlainObject(val)) {
1736
+ const typeName = getTypeName(val);
1737
+ const atPath = path ? ` at path "${path}"` : "";
1738
+ throw new Error(
1739
+ `r-state-tree: snapshots do not support ${typeName}${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1740
+ );
1372
1741
  }
1373
- return val;
1742
+ const keys = Object.keys(val);
1743
+ const cloned = {};
1744
+ for (let i = 0; i < keys.length; i++) {
1745
+ const key = keys[i];
1746
+ const keyPath = path ? `${path}.${key}` : key;
1747
+ cloned[key] = clone(val[key], keyPath);
1748
+ }
1749
+ return cloned;
1750
+ }
1751
+ function getTypeName(val) {
1752
+ if (val instanceof Map) return "Map";
1753
+ if (val instanceof Set) return "Set";
1754
+ if (val instanceof WeakMap) return "WeakMap";
1755
+ if (val instanceof WeakSet) return "WeakSet";
1756
+ if (val instanceof RegExp) return "RegExp";
1757
+ if (val instanceof Error) return "Error";
1758
+ if (val instanceof Promise) return "Promise";
1759
+ const proto = Object.getPrototypeOf(val);
1760
+ if (proto?.constructor?.name && proto.constructor.name !== "Object") {
1761
+ return `class instance (${proto.constructor.name})`;
1762
+ }
1763
+ return "non-plain object";
1374
1764
  }
1375
1765
  function getDiff(o1, o2, getConfig) {
1376
1766
  const config = getConfig(o2);
@@ -1443,7 +1833,9 @@ function updateProps(props, newProps) {
1443
1833
  }
1444
1834
  });
1445
1835
  if (newProps.models) {
1446
- if (!props.models) props.models = {};
1836
+ if (!props.models || !isObservable(props.models)) {
1837
+ props.models = getObservable(props.models || {});
1838
+ }
1447
1839
  Object.assign(props.models, newProps.models);
1448
1840
  }
1449
1841
  });
@@ -1667,7 +2059,9 @@ class StoreAdministration extends PreactObjectAdministration {
1667
2059
  }
1668
2060
  }
1669
2061
  getModelRef(name) {
1670
- return this.proxy.props.models?.[name] ?? null;
2062
+ const models = this.proxy.props.models;
2063
+ const ref = models?.[name] ?? null;
2064
+ return ref;
1671
2065
  }
1672
2066
  isRoot() {
1673
2067
  return !this.parent;
@@ -2005,11 +2399,12 @@ class ObservableListener {
2005
2399
  class ChildModelsAdministration extends ArrayAdministration {
2006
2400
  set(index, newValue) {
2007
2401
  return signalsCore.batch(() => {
2008
- super.set(index, newValue);
2402
+ const result = super.set(index, newValue);
2009
2403
  const sourceValue = getSource(newValue);
2010
2404
  if (this.source[index] !== sourceValue) {
2011
2405
  notifyArrayUpdate(this.proxy, index, this.source[index], sourceValue);
2012
2406
  }
2407
+ return result;
2013
2408
  });
2014
2409
  }
2015
2410
  spliceWithArray(index, deleteCount, newItems) {
@@ -2042,7 +2437,19 @@ function getIdKey(Ctor) {
2042
2437
  function getModelRefSnapshot(modelRef2) {
2043
2438
  const Ctor = Object.getPrototypeOf(modelRef2).constructor;
2044
2439
  const idKey = getIdKey(Ctor);
2045
- return idKey ? { [idKey]: getIdentifier(modelRef2) } : null;
2440
+ if (!idKey) return null;
2441
+ let id2 = getIdentifier(modelRef2);
2442
+ if (id2 === void 0) {
2443
+ const source2 = getSource(modelRef2);
2444
+ id2 = getIdentifier(source2);
2445
+ if (id2 === void 0) {
2446
+ const adm = getAdministration(modelRef2);
2447
+ if (adm && adm.proxy !== modelRef2) {
2448
+ id2 = getIdentifier(adm.proxy);
2449
+ }
2450
+ }
2451
+ }
2452
+ return { [idKey]: id2 };
2046
2453
  }
2047
2454
  function getSnapshotId(snapshot, Ctor) {
2048
2455
  const idKey = getIdKey(Ctor);
@@ -2127,9 +2534,7 @@ class ModelAdministration extends PreactObjectAdministration {
2127
2534
  adm.setId(name, value);
2128
2535
  break;
2129
2536
  }
2130
- case ModelCfgTypes.state:
2131
- case ModelCfgTypes.stateShallow:
2132
- case ModelCfgTypes.stateSignal: {
2537
+ case ModelCfgTypes.state: {
2133
2538
  adm.setState(name, value);
2134
2539
  break;
2135
2540
  }
@@ -2168,9 +2573,60 @@ class ModelAdministration extends PreactObjectAdministration {
2168
2573
  modelsTraceUnsub = /* @__PURE__ */ new Map();
2169
2574
  writeInProgress = /* @__PURE__ */ new Set();
2170
2575
  computedSnapshot;
2576
+ snapshotAtom = createAtom();
2171
2577
  snapshotMap = /* @__PURE__ */ new Map();
2172
2578
  contextCache = /* @__PURE__ */ new Map();
2173
2579
  parentName = null;
2580
+ /**
2581
+ * `@state` fields are shallow-reactive (property-level assignment triggers reactivity)
2582
+ * and participate in snapshots. Values stored in `@state` are not deep-wrapped.
2583
+ *
2584
+ * This helper walks a value and:
2585
+ * - observes any observable containers found (proxy or source) so in-place mutations
2586
+ * invalidate `getSnapshot()` / `toSnapshot()`
2587
+ * - avoids proxy traversal by preferring `getSource(...)`
2588
+ * - guards against cycles via `WeakSet`
2589
+ */
2590
+ observeSnapshotValue(value, seen) {
2591
+ if (value == null) return;
2592
+ if (typeof value !== "object") return;
2593
+ if (!seen) seen = /* @__PURE__ */ new WeakSet();
2594
+ const obj = value;
2595
+ if (seen.has(obj)) return;
2596
+ seen.add(obj);
2597
+ const adm = getAdministration(obj);
2598
+ if (adm) {
2599
+ adm.reportObserved();
2600
+ }
2601
+ const src = getSource(value);
2602
+ if (src && typeof src === "object" && src !== value) {
2603
+ this.observeSnapshotValue(src, seen);
2604
+ return;
2605
+ }
2606
+ if (Array.isArray(value)) {
2607
+ for (let i = 0; i < value.length; i++) {
2608
+ this.observeSnapshotValue(value[i], seen);
2609
+ }
2610
+ return;
2611
+ }
2612
+ if (value instanceof Map) {
2613
+ value.forEach((v, k) => {
2614
+ this.observeSnapshotValue(k, seen);
2615
+ this.observeSnapshotValue(v, seen);
2616
+ });
2617
+ return;
2618
+ }
2619
+ if (value instanceof Set) {
2620
+ value.forEach((v) => this.observeSnapshotValue(v, seen));
2621
+ return;
2622
+ }
2623
+ if (value instanceof Date) {
2624
+ return;
2625
+ }
2626
+ for (const key of Object.keys(value)) {
2627
+ this.observeSnapshotValue(value[key], seen);
2628
+ }
2629
+ }
2174
2630
  get parent() {
2175
2631
  this.parentAtom.reportObserved();
2176
2632
  return this._parent;
@@ -2199,12 +2655,15 @@ class ModelAdministration extends PreactObjectAdministration {
2199
2655
  setState(name, value) {
2200
2656
  const oldValue = this.source[name];
2201
2657
  if (value !== oldValue) {
2202
- PreactObjectAdministration.proxyTraps.set(
2203
- this.source,
2204
- name,
2205
- value,
2206
- this.proxy
2207
- );
2658
+ signalsCore.batch(() => {
2659
+ PreactObjectAdministration.proxyTraps.set(
2660
+ this.source,
2661
+ name,
2662
+ value,
2663
+ this.proxy
2664
+ );
2665
+ this.snapshotAtom.reportChanged();
2666
+ });
2208
2667
  }
2209
2668
  }
2210
2669
  setId(name, v) {
@@ -2258,9 +2717,9 @@ class ModelAdministration extends PreactObjectAdministration {
2258
2717
  getModelAdm(currentValue).detach();
2259
2718
  } else if (Array.isArray(currentValue)) {
2260
2719
  const oldModels = currentValue;
2261
- const newModelSet = new Set(newModels);
2720
+ const newModelSet = new Set(newModels.map((m) => getSource(m)));
2262
2721
  oldModels.forEach(
2263
- (child2) => newModelSet.has(child2) || getModelAdm(child2).detach()
2722
+ (child2) => newModelSet.has(getSource(child2)) || getModelAdm(child2).detach()
2264
2723
  );
2265
2724
  this.modelsTraceUnsub.get(name)?.();
2266
2725
  }
@@ -2283,8 +2742,8 @@ class ModelAdministration extends PreactObjectAdministration {
2283
2742
  })
2284
2743
  );
2285
2744
  newModels.forEach((child2) => {
2286
- const oldModelSet = Array.isArray(currentValue) ? new Set(currentValue) : /* @__PURE__ */ new Set();
2287
- if (!oldModelSet.has(child2)) {
2745
+ const oldModelSet = Array.isArray(currentValue) ? new Set(currentValue.map((m) => getSource(m))) : /* @__PURE__ */ new Set();
2746
+ if (!oldModelSet.has(getSource(child2))) {
2288
2747
  const internalModel = getModelAdm(child2);
2289
2748
  internalModel.attach(this, name);
2290
2749
  }
@@ -2398,11 +2857,14 @@ class ModelAdministration extends PreactObjectAdministration {
2398
2857
  toJSON() {
2399
2858
  return Object.keys(this.configuration).reduce((json, key) => {
2400
2859
  switch (this.configuration[key].type) {
2401
- case ModelCfgTypes.state:
2402
- case ModelCfgTypes.stateShallow:
2403
- case ModelCfgTypes.stateSignal:
2860
+ case ModelCfgTypes.state: {
2861
+ const value = this.proxy[key];
2862
+ this.observeSnapshotValue(value);
2863
+ json[key] = clone(getSource(value), key);
2864
+ break;
2865
+ }
2404
2866
  case ModelCfgTypes.id:
2405
- json[key] = clone(getSource(this.proxy[key]));
2867
+ json[key] = clone(getSource(this.proxy[key]), key);
2406
2868
  break;
2407
2869
  case ModelCfgTypes.modelRef:
2408
2870
  const model2 = this.proxy[key];
@@ -2466,8 +2928,6 @@ class ModelAdministration extends PreactObjectAdministration {
2466
2928
  const value = snapshot[key];
2467
2929
  switch (type) {
2468
2930
  case ModelCfgTypes.state:
2469
- case ModelCfgTypes.stateShallow:
2470
- case ModelCfgTypes.stateSignal:
2471
2931
  this.proxy[key] = value;
2472
2932
  break;
2473
2933
  case ModelCfgTypes.modelRef:
@@ -2543,6 +3003,7 @@ class ModelAdministration extends PreactObjectAdministration {
2543
3003
  getSnapshot() {
2544
3004
  if (!this.computedSnapshot) {
2545
3005
  this.computedSnapshot = createComputed(() => {
3006
+ this.snapshotAtom.reportObserved();
2546
3007
  const json = this.toJSON();
2547
3008
  configMap.set(json, this.configuration);
2548
3009
  return json;
@@ -2661,6 +3122,73 @@ function createContext(defaultValue) {
2661
3122
  }
2662
3123
  };
2663
3124
  }
3125
+ function toObservableTree(value) {
3126
+ return toObservableTreeInternal(value, /* @__PURE__ */ new Set(), "");
3127
+ }
3128
+ function buildPath(currentPath, key) {
3129
+ if (typeof key === "number") {
3130
+ return `${currentPath}[${key}]`;
3131
+ }
3132
+ return currentPath ? `${currentPath}.${key}` : key;
3133
+ }
3134
+ function toObservableTreeInternal(value, ancestorPath, path) {
3135
+ if (value === null || typeof value !== "object") {
3136
+ return value;
3137
+ }
3138
+ if (Array.isArray(value)) {
3139
+ if (ancestorPath.has(value)) {
3140
+ throw new Error(
3141
+ `r-state-tree: toObservableTree does not support circular references (cycle detected at path "${path}")`
3142
+ );
3143
+ }
3144
+ ancestorPath.add(value);
3145
+ const toWrap = [];
3146
+ for (let i = 0; i < value.length; i++) {
3147
+ const element = value[i];
3148
+ if (Array.isArray(element) || isPlainObject(element)) {
3149
+ toWrap.push({ index: i, element });
3150
+ }
3151
+ }
3152
+ const proxy = observable(value);
3153
+ for (const { index, element } of toWrap) {
3154
+ proxy[index] = toObservableTreeInternal(
3155
+ element,
3156
+ ancestorPath,
3157
+ buildPath(path, index)
3158
+ );
3159
+ }
3160
+ ancestorPath.delete(value);
3161
+ return proxy;
3162
+ }
3163
+ if (isPlainObject(value)) {
3164
+ if (ancestorPath.has(value)) {
3165
+ throw new Error(
3166
+ `r-state-tree: toObservableTree does not support circular references (cycle detected at path "${path}")`
3167
+ );
3168
+ }
3169
+ ancestorPath.add(value);
3170
+ const toWrap = [];
3171
+ const keys = Object.keys(value);
3172
+ for (let i = 0; i < keys.length; i++) {
3173
+ const key = keys[i];
3174
+ const propValue = value[key];
3175
+ if (Array.isArray(propValue) || isPlainObject(propValue)) {
3176
+ toWrap.push({ key, propValue });
3177
+ }
3178
+ }
3179
+ const proxy = observable(value);
3180
+ for (const { key, propValue } of toWrap) {
3181
+ proxy[key] = toObservableTreeInternal(
3182
+ propValue,
3183
+ ancestorPath,
3184
+ buildPath(path, key)
3185
+ );
3186
+ }
3187
+ ancestorPath.delete(value);
3188
+ return proxy;
3189
+ }
3190
+ return value;
3191
+ }
2664
3192
  function makeDecorator(type) {
2665
3193
  return function(value, context) {
2666
3194
  context.metadata[context.name] = type;
@@ -2683,10 +3211,7 @@ const child = makeChildDecorator(childType);
2683
3211
  const modelRef = makeChildDecorator(modelRefType);
2684
3212
  const model = makeDecorator(modelType);
2685
3213
  const id = makeDecorator(idType);
2686
- const state = Object.assign(makeDecorator(stateType), {
2687
- shallow: makeDecorator(stateShallowType),
2688
- signal: makeDecorator(stateSignalType)
2689
- });
3214
+ const state = makeDecorator(stateType);
2690
3215
  Object.defineProperty(exports, "Signal", {
2691
3216
  enumerable: true,
2692
3217
  get: () => signalsCore.Signal
@@ -2699,10 +3224,6 @@ Object.defineProperty(exports, "effect", {
2699
3224
  enumerable: true,
2700
3225
  get: () => signalsCore.effect
2701
3226
  });
2702
- Object.defineProperty(exports, "signal", {
2703
- enumerable: true,
2704
- get: () => signalsCore.signal
2705
- });
2706
3227
  Object.defineProperty(exports, "untracked", {
2707
3228
  enumerable: true,
2708
3229
  get: () => signalsCore.untracked
@@ -2727,8 +3248,10 @@ exports.onSnapshotDiff = onSnapshotDiff;
2727
3248
  exports.reaction = reaction;
2728
3249
  exports.reportChanged = reportChanged;
2729
3250
  exports.reportObserved = reportObserved;
3251
+ exports.signal = signal;
2730
3252
  exports.source = source;
2731
3253
  exports.state = state;
3254
+ exports.toObservableTree = toObservableTree;
2732
3255
  exports.toSnapshot = toSnapshot;
2733
3256
  exports.unmount = unmount;
2734
3257
  exports.updateStore = updateStore;