r-state-tree 0.5.0 → 0.6.1

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.
@@ -1,5 +1,5 @@
1
- import { batch, Signal, signal, computed as computed$1, untracked, effect } from "@preact/signals-core";
2
- import { Signal as Signal2, batch as batch2, effect as effect2, signal as signal2, untracked as untracked2 } from "@preact/signals-core";
1
+ import { batch, signal as signal$1, Signal, computed as computed$1, untracked, effect } from "@preact/signals-core";
2
+ import { Signal as Signal2, batch as batch2, effect as effect2, untracked as untracked2 } from "@preact/signals-core";
3
3
  var lib = {};
4
4
  var hasRequiredLib;
5
5
  function requireLib() {
@@ -16,8 +16,6 @@ var CommonCfgTypes = /* @__PURE__ */ ((CommonCfgTypes2) => {
16
16
  })(CommonCfgTypes || {});
17
17
  var ModelCfgTypes = /* @__PURE__ */ ((ModelCfgTypes2) => {
18
18
  ModelCfgTypes2["state"] = "state";
19
- ModelCfgTypes2["stateShallow"] = "stateShallow";
20
- ModelCfgTypes2["stateSignal"] = "stateSignal";
21
19
  ModelCfgTypes2["id"] = "id";
22
20
  ModelCfgTypes2["modelRef"] = "modelRef";
23
21
  return ModelCfgTypes2;
@@ -27,9 +25,6 @@ var StoreCfgTypes = /* @__PURE__ */ ((StoreCfgTypes2) => {
27
25
  return StoreCfgTypes2;
28
26
  })(StoreCfgTypes || {});
29
27
  var ObservableCfgTypes = /* @__PURE__ */ ((ObservableCfgTypes2) => {
30
- ObservableCfgTypes2["observable"] = "observable";
31
- ObservableCfgTypes2["observableShallow"] = "observableShallow";
32
- ObservableCfgTypes2["observableSignal"] = "observableSignal";
33
28
  ObservableCfgTypes2["computed"] = "computed";
34
29
  return ObservableCfgTypes2;
35
30
  })(ObservableCfgTypes || {});
@@ -46,14 +41,6 @@ const stateType = {
46
41
  type: "state"
47
42
  /* state */
48
43
  };
49
- const stateShallowType = {
50
- type: "stateShallow"
51
- /* stateShallow */
52
- };
53
- const stateSignalType = {
54
- type: "stateSignal"
55
- /* stateSignal */
56
- };
57
44
  const modelRefType = Object.assign(
58
45
  function(childType2) {
59
46
  return { type: "modelRef", childType: childType2 };
@@ -78,32 +65,29 @@ function isPropertyKey(val) {
78
65
  return typeof val === "string" || typeof val === "number" || typeof val === "symbol";
79
66
  }
80
67
  function getPropertyType(key, obj) {
81
- const hasMetadata = obj.constructor[Symbol.metadata] !== void 0;
68
+ const ctor = obj.constructor;
69
+ const hasMetadata = ctor != null && ctor[Symbol.metadata] !== void 0;
82
70
  const descriptor = getPropertyDescriptor$1(obj, key);
83
71
  if (descriptor?.value && typeof descriptor.value === "function") {
84
72
  return "action";
85
73
  }
86
- const isGetter = descriptor && (typeof descriptor.get === "function" || typeof descriptor.set === "function");
74
+ const isAccessor = descriptor && (typeof descriptor.get === "function" || typeof descriptor.set === "function");
87
75
  if (!hasMetadata) {
88
- if (isGetter) {
76
+ if (descriptor?.get) {
89
77
  return "computed";
90
78
  }
79
+ if (isAccessor) {
80
+ return null;
81
+ }
91
82
  return "observable";
92
83
  }
93
84
  const metadata = obj.constructor[Symbol.metadata];
94
- if (metadata && metadata[key]) {
95
- const config = metadata[key];
85
+ const config = metadata?.[key];
86
+ if (config) {
96
87
  switch (config.type) {
97
88
  case ObservableCfgTypes.computed:
98
89
  return "computed";
99
- case ObservableCfgTypes.observableShallow:
100
- case ModelCfgTypes.stateShallow:
101
- return "observableShallow";
102
- case ObservableCfgTypes.observableSignal:
103
- case ModelCfgTypes.stateSignal:
104
- return "observableSignal";
105
90
  case ModelCfgTypes.state:
106
- case ObservableCfgTypes.observable:
107
91
  case ModelCfgTypes.id:
108
92
  case ModelCfgTypes.modelRef:
109
93
  case CommonCfgTypes.child:
@@ -111,7 +95,7 @@ function getPropertyType(key, obj) {
111
95
  return "observable";
112
96
  }
113
97
  }
114
- return null;
98
+ return isAccessor ? null : "observable";
115
99
  }
116
100
  function getPropertyDescriptor$1(obj, key) {
117
101
  let node = obj;
@@ -140,7 +124,7 @@ class Administration {
140
124
  atom;
141
125
  valuesMap;
142
126
  isObserved = false;
143
- forceObservedAtoms;
127
+ forceObservedAtom;
144
128
  constructor(source2) {
145
129
  this.atom = createObservedAtom();
146
130
  this.source = source2;
@@ -150,13 +134,9 @@ class Administration {
150
134
  );
151
135
  }
152
136
  flushChange() {
153
- if (this.forceObservedAtoms?.length) {
154
- batch(() => {
155
- for (let i = 0; i < this.forceObservedAtoms.length; i++) {
156
- this.forceObservedAtoms[i].reportChanged();
157
- }
158
- });
159
- this.forceObservedAtoms = void 0;
137
+ if (this.forceObservedAtom) {
138
+ this.forceObservedAtom.reportChanged();
139
+ this.forceObservedAtom = void 0;
160
140
  }
161
141
  }
162
142
  getNode() {
@@ -165,9 +145,7 @@ class Administration {
165
145
  reportChanged() {
166
146
  this.atom.reportChanged();
167
147
  }
168
- reportObserveDeep() {
169
- }
170
- reportObserved(deep = false) {
148
+ reportObserved() {
171
149
  const entry = circularRefSet == null;
172
150
  if (entry) {
173
151
  circularRefSet = /* @__PURE__ */ new WeakSet();
@@ -175,15 +153,10 @@ class Administration {
175
153
  return;
176
154
  }
177
155
  circularRefSet.add(this);
178
- const atom = createAtom();
179
- if (!this.forceObservedAtoms) {
180
- this.forceObservedAtoms = [];
181
- }
182
- this.forceObservedAtoms.push(atom);
183
- atom.reportObserved();
184
- if (deep) {
185
- this.reportObserveDeep();
156
+ if (!this.forceObservedAtom) {
157
+ this.forceObservedAtom = createAtom();
186
158
  }
159
+ this.forceObservedAtom.reportObserved();
187
160
  if (entry) {
188
161
  circularRefSet = null;
189
162
  }
@@ -246,6 +219,9 @@ class NodeMap {
246
219
  reportChanged(key, value) {
247
220
  return this.get(key)?.reportChanged(value);
248
221
  }
222
+ keys() {
223
+ return this.map?.keys() ?? [];
224
+ }
249
225
  }
250
226
  class AtomMap extends NodeMap {
251
227
  createNode() {
@@ -263,31 +239,34 @@ class ObjectAdministration extends Administration {
263
239
  valuesMap;
264
240
  computedMap;
265
241
  types;
242
+ isWriting = false;
266
243
  static proxyTraps = {
267
244
  has(target, name) {
268
245
  const adm = getAdministration(target);
269
- if (!(name in Object.prototype) && isPropertyKey(name))
246
+ if (isPropertyKey(name) && (!(name in Object.prototype) || Object.prototype.hasOwnProperty.call(adm.source, name)))
270
247
  return adm.has(name);
271
248
  return Reflect.has(adm.source, name);
272
249
  },
273
250
  get(target, name) {
274
251
  const adm = getAdministration(target);
275
- if (!(name in Object.prototype) && isPropertyKey(name) && (typeof adm.source !== "function" || name !== "prototype")) {
276
- return adm.read(name);
252
+ if (isPropertyKey(name) && (!(name in Object.prototype) || Object.prototype.hasOwnProperty.call(adm.source, name)) && (typeof adm.source !== "function" || name !== "prototype")) {
253
+ return adm.read(name, arguments[2]);
277
254
  }
278
- return Reflect.get(adm.source, name, adm.proxy);
255
+ return Reflect.get(adm.source, name, arguments[2]);
279
256
  },
280
257
  set(target, name, value) {
281
258
  if (!isPropertyKey(name)) return false;
282
259
  const adm = getAdministration(target);
283
- adm.write(name, value);
284
- return true;
260
+ const receiver = arguments[3];
261
+ if (receiver === adm.proxy) {
262
+ return adm.write(name, value);
263
+ }
264
+ return Reflect.set(adm.source, name, value, receiver);
285
265
  },
286
266
  deleteProperty(target, name) {
287
267
  if (!isPropertyKey(name)) return false;
288
268
  const adm = getAdministration(target);
289
- adm.remove(name);
290
- return true;
269
+ return adm.remove(name);
291
270
  },
292
271
  ownKeys(target) {
293
272
  const adm = getAdministration(target);
@@ -296,22 +275,46 @@ class ObjectAdministration extends Administration {
296
275
  adm.atom.reportObserved();
297
276
  });
298
277
  return Reflect.ownKeys(adm.source);
278
+ },
279
+ defineProperty(target, name, descriptor) {
280
+ const adm = getAdministration(target);
281
+ if (adm.isWriting) {
282
+ return Reflect.defineProperty(adm.source, name, descriptor);
283
+ }
284
+ const result = Reflect.defineProperty(adm.source, name, descriptor);
285
+ if (result) {
286
+ batch(() => {
287
+ adm.types.delete(name);
288
+ adm.flushChange();
289
+ adm.keysAtom.reportChanged();
290
+ adm.hasMap.reportChanged(name);
291
+ if ("value" in descriptor) {
292
+ if (isObservable(descriptor.value)) {
293
+ adm.explicitObservables.add(name);
294
+ } else {
295
+ adm.explicitObservables.delete(name);
296
+ }
297
+ adm.valuesMap.reportChanged(name, descriptor.value);
298
+ } else {
299
+ adm.valuesMap.reportChanged(name, void 0);
300
+ }
301
+ });
302
+ }
303
+ return result;
299
304
  }
300
305
  };
301
306
  constructor(source2 = {}) {
302
307
  super(source2);
303
308
  this.keysAtom = createAtom();
304
309
  this.hasMap = new AtomMap(this.atom);
305
- this.valuesMap = new SignalMap();
310
+ this.valuesMap = new SignalMap(this.atom);
306
311
  this.types = /* @__PURE__ */ new Map();
307
312
  }
308
313
  get(key) {
309
314
  return Reflect.get(this.source, key, this.proxy);
310
315
  }
311
316
  set(key, value) {
312
- batch(() => {
313
- Reflect.set(this.source, key, value, this.proxy);
314
- });
317
+ return batch(() => Reflect.set(this.source, key, value, this.proxy));
315
318
  }
316
319
  getComputed(key) {
317
320
  if (!this.computedMap) this.computedMap = /* @__PURE__ */ new Map();
@@ -338,17 +341,6 @@ class ObjectAdministration extends Administration {
338
341
  }
339
342
  return type;
340
343
  }
341
- reportObserveDeep() {
342
- Object.getOwnPropertyNames(this.source).forEach((name) => {
343
- const type = this.getType(name);
344
- if (type === "observable") {
345
- const value = this.source[name];
346
- if (value && typeof value === "object") {
347
- getAdministration(getObservable(value))?.reportObserved();
348
- }
349
- }
350
- });
351
- }
352
344
  reportChanged() {
353
345
  this.types.clear();
354
346
  super.reportChanged();
@@ -363,14 +355,13 @@ class ObjectAdministration extends Administration {
363
355
  }
364
356
  return resolveNode(this.valuesMap.getOrCreate(key, this.source[key]));
365
357
  }
366
- read(key) {
358
+ read(key, receiver = this.proxy) {
367
359
  const type = this.getType(key);
368
360
  if (type === null) {
369
- return this.get(key);
361
+ return Reflect.get(this.source, key, receiver);
370
362
  }
371
363
  switch (type) {
372
364
  case "observable":
373
- case "observableShallow":
374
365
  case "action": {
375
366
  if (key in this.source) {
376
367
  this.valuesMap.reportObserved(key, this.source[key]);
@@ -380,48 +371,66 @@ class ObjectAdministration extends Administration {
380
371
  this.hasMap.reportObserved(key);
381
372
  }
382
373
  if (type === "observable") {
383
- return getObservable(this.get(key));
384
- }
385
- if (type === "observableShallow") {
386
- return getShallowObservable(this.get(key));
374
+ const value = Reflect.get(this.source, key, receiver);
375
+ const shouldWrap = this.explicitObservables.has(key) || isObservable(value);
376
+ if (shouldWrap && value && typeof value === "object" && !Object.isFrozen(value)) {
377
+ const desc = getPropertyDescriptor$1(this.source, key);
378
+ if (desc && !desc.configurable && !desc.writable) {
379
+ return value;
380
+ }
381
+ const existingAdm = getAdministration(value);
382
+ if (existingAdm) {
383
+ return existingAdm.proxy;
384
+ }
385
+ }
386
+ return value;
387
387
  }
388
- return getAction(this.get(key));
388
+ return getAction(
389
+ Reflect.get(this.source, key, receiver)
390
+ );
389
391
  }
390
- case "observableSignal": {
391
- if (key in this.source) {
392
- this.valuesMap.reportObserved(key, this.source[key]);
392
+ case "computed": {
393
+ if (receiver === this.proxy) {
394
+ return this.callComputed(key);
393
395
  }
394
396
  this.atom.reportObserved();
395
- if (this.atom.observing) {
396
- this.hasMap.reportObserved(key);
397
- }
398
- return this.get(key);
399
- }
400
- case "computed": {
401
- return this.callComputed(key);
397
+ return Reflect.get(this.source, key, receiver);
402
398
  }
403
399
  default:
404
400
  throw new Error(`unknown type passed to configure`);
405
401
  }
406
402
  }
403
+ explicitObservables = /* @__PURE__ */ new Set();
407
404
  write(key, newValue) {
408
405
  const type = this.getType(key);
409
406
  if (type === null) {
410
- this.set(key, newValue);
411
- return;
407
+ return this.set(key, newValue);
412
408
  }
413
409
  if (type === "computed") {
414
- batch(() => this.set(key, newValue));
415
- return;
410
+ return batch(() => this.set(key, newValue));
416
411
  }
417
412
  const had = key in this.source;
418
413
  const oldValue = this.get(key);
419
414
  const targetValue = getSource(newValue);
415
+ const oldExplicit = this.explicitObservables.has(key);
416
+ const newExplicit = isObservable(newValue);
417
+ if (newExplicit) {
418
+ this.explicitObservables.add(key);
419
+ } else {
420
+ this.explicitObservables.delete(key);
421
+ }
420
422
  if (type === "action" && typeof newValue !== "function" || type === "observable" && typeof newValue === "function") {
421
423
  this.types.delete(key);
422
424
  }
423
- if (!had || (isObservable(oldValue) ? oldValue !== newValue : oldValue !== targetValue)) {
424
- this.set(key, targetValue);
425
+ const changed = !had || !isObservable(oldValue) && oldExplicit !== newExplicit || (isObservable(oldValue) ? oldValue !== newValue : oldValue !== targetValue);
426
+ if (changed) {
427
+ this.isWriting = true;
428
+ try {
429
+ const result = this.set(key, targetValue);
430
+ if (!result) return false;
431
+ } finally {
432
+ this.isWriting = false;
433
+ }
425
434
  batch(() => {
426
435
  this.flushChange();
427
436
  if (!had) {
@@ -430,7 +439,9 @@ class ObjectAdministration extends Administration {
430
439
  }
431
440
  this.valuesMap.reportChanged(key, newValue);
432
441
  });
442
+ return true;
433
443
  }
444
+ return true;
434
445
  }
435
446
  has(key) {
436
447
  this.atom.reportObserved();
@@ -440,39 +451,27 @@ class ObjectAdministration extends Administration {
440
451
  return key in this.source;
441
452
  }
442
453
  remove(key) {
443
- if (!(key in this.source)) return;
444
- delete this.source[key];
445
- batch(() => {
446
- this.flushChange();
447
- this.valuesMap.reportChanged(key, void 0);
448
- this.keysAtom.reportChanged();
449
- this.hasMap.reportChanged(key);
450
- this.valuesMap.delete(key);
451
- });
454
+ if (!(key in this.source)) return true;
455
+ const result = Reflect.deleteProperty(this.source, key);
456
+ if (result) {
457
+ batch(() => {
458
+ this.flushChange();
459
+ this.valuesMap.reportChanged(key, void 0);
460
+ this.keysAtom.reportChanged();
461
+ this.hasMap.reportChanged(key);
462
+ this.valuesMap.delete(key);
463
+ });
464
+ }
465
+ return result;
452
466
  }
453
467
  }
454
468
  class PreactObjectAdministration extends ObjectAdministration {
455
- static proxyTraps = Object.assign(
456
- {},
457
- ObjectAdministration.proxyTraps,
458
- {
459
- get(target, prop, proxy) {
460
- if (!(prop in target) && (typeof prop === "string" || typeof prop === "number") && String(prop)[0] === "$") {
461
- return getSignal(proxy, prop.substring(1));
462
- }
463
- return ObjectAdministration.proxyTraps.get?.apply(
464
- null,
465
- arguments
466
- );
467
- }
468
- }
469
- );
470
469
  }
471
470
  function createObservedAtom() {
472
471
  let value = 0;
473
472
  const callbacks = /* @__PURE__ */ new Set();
474
473
  let observing = false;
475
- const signal22 = new Signal(value, {
474
+ const signal2 = new Signal(value, {
476
475
  watched() {
477
476
  callbacks.forEach((callback) => callback(true));
478
477
  observing = true;
@@ -483,12 +482,12 @@ function createObservedAtom() {
483
482
  }
484
483
  });
485
484
  return {
486
- node: signal22,
485
+ node: signal2,
487
486
  reportObserved() {
488
- return signal22.value;
487
+ return signal2.value;
489
488
  },
490
489
  reportChanged() {
491
- return signal22.value = ++value;
490
+ return signal2.value = ++value;
492
491
  },
493
492
  get observing() {
494
493
  return observing;
@@ -502,7 +501,7 @@ function createObservedAtom() {
502
501
  };
503
502
  }
504
503
  function createSignal(initialValue) {
505
- const s = signal(initialValue);
504
+ const s = signal$1(initialValue);
506
505
  return {
507
506
  node: s,
508
507
  reportChanged(value) {
@@ -521,7 +520,7 @@ function createSignal(initialValue) {
521
520
  }
522
521
  function createAtom() {
523
522
  let value = 0;
524
- const s = signal(value);
523
+ const s = signal$1(value);
525
524
  return {
526
525
  node: s,
527
526
  reportChanged() {
@@ -604,31 +603,12 @@ function createComputed(fn, context = null) {
604
603
  }
605
604
  };
606
605
  }
607
- function observableImpl(value, context) {
608
- if (context && typeof context === "object" && "kind" in context) {
609
- context.metadata[context.name] = { type: "observable" };
610
- return value;
611
- }
612
- return getObservable(value);
613
- }
614
- function shallowDecorator(value, context) {
615
- if (context && typeof context === "object" && "kind" in context) {
616
- context.metadata[context.name] = { type: "observableShallow" };
617
- return value;
618
- }
619
- throw new Error("observable.shallow can only be used as a decorator");
606
+ function observable(obj) {
607
+ return getObservable(obj);
620
608
  }
621
- function signalDecorator(value, context) {
622
- if (context && typeof context === "object" && "kind" in context) {
623
- context.metadata[context.name] = { type: "observableSignal" };
624
- return value;
625
- }
626
- throw new Error("observable.signal can only be used as a decorator");
609
+ function signal(value) {
610
+ return signal$1(value);
627
611
  }
628
- const observable = Object.assign(observableImpl, {
629
- shallow: shallowDecorator,
630
- signal: signalDecorator
631
- });
632
612
  function computed(value, context) {
633
613
  if (context && typeof context === "object" && "kind" in context) {
634
614
  context.metadata[context.name] = { type: "computed" };
@@ -639,29 +619,24 @@ function computed(value, context) {
639
619
  function source(obj) {
640
620
  return getSource(obj);
641
621
  }
642
- class Observable {
643
- constructor() {
644
- return getObservableClassInstance(this);
645
- }
646
- }
647
622
  function reportChanged(obj) {
648
623
  const adm = getAdministration(obj);
649
624
  adm.reportChanged();
650
625
  return obj;
651
626
  }
652
- function reportObserved(obj, opts) {
627
+ function reportObserved(obj) {
653
628
  const adm = getAdministration(obj);
654
- adm.reportObserved(opts?.deep);
629
+ adm.reportObserved();
655
630
  return obj;
656
631
  }
657
632
  const signalMap = /* @__PURE__ */ new WeakMap();
658
633
  function getSignal(obj, key) {
659
634
  const node = getInternalNode(obj, key);
660
635
  if (node instanceof Signal) {
661
- let signal22 = signalMap.get(node);
662
- if (!signal22) {
663
- signal22 = new Signal();
664
- Object.defineProperties(signal22, {
636
+ let signal2 = signalMap.get(node);
637
+ if (!signal2) {
638
+ signal2 = new Signal();
639
+ Object.defineProperties(signal2, {
665
640
  value: {
666
641
  get() {
667
642
  return obj[key];
@@ -676,9 +651,9 @@ function getSignal(obj, key) {
676
651
  }
677
652
  }
678
653
  });
679
- signalMap.set(node, signal22);
654
+ signalMap.set(node, signal2);
680
655
  }
681
- return signal22;
656
+ return signal2;
682
657
  }
683
658
  return node;
684
659
  }
@@ -687,17 +662,26 @@ class CollectionAdministration extends Administration {
687
662
  hasMap;
688
663
  valuesMap;
689
664
  keysAtom;
665
+ isWeak;
666
+ strongTracking = null;
667
+ weakTracking = null;
690
668
  static proxyTraps = {
691
669
  get(target, name) {
692
670
  const adm = getAdministration(target);
693
- if (name === "size" && "size" in adm.source) {
671
+ if (name === "size" && !adm.isWeak && "size" in adm.source) {
694
672
  return adm.size;
695
673
  }
696
674
  const val = adm.source[name];
697
675
  const collectionMethods = adm.constructor.methods;
698
- if (collectionMethods.hasOwnProperty(name) && typeof val === "function") {
676
+ if (collectionMethods.hasOwnProperty(name)) {
677
+ if (adm.isWeak && !isValidWeakMethod(name)) {
678
+ return val;
679
+ }
699
680
  return collectionMethods[name];
700
681
  }
682
+ if (typeof val === "function") {
683
+ return val;
684
+ }
701
685
  return val;
702
686
  }
703
687
  };
@@ -712,17 +696,71 @@ class CollectionAdministration extends Administration {
712
696
  entries: createMethod$1("entries"),
713
697
  keys: createMethod$1("keys"),
714
698
  values: createMethod$1("values"),
715
- [Symbol.iterator]: createMethod$1(Symbol.iterator)
699
+ [Symbol.iterator]: createMethod$1(Symbol.iterator),
700
+ // New ES methods
701
+ union: createGenericMethod("union"),
702
+ intersection: createGenericMethod("intersection"),
703
+ difference: createGenericMethod("difference"),
704
+ symmetricDifference: createGenericMethod("symmetricDifference"),
705
+ isSubsetOf: createGenericMethod("isSubsetOf"),
706
+ isSupersetOf: createGenericMethod("isSupersetOf"),
707
+ isDisjointFrom: createGenericMethod("isDisjointFrom")
716
708
  };
717
709
  constructor(source2) {
718
710
  super(source2);
719
711
  this.hasMap = new AtomMap(this.atom);
720
- this.valuesMap = new SignalMap();
712
+ this.valuesMap = new SignalMap(this.atom);
721
713
  this.keysAtom = createAtom();
722
714
  this.isMap = typeof source2.set === "function" && typeof source2.get === "function";
715
+ this.isWeak = source2 instanceof WeakMap || source2 instanceof WeakSet;
716
+ if (this.isWeak) {
717
+ this.weakTracking = /* @__PURE__ */ new WeakSet();
718
+ } else {
719
+ this.strongTracking = /* @__PURE__ */ new Set();
720
+ }
721
+ }
722
+ trackExplicitObservable(key) {
723
+ if (this.isWeak) {
724
+ if (isNonPrimitive(key)) {
725
+ this.weakTracking.add(key);
726
+ }
727
+ } else {
728
+ this.strongTracking.add(key);
729
+ }
730
+ }
731
+ untrackExplicitObservable(key) {
732
+ if (this.isWeak) {
733
+ if (isNonPrimitive(key)) {
734
+ this.weakTracking.delete(key);
735
+ }
736
+ } else {
737
+ this.strongTracking.delete(key);
738
+ }
739
+ }
740
+ hasExplicitObservable(key) {
741
+ if (this.isWeak) {
742
+ return isNonPrimitive(key) && this.weakTracking.has(key);
743
+ }
744
+ return this.strongTracking.has(key);
745
+ }
746
+ getProxyVariant(key) {
747
+ if (!isNonPrimitive(key)) return void 0;
748
+ const adm = getAdministration(key);
749
+ if (adm && adm.proxy && adm.proxy !== key) {
750
+ return adm.proxy;
751
+ }
752
+ return void 0;
753
+ }
754
+ getExistingKey(key) {
755
+ const target = getSource(key);
756
+ if (this.source.has(target)) return target;
757
+ if (this.source.has(key)) return key;
758
+ const proxy = this.getProxyVariant(key);
759
+ if (proxy !== void 0 && this.source.has(proxy)) return proxy;
760
+ return void 0;
723
761
  }
724
762
  hasEntry(key) {
725
- return this.source.has(getSource(key)) || this.source.has(key);
763
+ return this.getExistingKey(key) !== void 0;
726
764
  }
727
765
  onCollectionChange(key) {
728
766
  batch(() => {
@@ -731,13 +769,6 @@ class CollectionAdministration extends Administration {
731
769
  this.flushChange();
732
770
  });
733
771
  }
734
- reportObserveDeep() {
735
- this.source.forEach?.((value) => {
736
- if (value && typeof value === "object") {
737
- getAdministration(getObservable(value))?.reportObserved();
738
- }
739
- });
740
- }
741
772
  getNode(key) {
742
773
  if (key == null) {
743
774
  return resolveNode(this.atom);
@@ -758,13 +789,12 @@ class CollectionAdministration extends Administration {
758
789
  this.keysAtom.reportObserved();
759
790
  this.atom.reportObserved();
760
791
  this.source.forEach((value, key) => {
761
- const observed = getObservable(this.isMap ? key : value);
762
- callbackFn.call(
763
- thisArg,
764
- this.isMap ? this.get(key) : observed,
765
- observed,
766
- this.proxy
767
- );
792
+ if (this.isMap) {
793
+ callbackFn.call(thisArg, this.get(key), key, this.proxy);
794
+ return;
795
+ }
796
+ const wrapped = this.wrapSetValue(key);
797
+ callbackFn.call(thisArg, wrapped, wrapped, this.proxy);
768
798
  });
769
799
  }
770
800
  get size() {
@@ -773,43 +803,65 @@ class CollectionAdministration extends Administration {
773
803
  return this.source.size;
774
804
  }
775
805
  add(value) {
806
+ const target = getSource(value);
807
+ if (isObservable(value)) {
808
+ this.trackExplicitObservable(target);
809
+ }
776
810
  if (!this.hasEntry(value)) {
777
- const target = getSource(value);
778
811
  this.source.add(target);
779
812
  this.onCollectionChange(target);
780
813
  }
781
814
  return this;
782
815
  }
783
816
  delete(value) {
784
- if (this.hasEntry(value)) {
785
- const target = getSource(value);
786
- this.source.delete(target);
787
- this.source.delete(value);
788
- this.onCollectionChange(target);
789
- return true;
817
+ const existingKey = this.getExistingKey(value);
818
+ if (existingKey === void 0) return false;
819
+ const target = getSource(value);
820
+ this.untrackExplicitObservable(target);
821
+ this.untrackExplicitObservable(value);
822
+ const proxy = this.getProxyVariant(value);
823
+ if (proxy !== void 0) this.untrackExplicitObservable(proxy);
824
+ this.source.delete(existingKey);
825
+ this.source.delete(target);
826
+ this.source.delete(value);
827
+ if (proxy !== void 0) this.source.delete(proxy);
828
+ this.onCollectionChange(target);
829
+ return true;
830
+ }
831
+ wrapSetValue(value) {
832
+ if (this.hasExplicitObservable(value)) {
833
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
834
+ const existingAdm = getAdministration(value);
835
+ if (existingAdm) return existingAdm.proxy;
836
+ }
790
837
  }
791
- return false;
838
+ return value;
792
839
  }
793
840
  has(value) {
794
841
  this.atom.reportObserved();
795
- if (this.atom.observing || true) {
796
- const target = getSource(value);
797
- this.hasMap.reportObserved(target);
798
- }
842
+ const target = getSource(value);
843
+ this.hasMap.reportObserved(target);
799
844
  return this.hasEntry(value);
800
845
  }
801
846
  entries() {
847
+ this.keysAtom.reportObserved();
848
+ this.atom.reportObserved();
802
849
  const self = this;
803
- const keys = this.keys();
850
+ const iterator = this.source.entries();
804
851
  return {
805
852
  [Symbol.iterator]: function() {
806
853
  return this;
807
854
  },
808
855
  next() {
809
- const { done, value } = keys.next();
856
+ const { done, value } = iterator.next();
857
+ if (done) return { done: true, value: void 0 };
858
+ const [key, val] = value;
810
859
  return {
811
- done,
812
- value: done ? void 0 : [value, self.isMap ? self.get(value) : value]
860
+ done: false,
861
+ value: [
862
+ self.isMap ? key : self.wrapSetValue(key),
863
+ self.isMap ? self.get(key) : self.wrapSetValue(val)
864
+ ]
813
865
  };
814
866
  }
815
867
  };
@@ -817,19 +869,19 @@ class CollectionAdministration extends Administration {
817
869
  keys() {
818
870
  this.keysAtom.reportObserved();
819
871
  this.atom.reportObserved();
820
- let nextIndex = 0;
821
- const observableKeys = Array.from(this.source.keys()).map(
822
- (o) => getObservable(o)
823
- );
872
+ const self = this;
873
+ const iterator = this.source.keys();
824
874
  return {
825
875
  [Symbol.iterator]: function() {
826
876
  return this;
827
877
  },
828
878
  next() {
829
- return nextIndex < observableKeys.length ? {
830
- value: observableKeys[nextIndex++],
831
- done: false
832
- } : { done: true, value: void 0 };
879
+ const { done, value } = iterator.next();
880
+ if (done) return { done: true, value: void 0 };
881
+ return {
882
+ done: false,
883
+ value: self.isMap ? value : self.wrapSetValue(value)
884
+ };
833
885
  }
834
886
  };
835
887
  }
@@ -837,31 +889,54 @@ class CollectionAdministration extends Administration {
837
889
  const targetKey = getSource(key);
838
890
  const sourceMap = this.source;
839
891
  const has = this.has(key);
840
- const value = sourceMap.get(targetKey) ?? sourceMap.get(key);
841
- if (has) {
892
+ if (!has) return void 0;
893
+ const existingKey = this.getExistingKey(key);
894
+ const value = sourceMap.get(existingKey);
895
+ this.valuesMap.reportObserved(targetKey, value);
896
+ if (key !== targetKey) {
842
897
  this.valuesMap.reportObserved(key, value);
843
- if (isShallowObservable(this.proxy)) {
844
- return value;
898
+ }
899
+ const proxyKey = this.getProxyVariant(key);
900
+ if (proxyKey !== void 0 && proxyKey !== key && proxyKey !== targetKey) {
901
+ this.valuesMap.reportObserved(proxyKey, value);
902
+ }
903
+ if (this.hasExplicitObservable(targetKey) || this.hasExplicitObservable(key) || proxyKey !== void 0 && this.hasExplicitObservable(proxyKey)) {
904
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
905
+ const existingAdm = getAdministration(value);
906
+ if (existingAdm) return existingAdm.proxy;
845
907
  }
846
- return getObservable(value);
847
908
  }
848
- return void 0;
909
+ return value;
849
910
  }
850
911
  set(key, value) {
851
912
  const targetKey = getSource(key);
852
913
  const targetValue = getSource(value);
853
914
  const sourceMap = this.source;
854
- const hasKey = this.hasEntry(key);
855
- const oldValue = sourceMap.get(targetKey) ?? sourceMap.get(key);
856
- if (!hasKey || isObservable(oldValue) ? oldValue !== value : oldValue !== targetValue) {
915
+ if (isObservable(value)) {
916
+ this.trackExplicitObservable(targetKey);
917
+ } else {
918
+ this.untrackExplicitObservable(targetKey);
919
+ this.untrackExplicitObservable(key);
920
+ }
921
+ const existingKey = this.getExistingKey(key);
922
+ const hasKey = existingKey !== void 0;
923
+ const oldValue = hasKey ? sourceMap.get(existingKey) : void 0;
924
+ if (!hasKey || (isObservable(oldValue) ? oldValue !== value : oldValue !== targetValue)) {
857
925
  batch(() => {
858
926
  this.flushChange();
859
- if (sourceMap.has(key)) {
860
- sourceMap.set(key, targetValue);
927
+ if (existingKey !== void 0) {
928
+ sourceMap.set(existingKey, targetValue);
861
929
  } else {
862
930
  sourceMap.set(targetKey, targetValue);
863
931
  }
864
- this.valuesMap.reportChanged(key, value);
932
+ this.valuesMap.reportChanged(targetKey, value);
933
+ if (key !== targetKey) {
934
+ this.valuesMap.reportChanged(key, value);
935
+ }
936
+ const proxyKey = this.getProxyVariant(key);
937
+ if (proxyKey !== void 0 && proxyKey !== key && proxyKey !== targetKey) {
938
+ this.valuesMap.reportChanged(proxyKey, value);
939
+ }
865
940
  if (!hasKey) {
866
941
  this.hasMap.reportChanged(targetKey);
867
942
  this.keysAtom.reportChanged();
@@ -871,20 +946,22 @@ class CollectionAdministration extends Administration {
871
946
  return this;
872
947
  }
873
948
  values() {
874
- const self = this;
875
- const keys = this.keys();
949
+ this.keysAtom.reportObserved();
950
+ this.atom.reportObserved();
876
951
  if (!this.isMap) {
877
- return keys;
952
+ return this.keys();
878
953
  }
954
+ const entries = this.entries();
879
955
  return {
880
956
  [Symbol.iterator]: function() {
881
957
  return this;
882
958
  },
883
959
  next() {
884
- const { done, value } = keys.next();
960
+ const { done, value } = entries.next();
961
+ if (done) return { done: true, value: void 0 };
885
962
  return {
886
- done,
887
- value: done ? void 0 : self.get(value)
963
+ done: false,
964
+ value: value[1]
888
965
  };
889
966
  }
890
967
  };
@@ -894,53 +971,197 @@ class CollectionAdministration extends Administration {
894
971
  }
895
972
  [Symbol.toStringTag] = "Set";
896
973
  }
974
+ function isValidWeakMethod(name) {
975
+ const n = name;
976
+ return n === "get" || n === "set" || n === "add" || n === "has" || n === "delete";
977
+ }
978
+ function createGenericMethod(name) {
979
+ return function() {
980
+ const adm = getAdministration(this);
981
+ const method = adm.source[name];
982
+ if (typeof method !== "function") return method;
983
+ if (["union", "intersection", "difference", "symmetricDifference"].includes(
984
+ name
985
+ )) {
986
+ const other = arguments[0];
987
+ const result2 = /* @__PURE__ */ new Set();
988
+ if (name === "union") {
989
+ for (const item of this) result2.add(item);
990
+ for (const item of other) result2.add(item);
991
+ } else if (name === "intersection") {
992
+ for (const item of this) {
993
+ if (other.has(item)) result2.add(item);
994
+ }
995
+ } else if (name === "difference") {
996
+ for (const item of this) {
997
+ if (!other.has(item)) result2.add(item);
998
+ }
999
+ } else if (name === "symmetricDifference") {
1000
+ for (const item of this) {
1001
+ if (!other.has(item)) result2.add(item);
1002
+ }
1003
+ for (const item of other) {
1004
+ if (!this.has(item)) result2.add(item);
1005
+ }
1006
+ }
1007
+ return result2;
1008
+ }
1009
+ adm.keysAtom.reportObserved();
1010
+ adm.atom.reportObserved();
1011
+ const args = new Array(arguments.length);
1012
+ for (let i = 0; i < arguments.length; i++) {
1013
+ const arg = arguments[i];
1014
+ args[i] = getSource(arg);
1015
+ if (isObservable(arg)) {
1016
+ reportObserved(arg);
1017
+ }
1018
+ }
1019
+ const result = method.apply(adm.source, args);
1020
+ if (result === adm.source) return adm.proxy;
1021
+ return result;
1022
+ };
1023
+ }
897
1024
  function createMethod$1(method) {
898
1025
  return function() {
899
1026
  const adm = getAdministration(this);
900
- return adm[method].apply(adm, arguments);
1027
+ const result = adm[method].apply(adm, arguments);
1028
+ if (method === "add" || method === "set") {
1029
+ return this;
1030
+ }
1031
+ return result;
901
1032
  };
902
1033
  }
1034
+ function isArrayIndexKey(key) {
1035
+ if (typeof key === "symbol") return false;
1036
+ const keyStr = String(key);
1037
+ const num = Number(keyStr);
1038
+ return Number.isInteger(num) && num >= 0 && num < 4294967295 && // 2^32 - 1
1039
+ String(num) === keyStr;
1040
+ }
1041
+ function reportConflict() {
1042
+ if (process.env.NODE_ENV !== "production") {
1043
+ throw new Error(
1044
+ "r-state-tree: Cannot assign the same object as both observable and raw source in the same array. The value will be treated as observable."
1045
+ );
1046
+ }
1047
+ }
903
1048
  class ArrayAdministration extends Administration {
904
1049
  valuesMap;
905
1050
  keysAtom;
1051
+ /**
1052
+ * Parent-based ownership tracking: sources assigned as observable.
1053
+ * Unlike index-based tracking, this doesn't require updates on reorder ops.
1054
+ */
1055
+ observableSources = /* @__PURE__ */ new WeakSet();
1056
+ rawSources = /* @__PURE__ */ new WeakSet();
1057
+ /**
1058
+ * Track a value being assigned to this array.
1059
+ * Detects conflicts if same source is assigned as both observable and raw.
1060
+ */
1061
+ trackValue(value) {
1062
+ if (value && typeof value === "object") {
1063
+ const source2 = getSource(value);
1064
+ if (isObservable(value)) {
1065
+ if (this.rawSources.has(source2)) {
1066
+ reportConflict();
1067
+ }
1068
+ this.observableSources.add(source2);
1069
+ } else {
1070
+ if (this.observableSources.has(source2)) {
1071
+ reportConflict();
1072
+ } else {
1073
+ this.rawSources.add(source2);
1074
+ }
1075
+ }
1076
+ }
1077
+ }
906
1078
  static proxyTraps = {
907
- get(target, name) {
1079
+ get(target, name, receiver) {
908
1080
  const adm = getAdministration(target);
909
1081
  if (name === "length") {
910
1082
  return adm.getArrayLength();
911
1083
  }
912
- if (typeof name === "number") {
913
- return adm.get(name);
914
- }
915
- if (typeof name === "string" && String(parseInt(name)) === name) {
916
- return adm.get(parseInt(name));
1084
+ if (isArrayIndexKey(name)) {
1085
+ return adm.get(Number(name));
917
1086
  }
918
1087
  const arrayMethods = adm.constructor.methods;
919
1088
  if (arrayMethods.hasOwnProperty(name)) {
920
1089
  return arrayMethods[name];
921
1090
  }
922
- return adm.source[name];
1091
+ return Reflect.get(adm.source, name, receiver);
923
1092
  },
924
1093
  set(target, name, value) {
925
1094
  const adm = getAdministration(target);
926
1095
  if (name === "length") {
927
- adm.setArrayLength(value);
928
- } else if (typeof name === "number") {
929
- adm.set(name, value);
930
- } else if (typeof name === "string" && String(parseInt(name)) === name) {
931
- adm.set(parseInt(name), value);
1096
+ return adm.setArrayLength(value);
1097
+ } else if (isArrayIndexKey(name)) {
1098
+ return adm.set(Number(name), value);
932
1099
  } else {
933
- adm.source[name] = value;
1100
+ return Reflect.set(adm.source, name, value, arguments[3]);
934
1101
  }
935
- return true;
1102
+ },
1103
+ defineProperty(target, name, descriptor) {
1104
+ const adm = getAdministration(target);
1105
+ const result = Reflect.defineProperty(adm.source, name, descriptor);
1106
+ if (result) {
1107
+ batch(() => {
1108
+ adm.flushChange();
1109
+ if (name === "length") {
1110
+ adm.keysAtom.reportChanged();
1111
+ adm.atom.reportChanged();
1112
+ } else if (isArrayIndexKey(name)) {
1113
+ const index = Number(name);
1114
+ adm.keysAtom.reportChanged();
1115
+ adm.onArrayChanged(false, index, 1);
1116
+ } else {
1117
+ adm.atom.reportChanged();
1118
+ }
1119
+ });
1120
+ }
1121
+ return result;
1122
+ },
1123
+ deleteProperty(target, name) {
1124
+ const adm = getAdministration(target);
1125
+ const isIndex = isArrayIndexKey(name);
1126
+ const had = name in adm.source;
1127
+ const result = Reflect.deleteProperty(adm.source, name);
1128
+ if (result && had && isIndex) {
1129
+ const index = Number(name);
1130
+ adm.onArrayChanged(true, index, 1);
1131
+ }
1132
+ return result;
1133
+ },
1134
+ ownKeys(target) {
1135
+ const adm = getAdministration(target);
1136
+ batch(() => {
1137
+ adm.keysAtom.reportObserved();
1138
+ adm.atom.reportObserved();
1139
+ });
1140
+ return Reflect.ownKeys(adm.source);
1141
+ },
1142
+ has(target, name) {
1143
+ const adm = getAdministration(target);
1144
+ if (isArrayIndexKey(name)) {
1145
+ const index = Number(name);
1146
+ adm.atom.reportObserved();
1147
+ adm.valuesMap.reportObserved(index, adm.source[index]);
1148
+ return index in adm.source;
1149
+ }
1150
+ return Reflect.has(adm.source, name);
936
1151
  }
937
1152
  };
938
1153
  static methods = {
939
1154
  fill(value, start, end) {
940
1155
  const adm = getAdministration(this);
941
- const oldLength = adm.source.length;
942
- adm.source.fill(value, start, end);
943
- adm.onArrayChanged(oldLength !== adm.source.length, start, end);
1156
+ adm.trackValue(value);
1157
+ const targetValue = getSource(value);
1158
+ adm.source.fill(targetValue, start, end);
1159
+ const length = adm.source.length;
1160
+ const from = start == null ? 0 : start < 0 ? Math.max(length + start, 0) : start;
1161
+ const to = end == null ? length : end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
1162
+ if (from < to) {
1163
+ adm.onArrayChanged(false, from, to - from);
1164
+ }
944
1165
  return this;
945
1166
  },
946
1167
  splice(index, deleteCount, ...newItems) {
@@ -982,10 +1203,20 @@ class ArrayAdministration extends Administration {
982
1203
  },
983
1204
  sort(compareFn) {
984
1205
  const adm = getAdministration(this);
985
- adm.onArrayChanged();
986
- adm.source.sort(
987
- compareFn && ((a, b) => compareFn(getObservable(a), getObservable(b)))
988
- );
1206
+ const pairs = adm.source.map((stored, i) => ({
1207
+ value: this[i],
1208
+ stored
1209
+ }));
1210
+ const comparator = compareFn ?? ((a, b) => {
1211
+ const as = String(a);
1212
+ const bs = String(b);
1213
+ return as < bs ? -1 : as > bs ? 1 : 0;
1214
+ });
1215
+ pairs.sort((a, b) => comparator(a.value, b.value));
1216
+ for (let i = 0; i < pairs.length; i++) {
1217
+ adm.source[i] = pairs[i].stored;
1218
+ }
1219
+ adm.onArrayChanged(false, 0, adm.source.length);
989
1220
  return this;
990
1221
  },
991
1222
  join: createStringMethod("join"),
@@ -997,7 +1228,12 @@ class ArrayAdministration extends Administration {
997
1228
  slice: createCopyMethod("slice"),
998
1229
  concat: createCopyMethod("concat"),
999
1230
  flat: createCopyMethod("flat"),
1000
- copyWithin: createCopyMethod("copyWithin"),
1231
+ copyWithin(target, start, end) {
1232
+ const adm = getAdministration(this);
1233
+ adm.source.copyWithin(target, start, end);
1234
+ adm.onArrayChanged(false, 0, adm.source.length);
1235
+ return this;
1236
+ },
1001
1237
  every: createMapMethod("every"),
1002
1238
  forEach: createMapMethod("forEach"),
1003
1239
  map: createMapMethod("map"),
@@ -1011,17 +1247,9 @@ class ArrayAdministration extends Administration {
1011
1247
  };
1012
1248
  constructor(source2 = []) {
1013
1249
  super(source2);
1014
- this.valuesMap = new SignalMap();
1250
+ this.valuesMap = new SignalMap(this.atom);
1015
1251
  this.keysAtom = createAtom();
1016
1252
  }
1017
- reportObserveDeep() {
1018
- for (let i = 0; i < this.source.length; i++) {
1019
- const value = this.source[i];
1020
- if (value && typeof value === "object") {
1021
- getAdministration(getObservable(value))?.reportObserved();
1022
- }
1023
- }
1024
- }
1025
1253
  getNode(key) {
1026
1254
  if (key == null) {
1027
1255
  return this.atom;
@@ -1031,45 +1259,69 @@ class ArrayAdministration extends Administration {
1031
1259
  get(index) {
1032
1260
  this.atom.reportObserved();
1033
1261
  this.valuesMap.reportObserved(index, this.source[index]);
1034
- if (isShallowObservable(this.proxy)) {
1035
- return this.source[index];
1262
+ return this._getEffectiveValue(index);
1263
+ }
1264
+ _getEffectiveValue(index) {
1265
+ const value = this.source[index];
1266
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
1267
+ if (this.observableSources.has(value)) {
1268
+ const adm = getAdministration(value);
1269
+ if (adm.proxy !== value) {
1270
+ const desc = Object.getOwnPropertyDescriptor(this.source, index);
1271
+ if (desc && !desc.configurable && !desc.writable) {
1272
+ if (process.env.NODE_ENV !== "production") {
1273
+ console.warn(
1274
+ `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.`
1275
+ );
1276
+ }
1277
+ return value;
1278
+ }
1279
+ }
1280
+ return adm.proxy;
1281
+ }
1036
1282
  }
1037
- return getObservable(this.source[index]);
1283
+ return value;
1038
1284
  }
1039
1285
  set(index, newValue) {
1040
1286
  const values = this.source;
1041
1287
  const targetValue = getSource(newValue);
1042
- if (index < values.length) {
1288
+ const oldLength = values.length;
1289
+ this.trackValue(newValue);
1290
+ let changed = true;
1291
+ if (index < oldLength) {
1043
1292
  const oldValue = values[index];
1044
- const changed = isObservable(oldValue) ? newValue !== oldValue : targetValue !== oldValue;
1045
- if (changed) {
1046
- values[index] = targetValue;
1047
- this.onArrayChanged(false, index, 1);
1048
- }
1049
- } else if (index === values.length) {
1050
- this.spliceWithArray(index, 0, [newValue]);
1051
- } else {
1052
- throw new Error(
1053
- `Index out of bounds, ${index} is larger than ${values.length}`
1054
- );
1293
+ changed = targetValue !== oldValue;
1055
1294
  }
1295
+ if (!changed) return true;
1296
+ const result = Reflect.set(values, index, targetValue);
1297
+ if (!result) return false;
1298
+ const newLength = values.length;
1299
+ const lengthChanged = newLength !== oldLength;
1300
+ this.onArrayChanged(lengthChanged, index, 1);
1301
+ return true;
1056
1302
  }
1057
1303
  getArrayLength() {
1058
1304
  this.atom.reportObserved();
1059
1305
  this.keysAtom.reportObserved();
1060
1306
  return this.source.length;
1061
1307
  }
1062
- setArrayLength(newLength) {
1063
- if (typeof newLength !== "number" || newLength < 0)
1064
- throw new Error("Out of range: " + newLength);
1308
+ setArrayLength(input) {
1309
+ const num = Number(input);
1310
+ const coerced = num >>> 0;
1311
+ if (coerced !== num) {
1312
+ throw new RangeError("Invalid array length");
1313
+ }
1314
+ const newLength = coerced;
1065
1315
  const currentLength = this.source.length;
1066
- if (newLength === currentLength) return;
1067
- else if (newLength > currentLength) {
1068
- const newItems = new Array(newLength - currentLength);
1069
- for (let i = 0; i < newLength - currentLength; i++)
1070
- newItems[i] = void 0;
1071
- this.spliceWithArray(currentLength, 0, newItems);
1072
- } else this.spliceWithArray(newLength, currentLength - newLength);
1316
+ if (newLength === currentLength) return true;
1317
+ const result = Reflect.set(this.source, "length", newLength);
1318
+ if (!result) return false;
1319
+ if (newLength < currentLength) {
1320
+ this.onArrayChanged(true, newLength, currentLength - newLength);
1321
+ } else {
1322
+ this.onArrayChanged(true, currentLength, newLength - currentLength);
1323
+ }
1324
+ return true;
1073
1325
  }
1074
1326
  spliceWithArray(index, deleteCount, newItems) {
1075
1327
  const length = this.source.length;
@@ -1077,6 +1329,7 @@ class ArrayAdministration extends Administration {
1077
1329
  if (newItems) {
1078
1330
  for (let i = 0; i < newItems.length; i++) {
1079
1331
  newTargetItems[i] = getSource(newItems[i]);
1332
+ this.trackValue(newItems[i]);
1080
1333
  }
1081
1334
  }
1082
1335
  if (index === void 0) index = 0;
@@ -1085,15 +1338,18 @@ class ArrayAdministration extends Administration {
1085
1338
  if (arguments.length === 1) deleteCount = length - index;
1086
1339
  else if (deleteCount === void 0 || deleteCount === null) deleteCount = 0;
1087
1340
  else deleteCount = Math.max(0, Math.min(deleteCount, length - index));
1088
- const res = this.spliceItemsIntoValues(index, deleteCount, newTargetItems);
1341
+ const removedItems = [];
1342
+ for (let i = index; i < index + deleteCount; i++) {
1343
+ removedItems.push(this._getEffectiveValue(i));
1344
+ }
1345
+ this.spliceItemsIntoValues(index, deleteCount, newTargetItems);
1089
1346
  if (deleteCount !== 0 || newTargetItems.length !== 0) {
1090
- this.onArrayChanged(
1091
- length !== this.source.length,
1092
- index,
1093
- Math.max(deleteCount ?? 0, newItems?.length ?? 0)
1094
- );
1347
+ const shift = (newItems?.length ?? 0) - deleteCount;
1348
+ const reindexing = shift !== 0 && index + deleteCount < length;
1349
+ const count = reindexing ? Number.POSITIVE_INFINITY : Math.max(deleteCount ?? 0, newItems?.length ?? 0);
1350
+ this.onArrayChanged(length !== this.source.length, index, count);
1095
1351
  }
1096
- return res;
1352
+ return removedItems;
1097
1353
  }
1098
1354
  spliceItemsIntoValues(index, deleteCount, newItems) {
1099
1355
  return this.source.splice.apply(
@@ -1108,9 +1364,16 @@ class ArrayAdministration extends Administration {
1108
1364
  }
1109
1365
  if (index == null) {
1110
1366
  this.atom.reportChanged();
1111
- } else {
1112
- for (let i = index; i < index + count; i++) {
1113
- this.valuesMap.reportChanged(i, this.source[i]);
1367
+ } else if (count !== void 0 && count > 0) {
1368
+ const observedKeys = this.valuesMap.keys();
1369
+ const end = index + count;
1370
+ for (const key of observedKeys) {
1371
+ if (typeof key === "number" && key >= index && key < end) {
1372
+ const node = this.valuesMap.get(key);
1373
+ if (node) {
1374
+ node.reportChanged(this._getEffectiveValue(key));
1375
+ }
1376
+ }
1114
1377
  }
1115
1378
  }
1116
1379
  this.flushChange();
@@ -1126,7 +1389,7 @@ function createMethod(method, func) {
1126
1389
  function createStringMethod(method) {
1127
1390
  return createMethod(method, function() {
1128
1391
  const adm = getAdministration(this);
1129
- adm.reportObserved(false);
1392
+ adm.reportObserved();
1130
1393
  const sourceArr = getSource(this);
1131
1394
  return sourceArr[method].apply(sourceArr, arguments);
1132
1395
  });
@@ -1134,7 +1397,7 @@ function createStringMethod(method) {
1134
1397
  function createSearchMethod(method) {
1135
1398
  return createMethod(method, function() {
1136
1399
  const adm = getAdministration(this);
1137
- adm.reportObserved(false);
1400
+ adm.reportObserved();
1138
1401
  const target = arguments[0];
1139
1402
  const source2 = getSource(target);
1140
1403
  const sourceArr = getSource(this);
@@ -1150,10 +1413,38 @@ function createSearchMethod(method) {
1150
1413
  function createCopyMethod(method) {
1151
1414
  return createMethod(method, function() {
1152
1415
  const adm = getAdministration(this);
1153
- adm.reportObserved(false);
1154
- return getObservable(
1155
- adm.source[method].apply(adm.source, arguments)
1156
- );
1416
+ adm.reportObserved();
1417
+ const observedInput = [];
1418
+ observedInput.length = adm.source.length;
1419
+ const keys = Object.keys(adm.source);
1420
+ for (let i = 0; i < keys.length; i++) {
1421
+ const key = keys[i];
1422
+ const idx = Number(key);
1423
+ if (!Number.isNaN(idx)) {
1424
+ observedInput[idx] = this[idx];
1425
+ }
1426
+ }
1427
+ const args = Array.from(arguments);
1428
+ if (method === "concat") {
1429
+ for (let i = 0; i < args.length; i++) {
1430
+ const arg = args[i];
1431
+ if (Array.isArray(arg) && isObservable(arg)) {
1432
+ const argAdm = getAdministration(arg);
1433
+ const argObserved = [];
1434
+ argObserved.length = argAdm.source.length;
1435
+ const argKeys = Object.keys(argAdm.source);
1436
+ for (let j = 0; j < argKeys.length; j++) {
1437
+ const argKey = argKeys[j];
1438
+ const argIdx = Number(argKey);
1439
+ if (!Number.isNaN(argIdx)) {
1440
+ argObserved[argIdx] = arg[argIdx];
1441
+ }
1442
+ }
1443
+ args[i] = argObserved;
1444
+ }
1445
+ }
1446
+ }
1447
+ return Array.prototype[method].apply(observedInput, args);
1157
1448
  });
1158
1449
  }
1159
1450
  function createMapMethod(method) {
@@ -1161,14 +1452,9 @@ function createMapMethod(method) {
1161
1452
  method,
1162
1453
  function(callback, thisArg) {
1163
1454
  const adm = getAdministration(this);
1164
- adm.reportObserved(false);
1165
- return adm.source[method]((element, index) => {
1166
- return callback.call(
1167
- thisArg,
1168
- element && typeof element === "object" ? getObservable(element) : element,
1169
- index,
1170
- this
1171
- );
1455
+ adm.reportObserved();
1456
+ return adm.source[method]((_element, index) => {
1457
+ return callback.call(thisArg, this[index], index, this);
1172
1458
  });
1173
1459
  }
1174
1460
  );
@@ -1178,28 +1464,17 @@ function createFilterMethod(method) {
1178
1464
  method,
1179
1465
  function(callback, thisArg) {
1180
1466
  const adm = getAdministration(this);
1181
- adm.reportObserved(false);
1182
- return getObservable(
1183
- adm.source[method]((element, index) => {
1184
- return callback.call(
1185
- thisArg,
1186
- element && typeof element === "object" ? getObservable(element) : element,
1187
- index,
1188
- this
1189
- );
1190
- })
1191
- );
1467
+ adm.reportObserved();
1468
+ return adm.source[method]((_element, index) => {
1469
+ return callback.call(thisArg, this[index], index, this);
1470
+ });
1192
1471
  }
1193
1472
  );
1194
1473
  }
1195
1474
  function createReduceMethod(method) {
1196
1475
  return createMethod(method, function() {
1197
1476
  const adm = getAdministration(this);
1198
- adm.reportObserved(false);
1199
- const callback = arguments[0];
1200
- arguments[0] = (accumulator, currentValue, index) => {
1201
- return callback(accumulator, getObservable(currentValue), index, this);
1202
- };
1477
+ adm.reportObserved();
1203
1478
  return adm.source[method].apply(adm.source, arguments);
1204
1479
  });
1205
1480
  }
@@ -1226,6 +1501,7 @@ function addDateSetMethod(method) {
1226
1501
  const adm = getAdministration(this);
1227
1502
  const res = adm.source[method].apply(adm.source, arguments);
1228
1503
  adm.atom.reportChanged();
1504
+ adm.flushChange();
1229
1505
  return res;
1230
1506
  };
1231
1507
  }
@@ -1261,9 +1537,15 @@ function getAction(fn) {
1261
1537
  }
1262
1538
  function getObservableClassInstance(value) {
1263
1539
  const adm = new PreactObjectAdministration(value);
1540
+ administrationMap.set(adm.proxy, adm);
1264
1541
  administrationMap.set(adm.source, adm);
1265
1542
  return adm.proxy;
1266
1543
  }
1544
+ class Observable {
1545
+ constructor() {
1546
+ return getObservableClassInstance(this);
1547
+ }
1548
+ }
1267
1549
  function createObservableWithCustomAdministration(value, Adm) {
1268
1550
  const adm = new Adm(value);
1269
1551
  administrationMap.set(adm.proxy, adm);
@@ -1271,40 +1553,6 @@ function createObservableWithCustomAdministration(value, Adm) {
1271
1553
  return adm.proxy;
1272
1554
  }
1273
1555
  function getObservable(value) {
1274
- if (!value) {
1275
- return value;
1276
- }
1277
- const adm = getAdministration(value);
1278
- if (adm) {
1279
- return adm.proxy;
1280
- }
1281
- if ((typeof value === "object" || typeof value === "function") && !Object.isFrozen(value)) {
1282
- const obj = value;
1283
- let Adm = PreactObjectAdministration;
1284
- if (Array.isArray(obj)) {
1285
- Adm = ArrayAdministration;
1286
- } else if (obj instanceof Map || obj instanceof WeakMap) {
1287
- Adm = CollectionAdministration;
1288
- } else if (obj instanceof Set || obj instanceof WeakSet) {
1289
- Adm = CollectionAdministration;
1290
- } else if (obj instanceof Date) {
1291
- Adm = DateAdministration;
1292
- } else if (!isPlainObject(value)) {
1293
- return value;
1294
- }
1295
- const adm2 = new Adm(obj);
1296
- administrationMap.set(adm2.proxy, adm2);
1297
- administrationMap.set(adm2.source, adm2);
1298
- return adm2.proxy;
1299
- }
1300
- return value;
1301
- }
1302
- const shallowObservables = /* @__PURE__ */ new WeakSet();
1303
- function isShallowObservable(obj) {
1304
- if (!obj || typeof obj !== "object") return false;
1305
- return shallowObservables.has(obj);
1306
- }
1307
- function getShallowObservable(value) {
1308
1556
  if (!value) {
1309
1557
  return value;
1310
1558
  }
@@ -1312,23 +1560,43 @@ function getShallowObservable(value) {
1312
1560
  if (existingAdm) {
1313
1561
  return existingAdm.proxy;
1314
1562
  }
1315
- if ((typeof value === "object" || typeof value === "function") && !Object.isFrozen(value)) {
1563
+ if (typeof value === "function") {
1564
+ if (process.env.NODE_ENV !== "production") {
1565
+ console.warn(
1566
+ `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.`
1567
+ );
1568
+ }
1569
+ return value;
1570
+ }
1571
+ if (typeof value === "object") {
1316
1572
  const obj = value;
1317
1573
  let Adm = null;
1318
- if (Array.isArray(obj)) {
1319
- Adm = ArrayAdministration;
1320
- } else if (obj instanceof Map || obj instanceof WeakMap) {
1574
+ if (obj instanceof Map || obj instanceof WeakMap) {
1321
1575
  Adm = CollectionAdministration;
1322
1576
  } else if (obj instanceof Set || obj instanceof WeakSet) {
1323
1577
  Adm = CollectionAdministration;
1578
+ } else if (obj instanceof Date) {
1579
+ Adm = DateAdministration;
1580
+ } else if (!Object.isFrozen(obj)) {
1581
+ if (Array.isArray(obj)) {
1582
+ Adm = ArrayAdministration;
1583
+ } else if (isPlainObject(obj)) {
1584
+ Adm = PreactObjectAdministration;
1585
+ }
1324
1586
  }
1325
1587
  if (Adm) {
1326
1588
  const adm = new Adm(obj);
1327
1589
  administrationMap.set(adm.proxy, adm);
1328
1590
  administrationMap.set(adm.source, adm);
1329
- shallowObservables.add(adm.proxy);
1330
1591
  return adm.proxy;
1331
1592
  }
1593
+ if (process.env.NODE_ENV !== "production" && !Object.isFrozen(obj)) {
1594
+ const proto = Object.getPrototypeOf(obj);
1595
+ const typeName = proto?.constructor?.name && proto.constructor.name !== "Object" ? `instance of ${proto.constructor.name}` : "non-plain object";
1596
+ console.warn(
1597
+ `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'.`
1598
+ );
1599
+ }
1332
1600
  }
1333
1601
  return value;
1334
1602
  }
@@ -1357,19 +1625,77 @@ function getPropertyDescriptor(obj, key) {
1357
1625
  }
1358
1626
  return void 0;
1359
1627
  }
1360
- function clone(val) {
1361
- if (Array.isArray(val)) {
1362
- return val.map((v) => clone(v));
1363
- } else if (val && typeof val === "object") {
1364
- const keys = Object.keys(val);
1365
- const cloned = {};
1366
- for (let i = 0; i < keys.length; i++) {
1367
- const key = keys[i];
1368
- cloned[key] = clone(val[key]);
1628
+ function clone(val, path = "") {
1629
+ if (val === null || val === void 0) {
1630
+ return val;
1631
+ }
1632
+ if (typeof val !== "object") {
1633
+ if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
1634
+ return val;
1369
1635
  }
1370
- return cloned;
1636
+ const atPath = path ? ` at path "${path}"` : "";
1637
+ if (typeof val === "bigint") {
1638
+ throw new Error(
1639
+ `r-state-tree: snapshots do not support bigint${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1640
+ );
1641
+ }
1642
+ if (typeof val === "symbol") {
1643
+ throw new Error(
1644
+ `r-state-tree: snapshots do not support symbol${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1645
+ );
1646
+ }
1647
+ if (typeof val === "function") {
1648
+ throw new Error(
1649
+ `r-state-tree: snapshots do not support function${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1650
+ );
1651
+ }
1652
+ throw new Error(
1653
+ `r-state-tree: snapshots do not support ${typeof val}${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1654
+ );
1655
+ }
1656
+ if (val instanceof Signal) {
1657
+ return clone(
1658
+ val.value,
1659
+ path
1660
+ );
1661
+ }
1662
+ if (val instanceof Date) {
1663
+ return val.toISOString();
1664
+ }
1665
+ if (Array.isArray(val)) {
1666
+ return val.map(
1667
+ (v, i) => clone(v, path ? `${path}[${i}]` : `[${i}]`)
1668
+ );
1371
1669
  }
1372
- return val;
1670
+ if (!isPlainObject(val)) {
1671
+ const typeName = getTypeName(val);
1672
+ const atPath = path ? ` at path "${path}"` : "";
1673
+ throw new Error(
1674
+ `r-state-tree: snapshots do not support ${typeName}${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
1675
+ );
1676
+ }
1677
+ const keys = Object.keys(val);
1678
+ const cloned = {};
1679
+ for (let i = 0; i < keys.length; i++) {
1680
+ const key = keys[i];
1681
+ const keyPath = path ? `${path}.${key}` : key;
1682
+ cloned[key] = clone(val[key], keyPath);
1683
+ }
1684
+ return cloned;
1685
+ }
1686
+ function getTypeName(val) {
1687
+ if (val instanceof Map) return "Map";
1688
+ if (val instanceof Set) return "Set";
1689
+ if (val instanceof WeakMap) return "WeakMap";
1690
+ if (val instanceof WeakSet) return "WeakSet";
1691
+ if (val instanceof RegExp) return "RegExp";
1692
+ if (val instanceof Error) return "Error";
1693
+ if (val instanceof Promise) return "Promise";
1694
+ const proto = Object.getPrototypeOf(val);
1695
+ if (proto?.constructor?.name && proto.constructor.name !== "Object") {
1696
+ return `class instance (${proto.constructor.name})`;
1697
+ }
1698
+ return "non-plain object";
1373
1699
  }
1374
1700
  function getDiff(o1, o2, getConfig) {
1375
1701
  const config = getConfig(o2);
@@ -1442,7 +1768,9 @@ function updateProps(props, newProps) {
1442
1768
  }
1443
1769
  });
1444
1770
  if (newProps.models) {
1445
- if (!props.models) props.models = {};
1771
+ if (!props.models || !isObservable(props.models)) {
1772
+ props.models = getObservable(props.models || {});
1773
+ }
1446
1774
  Object.assign(props.models, newProps.models);
1447
1775
  }
1448
1776
  });
@@ -1666,7 +1994,9 @@ class StoreAdministration extends PreactObjectAdministration {
1666
1994
  }
1667
1995
  }
1668
1996
  getModelRef(name) {
1669
- return this.proxy.props.models?.[name] ?? null;
1997
+ const models = this.proxy.props.models;
1998
+ const ref = models?.[name] ?? null;
1999
+ return ref;
1670
2000
  }
1671
2001
  isRoot() {
1672
2002
  return !this.parent;
@@ -2004,11 +2334,12 @@ class ObservableListener {
2004
2334
  class ChildModelsAdministration extends ArrayAdministration {
2005
2335
  set(index, newValue) {
2006
2336
  return batch(() => {
2007
- super.set(index, newValue);
2337
+ const result = super.set(index, newValue);
2008
2338
  const sourceValue = getSource(newValue);
2009
2339
  if (this.source[index] !== sourceValue) {
2010
2340
  notifyArrayUpdate(this.proxy, index, this.source[index], sourceValue);
2011
2341
  }
2342
+ return result;
2012
2343
  });
2013
2344
  }
2014
2345
  spliceWithArray(index, deleteCount, newItems) {
@@ -2126,9 +2457,7 @@ class ModelAdministration extends PreactObjectAdministration {
2126
2457
  adm.setId(name, value);
2127
2458
  break;
2128
2459
  }
2129
- case ModelCfgTypes.state:
2130
- case ModelCfgTypes.stateShallow:
2131
- case ModelCfgTypes.stateSignal: {
2460
+ case ModelCfgTypes.state: {
2132
2461
  adm.setState(name, value);
2133
2462
  break;
2134
2463
  }
@@ -2198,12 +2527,14 @@ class ModelAdministration extends PreactObjectAdministration {
2198
2527
  setState(name, value) {
2199
2528
  const oldValue = this.source[name];
2200
2529
  if (value !== oldValue) {
2201
- PreactObjectAdministration.proxyTraps.set(
2202
- this.source,
2203
- name,
2204
- value,
2205
- this.proxy
2206
- );
2530
+ batch(() => {
2531
+ PreactObjectAdministration.proxyTraps.set(
2532
+ this.source,
2533
+ name,
2534
+ value,
2535
+ this.proxy
2536
+ );
2537
+ });
2207
2538
  }
2208
2539
  }
2209
2540
  setId(name, v) {
@@ -2257,9 +2588,9 @@ class ModelAdministration extends PreactObjectAdministration {
2257
2588
  getModelAdm(currentValue).detach();
2258
2589
  } else if (Array.isArray(currentValue)) {
2259
2590
  const oldModels = currentValue;
2260
- const newModelSet = new Set(newModels);
2591
+ const newModelSet = new Set(newModels.map((m) => getSource(m)));
2261
2592
  oldModels.forEach(
2262
- (child2) => newModelSet.has(child2) || getModelAdm(child2).detach()
2593
+ (child2) => newModelSet.has(getSource(child2)) || getModelAdm(child2).detach()
2263
2594
  );
2264
2595
  this.modelsTraceUnsub.get(name)?.();
2265
2596
  }
@@ -2282,8 +2613,8 @@ class ModelAdministration extends PreactObjectAdministration {
2282
2613
  })
2283
2614
  );
2284
2615
  newModels.forEach((child2) => {
2285
- const oldModelSet = Array.isArray(currentValue) ? new Set(currentValue) : /* @__PURE__ */ new Set();
2286
- if (!oldModelSet.has(child2)) {
2616
+ const oldModelSet = Array.isArray(currentValue) ? new Set(currentValue.map((m) => getSource(m))) : /* @__PURE__ */ new Set();
2617
+ if (!oldModelSet.has(getSource(child2))) {
2287
2618
  const internalModel = getModelAdm(child2);
2288
2619
  internalModel.attach(this, name);
2289
2620
  }
@@ -2397,11 +2728,12 @@ class ModelAdministration extends PreactObjectAdministration {
2397
2728
  toJSON() {
2398
2729
  return Object.keys(this.configuration).reduce((json, key) => {
2399
2730
  switch (this.configuration[key].type) {
2400
- case ModelCfgTypes.state:
2401
- case ModelCfgTypes.stateShallow:
2402
- case ModelCfgTypes.stateSignal:
2731
+ case ModelCfgTypes.state: {
2732
+ json[key] = clone(this.proxy[key], key);
2733
+ break;
2734
+ }
2403
2735
  case ModelCfgTypes.id:
2404
- json[key] = clone(getSource(this.proxy[key]));
2736
+ json[key] = clone(getSource(this.proxy[key]), key);
2405
2737
  break;
2406
2738
  case ModelCfgTypes.modelRef:
2407
2739
  const model2 = this.proxy[key];
@@ -2465,8 +2797,6 @@ class ModelAdministration extends PreactObjectAdministration {
2465
2797
  const value = snapshot[key];
2466
2798
  switch (type) {
2467
2799
  case ModelCfgTypes.state:
2468
- case ModelCfgTypes.stateShallow:
2469
- case ModelCfgTypes.stateSignal:
2470
2800
  this.proxy[key] = value;
2471
2801
  break;
2472
2802
  case ModelCfgTypes.modelRef:
@@ -2660,6 +2990,73 @@ function createContext(defaultValue) {
2660
2990
  }
2661
2991
  };
2662
2992
  }
2993
+ function toObservableTree(value) {
2994
+ return toObservableTreeInternal(value, /* @__PURE__ */ new Set(), "");
2995
+ }
2996
+ function buildPath(currentPath, key) {
2997
+ if (typeof key === "number") {
2998
+ return `${currentPath}[${key}]`;
2999
+ }
3000
+ return currentPath ? `${currentPath}.${key}` : key;
3001
+ }
3002
+ function toObservableTreeInternal(value, ancestorPath, path) {
3003
+ if (value === null || typeof value !== "object") {
3004
+ return value;
3005
+ }
3006
+ if (Array.isArray(value)) {
3007
+ if (ancestorPath.has(value)) {
3008
+ throw new Error(
3009
+ `r-state-tree: toObservableTree does not support circular references (cycle detected at path "${path}")`
3010
+ );
3011
+ }
3012
+ ancestorPath.add(value);
3013
+ const toWrap = [];
3014
+ for (let i = 0; i < value.length; i++) {
3015
+ const element = value[i];
3016
+ if (Array.isArray(element) || isPlainObject(element)) {
3017
+ toWrap.push({ index: i, element });
3018
+ }
3019
+ }
3020
+ const proxy = observable(value);
3021
+ for (const { index, element } of toWrap) {
3022
+ proxy[index] = toObservableTreeInternal(
3023
+ element,
3024
+ ancestorPath,
3025
+ buildPath(path, index)
3026
+ );
3027
+ }
3028
+ ancestorPath.delete(value);
3029
+ return proxy;
3030
+ }
3031
+ if (isPlainObject(value)) {
3032
+ if (ancestorPath.has(value)) {
3033
+ throw new Error(
3034
+ `r-state-tree: toObservableTree does not support circular references (cycle detected at path "${path}")`
3035
+ );
3036
+ }
3037
+ ancestorPath.add(value);
3038
+ const toWrap = [];
3039
+ const keys = Object.keys(value);
3040
+ for (let i = 0; i < keys.length; i++) {
3041
+ const key = keys[i];
3042
+ const propValue = value[key];
3043
+ if (Array.isArray(propValue) || isPlainObject(propValue)) {
3044
+ toWrap.push({ key, propValue });
3045
+ }
3046
+ }
3047
+ const proxy = observable(value);
3048
+ for (const { key, propValue } of toWrap) {
3049
+ proxy[key] = toObservableTreeInternal(
3050
+ propValue,
3051
+ ancestorPath,
3052
+ buildPath(path, key)
3053
+ );
3054
+ }
3055
+ ancestorPath.delete(value);
3056
+ return proxy;
3057
+ }
3058
+ return value;
3059
+ }
2663
3060
  function makeDecorator(type) {
2664
3061
  return function(value, context) {
2665
3062
  context.metadata[context.name] = type;
@@ -2682,10 +3079,7 @@ const child = makeChildDecorator(childType);
2682
3079
  const modelRef = makeChildDecorator(modelRefType);
2683
3080
  const model = makeDecorator(modelType);
2684
3081
  const id = makeDecorator(idType);
2685
- const state = Object.assign(makeDecorator(stateType), {
2686
- shallow: makeDecorator(stateShallowType),
2687
- signal: makeDecorator(stateSignalType)
2688
- });
3082
+ const state = makeDecorator(stateType);
2689
3083
  export {
2690
3084
  Model,
2691
3085
  Observable,
@@ -2710,9 +3104,10 @@ export {
2710
3104
  reaction,
2711
3105
  reportChanged,
2712
3106
  reportObserved,
2713
- signal2 as signal,
3107
+ signal,
2714
3108
  source,
2715
3109
  state,
3110
+ toObservableTree,
2716
3111
  toSnapshot,
2717
3112
  unmount,
2718
3113
  untracked2 as untracked,