r-state-tree 0.4.7 → 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.
- package/README.md +358 -28
- package/dist/index.d.ts +4 -3
- package/dist/model/ChildModelsAdministration.d.ts +1 -1
- package/dist/model/ModelAdministration.d.ts +2 -0
- package/dist/observables/array.d.ts +5 -3
- package/dist/observables/collection.d.ts +10 -14
- package/dist/observables/index.d.ts +2 -2
- package/dist/observables/internal/Administration.d.ts +2 -3
- package/dist/observables/internal/NodeMap.d.ts +1 -0
- package/dist/observables/internal/lookup.d.ts +3 -0
- package/dist/observables/object.d.ts +5 -4
- package/dist/observables/preact.d.ts +5 -15
- package/dist/r-state-tree.cjs +1034 -309
- package/dist/r-state-tree.js +1048 -320
- package/dist/store/StoreAdministration.d.ts +1 -1
- package/dist/toObservableTree.d.ts +1 -0
- package/dist/types.d.ts +5 -3
- package/dist/utils.d.ts +1 -1
- package/package.json +1 -1
package/dist/r-state-tree.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { batch,
|
|
2
|
-
import { Signal as Signal2, batch as batch2, effect as effect2,
|
|
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() {
|
|
@@ -25,7 +25,6 @@ var StoreCfgTypes = /* @__PURE__ */ ((StoreCfgTypes2) => {
|
|
|
25
25
|
return StoreCfgTypes2;
|
|
26
26
|
})(StoreCfgTypes || {});
|
|
27
27
|
var ObservableCfgTypes = /* @__PURE__ */ ((ObservableCfgTypes2) => {
|
|
28
|
-
ObservableCfgTypes2["observable"] = "observable";
|
|
29
28
|
ObservableCfgTypes2["computed"] = "computed";
|
|
30
29
|
return ObservableCfgTypes2;
|
|
31
30
|
})(ObservableCfgTypes || {});
|
|
@@ -66,26 +65,29 @@ function isPropertyKey(val) {
|
|
|
66
65
|
return typeof val === "string" || typeof val === "number" || typeof val === "symbol";
|
|
67
66
|
}
|
|
68
67
|
function getPropertyType(key, obj) {
|
|
69
|
-
const
|
|
68
|
+
const ctor = obj.constructor;
|
|
69
|
+
const hasMetadata = ctor != null && ctor[Symbol.metadata] !== void 0;
|
|
70
70
|
const descriptor = getPropertyDescriptor$1(obj, key);
|
|
71
71
|
if (descriptor?.value && typeof descriptor.value === "function") {
|
|
72
72
|
return "action";
|
|
73
73
|
}
|
|
74
|
-
const
|
|
74
|
+
const isAccessor = descriptor && (typeof descriptor.get === "function" || typeof descriptor.set === "function");
|
|
75
75
|
if (!hasMetadata) {
|
|
76
|
-
if (
|
|
76
|
+
if (descriptor?.get) {
|
|
77
77
|
return "computed";
|
|
78
78
|
}
|
|
79
|
+
if (isAccessor) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
79
82
|
return "observable";
|
|
80
83
|
}
|
|
81
84
|
const metadata = obj.constructor[Symbol.metadata];
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
const config = metadata?.[key];
|
|
86
|
+
if (config) {
|
|
84
87
|
switch (config.type) {
|
|
85
88
|
case ObservableCfgTypes.computed:
|
|
86
89
|
return "computed";
|
|
87
90
|
case ModelCfgTypes.state:
|
|
88
|
-
case ObservableCfgTypes.observable:
|
|
89
91
|
case ModelCfgTypes.id:
|
|
90
92
|
case ModelCfgTypes.modelRef:
|
|
91
93
|
case CommonCfgTypes.child:
|
|
@@ -93,7 +95,7 @@ function getPropertyType(key, obj) {
|
|
|
93
95
|
return "observable";
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
|
-
return null;
|
|
98
|
+
return isAccessor ? null : "observable";
|
|
97
99
|
}
|
|
98
100
|
function getPropertyDescriptor$1(obj, key) {
|
|
99
101
|
let node = obj;
|
|
@@ -122,7 +124,7 @@ class Administration {
|
|
|
122
124
|
atom;
|
|
123
125
|
valuesMap;
|
|
124
126
|
isObserved = false;
|
|
125
|
-
|
|
127
|
+
forceObservedAtom;
|
|
126
128
|
constructor(source2) {
|
|
127
129
|
this.atom = createObservedAtom();
|
|
128
130
|
this.source = source2;
|
|
@@ -132,13 +134,9 @@ class Administration {
|
|
|
132
134
|
);
|
|
133
135
|
}
|
|
134
136
|
flushChange() {
|
|
135
|
-
if (this.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
this.forceObservedAtoms[i].reportChanged();
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
this.forceObservedAtoms = void 0;
|
|
137
|
+
if (this.forceObservedAtom) {
|
|
138
|
+
this.forceObservedAtom.reportChanged();
|
|
139
|
+
this.forceObservedAtom = void 0;
|
|
142
140
|
}
|
|
143
141
|
}
|
|
144
142
|
getNode() {
|
|
@@ -147,9 +145,7 @@ class Administration {
|
|
|
147
145
|
reportChanged() {
|
|
148
146
|
this.atom.reportChanged();
|
|
149
147
|
}
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
reportObserved(deep = false) {
|
|
148
|
+
reportObserved() {
|
|
153
149
|
const entry = circularRefSet == null;
|
|
154
150
|
if (entry) {
|
|
155
151
|
circularRefSet = /* @__PURE__ */ new WeakSet();
|
|
@@ -157,15 +153,10 @@ class Administration {
|
|
|
157
153
|
return;
|
|
158
154
|
}
|
|
159
155
|
circularRefSet.add(this);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
this.forceObservedAtoms = [];
|
|
163
|
-
}
|
|
164
|
-
this.forceObservedAtoms.push(atom);
|
|
165
|
-
atom.reportObserved();
|
|
166
|
-
if (deep) {
|
|
167
|
-
this.reportObserveDeep();
|
|
156
|
+
if (!this.forceObservedAtom) {
|
|
157
|
+
this.forceObservedAtom = createAtom();
|
|
168
158
|
}
|
|
159
|
+
this.forceObservedAtom.reportObserved();
|
|
169
160
|
if (entry) {
|
|
170
161
|
circularRefSet = null;
|
|
171
162
|
}
|
|
@@ -228,6 +219,9 @@ class NodeMap {
|
|
|
228
219
|
reportChanged(key, value) {
|
|
229
220
|
return this.get(key)?.reportChanged(value);
|
|
230
221
|
}
|
|
222
|
+
keys() {
|
|
223
|
+
return this.map?.keys() ?? [];
|
|
224
|
+
}
|
|
231
225
|
}
|
|
232
226
|
class AtomMap extends NodeMap {
|
|
233
227
|
createNode() {
|
|
@@ -245,31 +239,34 @@ class ObjectAdministration extends Administration {
|
|
|
245
239
|
valuesMap;
|
|
246
240
|
computedMap;
|
|
247
241
|
types;
|
|
242
|
+
isWriting = false;
|
|
248
243
|
static proxyTraps = {
|
|
249
244
|
has(target, name) {
|
|
250
245
|
const adm = getAdministration(target);
|
|
251
|
-
if (!(name in Object.prototype)
|
|
246
|
+
if (isPropertyKey(name) && (!(name in Object.prototype) || Object.prototype.hasOwnProperty.call(adm.source, name)))
|
|
252
247
|
return adm.has(name);
|
|
253
248
|
return Reflect.has(adm.source, name);
|
|
254
249
|
},
|
|
255
250
|
get(target, name) {
|
|
256
251
|
const adm = getAdministration(target);
|
|
257
|
-
if (!(name in Object.prototype)
|
|
258
|
-
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]);
|
|
259
254
|
}
|
|
260
|
-
return Reflect.get(adm.source, name,
|
|
255
|
+
return Reflect.get(adm.source, name, arguments[2]);
|
|
261
256
|
},
|
|
262
257
|
set(target, name, value) {
|
|
263
258
|
if (!isPropertyKey(name)) return false;
|
|
264
259
|
const adm = getAdministration(target);
|
|
265
|
-
|
|
266
|
-
|
|
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);
|
|
267
265
|
},
|
|
268
266
|
deleteProperty(target, name) {
|
|
269
267
|
if (!isPropertyKey(name)) return false;
|
|
270
268
|
const adm = getAdministration(target);
|
|
271
|
-
adm.remove(name);
|
|
272
|
-
return true;
|
|
269
|
+
return adm.remove(name);
|
|
273
270
|
},
|
|
274
271
|
ownKeys(target) {
|
|
275
272
|
const adm = getAdministration(target);
|
|
@@ -278,21 +275,47 @@ class ObjectAdministration extends Administration {
|
|
|
278
275
|
adm.atom.reportObserved();
|
|
279
276
|
});
|
|
280
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;
|
|
281
304
|
}
|
|
282
305
|
};
|
|
283
306
|
constructor(source2 = {}) {
|
|
284
307
|
super(source2);
|
|
285
308
|
this.keysAtom = createAtom();
|
|
286
309
|
this.hasMap = new AtomMap(this.atom);
|
|
287
|
-
this.valuesMap = new SignalMap();
|
|
310
|
+
this.valuesMap = new SignalMap(this.atom);
|
|
288
311
|
this.types = /* @__PURE__ */ new Map();
|
|
289
312
|
}
|
|
290
313
|
get(key) {
|
|
291
314
|
return Reflect.get(this.source, key, this.proxy);
|
|
292
315
|
}
|
|
293
316
|
set(key, value) {
|
|
294
|
-
batch(() => {
|
|
295
|
-
Reflect.set(this.source, key, value, this.proxy);
|
|
317
|
+
return batch(() => {
|
|
318
|
+
return Reflect.set(this.source, key, value, this.proxy);
|
|
296
319
|
});
|
|
297
320
|
}
|
|
298
321
|
getComputed(key) {
|
|
@@ -320,17 +343,6 @@ class ObjectAdministration extends Administration {
|
|
|
320
343
|
}
|
|
321
344
|
return type;
|
|
322
345
|
}
|
|
323
|
-
reportObserveDeep() {
|
|
324
|
-
Object.getOwnPropertyNames(this.source).forEach((name) => {
|
|
325
|
-
const type = this.getType(name);
|
|
326
|
-
if (type === "observable") {
|
|
327
|
-
const value = this.source[name];
|
|
328
|
-
if (value && typeof value === "object") {
|
|
329
|
-
getAdministration(getObservable(value))?.reportObserved();
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
346
|
reportChanged() {
|
|
335
347
|
this.types.clear();
|
|
336
348
|
super.reportChanged();
|
|
@@ -345,10 +357,10 @@ class ObjectAdministration extends Administration {
|
|
|
345
357
|
}
|
|
346
358
|
return resolveNode(this.valuesMap.getOrCreate(key, this.source[key]));
|
|
347
359
|
}
|
|
348
|
-
read(key) {
|
|
360
|
+
read(key, receiver = this.proxy) {
|
|
349
361
|
const type = this.getType(key);
|
|
350
362
|
if (type === null) {
|
|
351
|
-
return
|
|
363
|
+
return Reflect.get(this.source, key, receiver);
|
|
352
364
|
}
|
|
353
365
|
switch (type) {
|
|
354
366
|
case "observable":
|
|
@@ -361,35 +373,66 @@ class ObjectAdministration extends Administration {
|
|
|
361
373
|
this.hasMap.reportObserved(key);
|
|
362
374
|
}
|
|
363
375
|
if (type === "observable") {
|
|
364
|
-
|
|
376
|
+
const value = Reflect.get(this.source, key, receiver);
|
|
377
|
+
const shouldWrap = this.explicitObservables.has(key) || isObservable(value);
|
|
378
|
+
if (shouldWrap && value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
379
|
+
const desc = getPropertyDescriptor$1(this.source, key);
|
|
380
|
+
if (desc && !desc.configurable && !desc.writable) {
|
|
381
|
+
return value;
|
|
382
|
+
}
|
|
383
|
+
const existingAdm = getAdministration(value);
|
|
384
|
+
if (existingAdm) {
|
|
385
|
+
return existingAdm.proxy;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return value;
|
|
365
389
|
}
|
|
366
|
-
return getAction(
|
|
390
|
+
return getAction(
|
|
391
|
+
Reflect.get(this.source, key, receiver)
|
|
392
|
+
);
|
|
367
393
|
}
|
|
368
394
|
case "computed": {
|
|
369
|
-
|
|
395
|
+
if (receiver === this.proxy) {
|
|
396
|
+
return this.callComputed(key);
|
|
397
|
+
}
|
|
398
|
+
this.atom.reportObserved();
|
|
399
|
+
return Reflect.get(this.source, key, receiver);
|
|
370
400
|
}
|
|
371
401
|
default:
|
|
372
402
|
throw new Error(`unknown type passed to configure`);
|
|
373
403
|
}
|
|
374
404
|
}
|
|
405
|
+
explicitObservables = /* @__PURE__ */ new Set();
|
|
375
406
|
write(key, newValue) {
|
|
376
407
|
const type = this.getType(key);
|
|
377
408
|
if (type === null) {
|
|
378
|
-
this.set(key, newValue);
|
|
379
|
-
return;
|
|
409
|
+
return this.set(key, newValue);
|
|
380
410
|
}
|
|
381
411
|
if (type === "computed") {
|
|
382
|
-
batch(() => this.set(key, newValue));
|
|
383
|
-
return;
|
|
412
|
+
return batch(() => this.set(key, newValue));
|
|
384
413
|
}
|
|
385
414
|
const had = key in this.source;
|
|
386
415
|
const oldValue = this.get(key);
|
|
387
416
|
const targetValue = getSource(newValue);
|
|
417
|
+
const oldExplicit = this.explicitObservables.has(key);
|
|
418
|
+
const newExplicit = isObservable(newValue);
|
|
419
|
+
if (newExplicit) {
|
|
420
|
+
this.explicitObservables.add(key);
|
|
421
|
+
} else {
|
|
422
|
+
this.explicitObservables.delete(key);
|
|
423
|
+
}
|
|
388
424
|
if (type === "action" && typeof newValue !== "function" || type === "observable" && typeof newValue === "function") {
|
|
389
425
|
this.types.delete(key);
|
|
390
426
|
}
|
|
391
|
-
|
|
392
|
-
|
|
427
|
+
const changed = !had || !isObservable(oldValue) && oldExplicit !== newExplicit || (isObservable(oldValue) ? oldValue !== newValue : oldValue !== targetValue);
|
|
428
|
+
if (changed) {
|
|
429
|
+
this.isWriting = true;
|
|
430
|
+
try {
|
|
431
|
+
const result = this.set(key, targetValue);
|
|
432
|
+
if (!result) return false;
|
|
433
|
+
} finally {
|
|
434
|
+
this.isWriting = false;
|
|
435
|
+
}
|
|
393
436
|
batch(() => {
|
|
394
437
|
this.flushChange();
|
|
395
438
|
if (!had) {
|
|
@@ -398,7 +441,9 @@ class ObjectAdministration extends Administration {
|
|
|
398
441
|
}
|
|
399
442
|
this.valuesMap.reportChanged(key, newValue);
|
|
400
443
|
});
|
|
444
|
+
return true;
|
|
401
445
|
}
|
|
446
|
+
return true;
|
|
402
447
|
}
|
|
403
448
|
has(key) {
|
|
404
449
|
this.atom.reportObserved();
|
|
@@ -408,39 +453,27 @@ class ObjectAdministration extends Administration {
|
|
|
408
453
|
return key in this.source;
|
|
409
454
|
}
|
|
410
455
|
remove(key) {
|
|
411
|
-
if (!(key in this.source)) return;
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
456
|
+
if (!(key in this.source)) return true;
|
|
457
|
+
const result = Reflect.deleteProperty(this.source, key);
|
|
458
|
+
if (result) {
|
|
459
|
+
batch(() => {
|
|
460
|
+
this.flushChange();
|
|
461
|
+
this.valuesMap.reportChanged(key, void 0);
|
|
462
|
+
this.keysAtom.reportChanged();
|
|
463
|
+
this.hasMap.reportChanged(key);
|
|
464
|
+
this.valuesMap.delete(key);
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
return result;
|
|
420
468
|
}
|
|
421
469
|
}
|
|
422
470
|
class PreactObjectAdministration extends ObjectAdministration {
|
|
423
|
-
static proxyTraps = Object.assign(
|
|
424
|
-
{},
|
|
425
|
-
ObjectAdministration.proxyTraps,
|
|
426
|
-
{
|
|
427
|
-
get(target, prop, proxy) {
|
|
428
|
-
if (!(prop in target) && (typeof prop === "string" || typeof prop === "number") && String(prop)[0] === "$") {
|
|
429
|
-
return getSignal(proxy, prop.substring(1));
|
|
430
|
-
}
|
|
431
|
-
return ObjectAdministration.proxyTraps.get?.apply(
|
|
432
|
-
null,
|
|
433
|
-
arguments
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
);
|
|
438
471
|
}
|
|
439
472
|
function createObservedAtom() {
|
|
440
473
|
let value = 0;
|
|
441
474
|
const callbacks = /* @__PURE__ */ new Set();
|
|
442
475
|
let observing = false;
|
|
443
|
-
const
|
|
476
|
+
const signal2 = new Signal(value, {
|
|
444
477
|
watched() {
|
|
445
478
|
callbacks.forEach((callback) => callback(true));
|
|
446
479
|
observing = true;
|
|
@@ -451,12 +484,12 @@ function createObservedAtom() {
|
|
|
451
484
|
}
|
|
452
485
|
});
|
|
453
486
|
return {
|
|
454
|
-
node:
|
|
487
|
+
node: signal2,
|
|
455
488
|
reportObserved() {
|
|
456
|
-
return
|
|
489
|
+
return signal2.value;
|
|
457
490
|
},
|
|
458
491
|
reportChanged() {
|
|
459
|
-
return
|
|
492
|
+
return signal2.value = ++value;
|
|
460
493
|
},
|
|
461
494
|
get observing() {
|
|
462
495
|
return observing;
|
|
@@ -470,7 +503,7 @@ function createObservedAtom() {
|
|
|
470
503
|
};
|
|
471
504
|
}
|
|
472
505
|
function createSignal(initialValue) {
|
|
473
|
-
const s = signal(initialValue);
|
|
506
|
+
const s = signal$1(initialValue);
|
|
474
507
|
return {
|
|
475
508
|
node: s,
|
|
476
509
|
reportChanged(value) {
|
|
@@ -489,7 +522,7 @@ function createSignal(initialValue) {
|
|
|
489
522
|
}
|
|
490
523
|
function createAtom() {
|
|
491
524
|
let value = 0;
|
|
492
|
-
const s = signal(value);
|
|
525
|
+
const s = signal$1(value);
|
|
493
526
|
return {
|
|
494
527
|
node: s,
|
|
495
528
|
reportChanged() {
|
|
@@ -572,12 +605,11 @@ function createComputed(fn, context = null) {
|
|
|
572
605
|
}
|
|
573
606
|
};
|
|
574
607
|
}
|
|
575
|
-
function observable(
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
return getObservable(value);
|
|
608
|
+
function observable(obj) {
|
|
609
|
+
return getObservable(obj);
|
|
610
|
+
}
|
|
611
|
+
function signal(value) {
|
|
612
|
+
return signal$1(value);
|
|
581
613
|
}
|
|
582
614
|
function computed(value, context) {
|
|
583
615
|
if (context && typeof context === "object" && "kind" in context) {
|
|
@@ -589,29 +621,24 @@ function computed(value, context) {
|
|
|
589
621
|
function source(obj) {
|
|
590
622
|
return getSource(obj);
|
|
591
623
|
}
|
|
592
|
-
class Observable {
|
|
593
|
-
constructor() {
|
|
594
|
-
return getObservableClassInstance(this);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
624
|
function reportChanged(obj) {
|
|
598
625
|
const adm = getAdministration(obj);
|
|
599
626
|
adm.reportChanged();
|
|
600
627
|
return obj;
|
|
601
628
|
}
|
|
602
|
-
function reportObserved(obj
|
|
629
|
+
function reportObserved(obj) {
|
|
603
630
|
const adm = getAdministration(obj);
|
|
604
|
-
adm.reportObserved(
|
|
631
|
+
adm.reportObserved();
|
|
605
632
|
return obj;
|
|
606
633
|
}
|
|
607
634
|
const signalMap = /* @__PURE__ */ new WeakMap();
|
|
608
635
|
function getSignal(obj, key) {
|
|
609
636
|
const node = getInternalNode(obj, key);
|
|
610
637
|
if (node instanceof Signal) {
|
|
611
|
-
let
|
|
612
|
-
if (!
|
|
613
|
-
|
|
614
|
-
Object.defineProperties(
|
|
638
|
+
let signal2 = signalMap.get(node);
|
|
639
|
+
if (!signal2) {
|
|
640
|
+
signal2 = new Signal();
|
|
641
|
+
Object.defineProperties(signal2, {
|
|
615
642
|
value: {
|
|
616
643
|
get() {
|
|
617
644
|
return obj[key];
|
|
@@ -626,9 +653,9 @@ function getSignal(obj, key) {
|
|
|
626
653
|
}
|
|
627
654
|
}
|
|
628
655
|
});
|
|
629
|
-
signalMap.set(node,
|
|
656
|
+
signalMap.set(node, signal2);
|
|
630
657
|
}
|
|
631
|
-
return
|
|
658
|
+
return signal2;
|
|
632
659
|
}
|
|
633
660
|
return node;
|
|
634
661
|
}
|
|
@@ -637,17 +664,36 @@ class CollectionAdministration extends Administration {
|
|
|
637
664
|
hasMap;
|
|
638
665
|
valuesMap;
|
|
639
666
|
keysAtom;
|
|
667
|
+
isWeak;
|
|
668
|
+
strongTracking = null;
|
|
669
|
+
weakTracking = null;
|
|
640
670
|
static proxyTraps = {
|
|
641
671
|
get(target, name) {
|
|
642
672
|
const adm = getAdministration(target);
|
|
643
|
-
if (name === "size" && "size" in adm.source) {
|
|
673
|
+
if (name === "size" && !adm.isWeak && "size" in adm.source) {
|
|
644
674
|
return adm.size;
|
|
645
675
|
}
|
|
646
676
|
const val = adm.source[name];
|
|
647
677
|
const collectionMethods = adm.constructor.methods;
|
|
648
|
-
if (collectionMethods.hasOwnProperty(name)
|
|
678
|
+
if (collectionMethods.hasOwnProperty(name)) {
|
|
679
|
+
if (adm.isWeak && !isValidWeakMethod(name)) {
|
|
680
|
+
return val;
|
|
681
|
+
}
|
|
649
682
|
return collectionMethods[name];
|
|
650
683
|
}
|
|
684
|
+
if (typeof val === "function") {
|
|
685
|
+
return function() {
|
|
686
|
+
if (process.env.NODE_ENV !== "production") {
|
|
687
|
+
console.warn(
|
|
688
|
+
`r-state-tree: Calling uninstrumented collection method "${String(
|
|
689
|
+
name
|
|
690
|
+
)}". Reactivity is not guaranteed for this call.`
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
const result = val.apply(adm.source, arguments);
|
|
694
|
+
return result === adm.source ? adm.proxy : result;
|
|
695
|
+
};
|
|
696
|
+
}
|
|
651
697
|
return val;
|
|
652
698
|
}
|
|
653
699
|
};
|
|
@@ -662,17 +708,71 @@ class CollectionAdministration extends Administration {
|
|
|
662
708
|
entries: createMethod$1("entries"),
|
|
663
709
|
keys: createMethod$1("keys"),
|
|
664
710
|
values: createMethod$1("values"),
|
|
665
|
-
[Symbol.iterator]: createMethod$1(Symbol.iterator)
|
|
711
|
+
[Symbol.iterator]: createMethod$1(Symbol.iterator),
|
|
712
|
+
// New ES methods
|
|
713
|
+
union: createGenericMethod("union"),
|
|
714
|
+
intersection: createGenericMethod("intersection"),
|
|
715
|
+
difference: createGenericMethod("difference"),
|
|
716
|
+
symmetricDifference: createGenericMethod("symmetricDifference"),
|
|
717
|
+
isSubsetOf: createGenericMethod("isSubsetOf"),
|
|
718
|
+
isSupersetOf: createGenericMethod("isSupersetOf"),
|
|
719
|
+
isDisjointFrom: createGenericMethod("isDisjointFrom")
|
|
666
720
|
};
|
|
667
721
|
constructor(source2) {
|
|
668
722
|
super(source2);
|
|
669
723
|
this.hasMap = new AtomMap(this.atom);
|
|
670
|
-
this.valuesMap = new SignalMap();
|
|
724
|
+
this.valuesMap = new SignalMap(this.atom);
|
|
671
725
|
this.keysAtom = createAtom();
|
|
672
726
|
this.isMap = typeof source2.set === "function" && typeof source2.get === "function";
|
|
727
|
+
this.isWeak = source2 instanceof WeakMap || source2 instanceof WeakSet;
|
|
728
|
+
if (this.isWeak) {
|
|
729
|
+
this.weakTracking = /* @__PURE__ */ new WeakSet();
|
|
730
|
+
} else {
|
|
731
|
+
this.strongTracking = /* @__PURE__ */ new Set();
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
trackExplicitObservable(key) {
|
|
735
|
+
if (this.isWeak) {
|
|
736
|
+
if (isNonPrimitive(key)) {
|
|
737
|
+
this.weakTracking.add(key);
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
740
|
+
this.strongTracking.add(key);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
untrackExplicitObservable(key) {
|
|
744
|
+
if (this.isWeak) {
|
|
745
|
+
if (isNonPrimitive(key)) {
|
|
746
|
+
this.weakTracking.delete(key);
|
|
747
|
+
}
|
|
748
|
+
} else {
|
|
749
|
+
this.strongTracking.delete(key);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
hasExplicitObservable(key) {
|
|
753
|
+
if (this.isWeak) {
|
|
754
|
+
return isNonPrimitive(key) && this.weakTracking.has(key);
|
|
755
|
+
}
|
|
756
|
+
return this.strongTracking.has(key);
|
|
757
|
+
}
|
|
758
|
+
getProxyVariant(key) {
|
|
759
|
+
if (!isNonPrimitive(key)) return void 0;
|
|
760
|
+
const adm = getAdministration(key);
|
|
761
|
+
if (adm && adm.proxy && adm.proxy !== key) {
|
|
762
|
+
return adm.proxy;
|
|
763
|
+
}
|
|
764
|
+
return void 0;
|
|
765
|
+
}
|
|
766
|
+
getExistingKey(key) {
|
|
767
|
+
const target = getSource(key);
|
|
768
|
+
if (this.source.has(target)) return target;
|
|
769
|
+
if (this.source.has(key)) return key;
|
|
770
|
+
const proxy = this.getProxyVariant(key);
|
|
771
|
+
if (proxy !== void 0 && this.source.has(proxy)) return proxy;
|
|
772
|
+
return void 0;
|
|
673
773
|
}
|
|
674
774
|
hasEntry(key) {
|
|
675
|
-
return this.
|
|
775
|
+
return this.getExistingKey(key) !== void 0;
|
|
676
776
|
}
|
|
677
777
|
onCollectionChange(key) {
|
|
678
778
|
batch(() => {
|
|
@@ -681,13 +781,6 @@ class CollectionAdministration extends Administration {
|
|
|
681
781
|
this.flushChange();
|
|
682
782
|
});
|
|
683
783
|
}
|
|
684
|
-
reportObserveDeep() {
|
|
685
|
-
this.source.forEach?.((value) => {
|
|
686
|
-
if (value && typeof value === "object") {
|
|
687
|
-
getAdministration(getObservable(value))?.reportObserved();
|
|
688
|
-
}
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
784
|
getNode(key) {
|
|
692
785
|
if (key == null) {
|
|
693
786
|
return resolveNode(this.atom);
|
|
@@ -708,13 +801,12 @@ class CollectionAdministration extends Administration {
|
|
|
708
801
|
this.keysAtom.reportObserved();
|
|
709
802
|
this.atom.reportObserved();
|
|
710
803
|
this.source.forEach((value, key) => {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
);
|
|
804
|
+
if (this.isMap) {
|
|
805
|
+
callbackFn.call(thisArg, this.get(key), key, this.proxy);
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
const wrapped = this.wrapSetValue(key);
|
|
809
|
+
callbackFn.call(thisArg, wrapped, wrapped, this.proxy);
|
|
718
810
|
});
|
|
719
811
|
}
|
|
720
812
|
get size() {
|
|
@@ -723,43 +815,68 @@ class CollectionAdministration extends Administration {
|
|
|
723
815
|
return this.source.size;
|
|
724
816
|
}
|
|
725
817
|
add(value) {
|
|
818
|
+
const target = getSource(value);
|
|
819
|
+
if (isObservable(value)) {
|
|
820
|
+
this.trackExplicitObservable(target);
|
|
821
|
+
} else {
|
|
822
|
+
this.untrackExplicitObservable(target);
|
|
823
|
+
this.untrackExplicitObservable(value);
|
|
824
|
+
}
|
|
726
825
|
if (!this.hasEntry(value)) {
|
|
727
|
-
const target = getSource(value);
|
|
728
826
|
this.source.add(target);
|
|
729
827
|
this.onCollectionChange(target);
|
|
730
828
|
}
|
|
731
829
|
return this;
|
|
732
830
|
}
|
|
733
831
|
delete(value) {
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
832
|
+
const existingKey = this.getExistingKey(value);
|
|
833
|
+
if (existingKey === void 0) return false;
|
|
834
|
+
const target = getSource(value);
|
|
835
|
+
this.untrackExplicitObservable(target);
|
|
836
|
+
this.untrackExplicitObservable(value);
|
|
837
|
+
const proxy = this.getProxyVariant(value);
|
|
838
|
+
if (proxy !== void 0) this.untrackExplicitObservable(proxy);
|
|
839
|
+
this.source.delete(existingKey);
|
|
840
|
+
this.source.delete(target);
|
|
841
|
+
this.source.delete(value);
|
|
842
|
+
if (proxy !== void 0) this.source.delete(proxy);
|
|
843
|
+
this.onCollectionChange(target);
|
|
844
|
+
return true;
|
|
845
|
+
}
|
|
846
|
+
wrapSetValue(value) {
|
|
847
|
+
if (this.hasExplicitObservable(value)) {
|
|
848
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
849
|
+
const existingAdm = getAdministration(value);
|
|
850
|
+
if (existingAdm) return existingAdm.proxy;
|
|
851
|
+
}
|
|
740
852
|
}
|
|
741
|
-
return
|
|
853
|
+
return value;
|
|
742
854
|
}
|
|
743
855
|
has(value) {
|
|
744
856
|
this.atom.reportObserved();
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
this.hasMap.reportObserved(target);
|
|
748
|
-
}
|
|
857
|
+
const target = getSource(value);
|
|
858
|
+
this.hasMap.reportObserved(target);
|
|
749
859
|
return this.hasEntry(value);
|
|
750
860
|
}
|
|
751
861
|
entries() {
|
|
862
|
+
this.keysAtom.reportObserved();
|
|
863
|
+
this.atom.reportObserved();
|
|
752
864
|
const self = this;
|
|
753
|
-
const
|
|
865
|
+
const iterator = this.source.entries();
|
|
754
866
|
return {
|
|
755
867
|
[Symbol.iterator]: function() {
|
|
756
868
|
return this;
|
|
757
869
|
},
|
|
758
870
|
next() {
|
|
759
|
-
const { done, value } =
|
|
871
|
+
const { done, value } = iterator.next();
|
|
872
|
+
if (done) return { done: true, value: void 0 };
|
|
873
|
+
const [key, val] = value;
|
|
760
874
|
return {
|
|
761
|
-
done,
|
|
762
|
-
value:
|
|
875
|
+
done: false,
|
|
876
|
+
value: [
|
|
877
|
+
self.isMap ? key : self.wrapSetValue(key),
|
|
878
|
+
self.isMap ? self.get(key) : self.wrapSetValue(val)
|
|
879
|
+
]
|
|
763
880
|
};
|
|
764
881
|
}
|
|
765
882
|
};
|
|
@@ -767,19 +884,19 @@ class CollectionAdministration extends Administration {
|
|
|
767
884
|
keys() {
|
|
768
885
|
this.keysAtom.reportObserved();
|
|
769
886
|
this.atom.reportObserved();
|
|
770
|
-
|
|
771
|
-
const
|
|
772
|
-
(o) => getObservable(o)
|
|
773
|
-
);
|
|
887
|
+
const self = this;
|
|
888
|
+
const iterator = this.source.keys();
|
|
774
889
|
return {
|
|
775
890
|
[Symbol.iterator]: function() {
|
|
776
891
|
return this;
|
|
777
892
|
},
|
|
778
893
|
next() {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
894
|
+
const { done, value } = iterator.next();
|
|
895
|
+
if (done) return { done: true, value: void 0 };
|
|
896
|
+
return {
|
|
897
|
+
done: false,
|
|
898
|
+
value: self.isMap ? value : self.wrapSetValue(value)
|
|
899
|
+
};
|
|
783
900
|
}
|
|
784
901
|
};
|
|
785
902
|
}
|
|
@@ -787,28 +904,54 @@ class CollectionAdministration extends Administration {
|
|
|
787
904
|
const targetKey = getSource(key);
|
|
788
905
|
const sourceMap = this.source;
|
|
789
906
|
const has = this.has(key);
|
|
790
|
-
|
|
791
|
-
|
|
907
|
+
if (!has) return void 0;
|
|
908
|
+
const existingKey = this.getExistingKey(key);
|
|
909
|
+
const value = sourceMap.get(existingKey);
|
|
910
|
+
this.valuesMap.reportObserved(targetKey, value);
|
|
911
|
+
if (key !== targetKey) {
|
|
792
912
|
this.valuesMap.reportObserved(key, value);
|
|
793
|
-
return getObservable(value);
|
|
794
913
|
}
|
|
795
|
-
|
|
914
|
+
const proxyKey = this.getProxyVariant(key);
|
|
915
|
+
if (proxyKey !== void 0 && proxyKey !== key && proxyKey !== targetKey) {
|
|
916
|
+
this.valuesMap.reportObserved(proxyKey, value);
|
|
917
|
+
}
|
|
918
|
+
if (this.hasExplicitObservable(targetKey) || this.hasExplicitObservable(key) || proxyKey !== void 0 && this.hasExplicitObservable(proxyKey)) {
|
|
919
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
920
|
+
const existingAdm = getAdministration(value);
|
|
921
|
+
if (existingAdm) return existingAdm.proxy;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return value;
|
|
796
925
|
}
|
|
797
926
|
set(key, value) {
|
|
798
927
|
const targetKey = getSource(key);
|
|
799
928
|
const targetValue = getSource(value);
|
|
800
929
|
const sourceMap = this.source;
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
930
|
+
if (isObservable(value)) {
|
|
931
|
+
this.trackExplicitObservable(targetKey);
|
|
932
|
+
} else {
|
|
933
|
+
this.untrackExplicitObservable(targetKey);
|
|
934
|
+
this.untrackExplicitObservable(key);
|
|
935
|
+
}
|
|
936
|
+
const existingKey = this.getExistingKey(key);
|
|
937
|
+
const hasKey = existingKey !== void 0;
|
|
938
|
+
const oldValue = hasKey ? sourceMap.get(existingKey) : void 0;
|
|
939
|
+
if (!hasKey || (isObservable(oldValue) ? oldValue !== value : oldValue !== targetValue)) {
|
|
804
940
|
batch(() => {
|
|
805
941
|
this.flushChange();
|
|
806
|
-
if (
|
|
807
|
-
sourceMap.set(
|
|
942
|
+
if (existingKey !== void 0) {
|
|
943
|
+
sourceMap.set(existingKey, targetValue);
|
|
808
944
|
} else {
|
|
809
945
|
sourceMap.set(targetKey, targetValue);
|
|
810
946
|
}
|
|
811
|
-
this.valuesMap.reportChanged(
|
|
947
|
+
this.valuesMap.reportChanged(targetKey, value);
|
|
948
|
+
if (key !== targetKey) {
|
|
949
|
+
this.valuesMap.reportChanged(key, value);
|
|
950
|
+
}
|
|
951
|
+
const proxyKey = this.getProxyVariant(key);
|
|
952
|
+
if (proxyKey !== void 0 && proxyKey !== key && proxyKey !== targetKey) {
|
|
953
|
+
this.valuesMap.reportChanged(proxyKey, value);
|
|
954
|
+
}
|
|
812
955
|
if (!hasKey) {
|
|
813
956
|
this.hasMap.reportChanged(targetKey);
|
|
814
957
|
this.keysAtom.reportChanged();
|
|
@@ -818,20 +961,22 @@ class CollectionAdministration extends Administration {
|
|
|
818
961
|
return this;
|
|
819
962
|
}
|
|
820
963
|
values() {
|
|
821
|
-
|
|
822
|
-
|
|
964
|
+
this.keysAtom.reportObserved();
|
|
965
|
+
this.atom.reportObserved();
|
|
823
966
|
if (!this.isMap) {
|
|
824
|
-
return keys;
|
|
967
|
+
return this.keys();
|
|
825
968
|
}
|
|
969
|
+
const entries = this.entries();
|
|
826
970
|
return {
|
|
827
971
|
[Symbol.iterator]: function() {
|
|
828
972
|
return this;
|
|
829
973
|
},
|
|
830
974
|
next() {
|
|
831
|
-
const { done, value } =
|
|
975
|
+
const { done, value } = entries.next();
|
|
976
|
+
if (done) return { done: true, value: void 0 };
|
|
832
977
|
return {
|
|
833
|
-
done,
|
|
834
|
-
value:
|
|
978
|
+
done: false,
|
|
979
|
+
value: value[1]
|
|
835
980
|
};
|
|
836
981
|
}
|
|
837
982
|
};
|
|
@@ -841,53 +986,177 @@ class CollectionAdministration extends Administration {
|
|
|
841
986
|
}
|
|
842
987
|
[Symbol.toStringTag] = "Set";
|
|
843
988
|
}
|
|
989
|
+
function isValidWeakMethod(name) {
|
|
990
|
+
const n = name;
|
|
991
|
+
return n === "get" || n === "set" || n === "add" || n === "has" || n === "delete";
|
|
992
|
+
}
|
|
993
|
+
function createGenericMethod(name) {
|
|
994
|
+
return function() {
|
|
995
|
+
const adm = getAdministration(this);
|
|
996
|
+
const method = adm.source[name];
|
|
997
|
+
if (typeof method !== "function") return method;
|
|
998
|
+
if (["union", "intersection", "difference", "symmetricDifference"].includes(
|
|
999
|
+
name
|
|
1000
|
+
)) {
|
|
1001
|
+
const other = arguments[0];
|
|
1002
|
+
const result2 = /* @__PURE__ */ new Set();
|
|
1003
|
+
if (name === "union") {
|
|
1004
|
+
for (const item of this) result2.add(item);
|
|
1005
|
+
for (const item of other) result2.add(item);
|
|
1006
|
+
} else if (name === "intersection") {
|
|
1007
|
+
for (const item of this) {
|
|
1008
|
+
if (other.has(item)) result2.add(item);
|
|
1009
|
+
}
|
|
1010
|
+
} else if (name === "difference") {
|
|
1011
|
+
for (const item of this) {
|
|
1012
|
+
if (!other.has(item)) result2.add(item);
|
|
1013
|
+
}
|
|
1014
|
+
} else if (name === "symmetricDifference") {
|
|
1015
|
+
for (const item of this) {
|
|
1016
|
+
if (!other.has(item)) result2.add(item);
|
|
1017
|
+
}
|
|
1018
|
+
for (const item of other) {
|
|
1019
|
+
if (!this.has(item)) result2.add(item);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
return result2;
|
|
1023
|
+
}
|
|
1024
|
+
adm.keysAtom.reportObserved();
|
|
1025
|
+
adm.atom.reportObserved();
|
|
1026
|
+
const args = new Array(arguments.length);
|
|
1027
|
+
for (let i = 0; i < arguments.length; i++) {
|
|
1028
|
+
const arg = arguments[i];
|
|
1029
|
+
args[i] = getSource(arg);
|
|
1030
|
+
if (isObservable(arg)) {
|
|
1031
|
+
reportObserved(arg);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
const result = method.apply(adm.source, args);
|
|
1035
|
+
if (result === adm.source) return adm.proxy;
|
|
1036
|
+
return result;
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
844
1039
|
function createMethod$1(method) {
|
|
845
1040
|
return function() {
|
|
846
1041
|
const adm = getAdministration(this);
|
|
847
|
-
|
|
1042
|
+
const result = adm[method].apply(adm, arguments);
|
|
1043
|
+
if (method === "add" || method === "set") {
|
|
1044
|
+
return this;
|
|
1045
|
+
}
|
|
1046
|
+
return result;
|
|
848
1047
|
};
|
|
849
1048
|
}
|
|
1049
|
+
function isArrayIndexKey(key) {
|
|
1050
|
+
if (typeof key === "symbol") return false;
|
|
1051
|
+
const keyStr = String(key);
|
|
1052
|
+
const num = Number(keyStr);
|
|
1053
|
+
return Number.isInteger(num) && num >= 0 && num < 4294967295 && // 2^32 - 1
|
|
1054
|
+
String(num) === keyStr;
|
|
1055
|
+
}
|
|
850
1056
|
class ArrayAdministration extends Administration {
|
|
851
1057
|
valuesMap;
|
|
852
1058
|
keysAtom;
|
|
1059
|
+
explicitObservables = /* @__PURE__ */ new Set();
|
|
1060
|
+
syncExplicitObservablesFromSource() {
|
|
1061
|
+
for (let i = 0; i < this.source.length; i++) {
|
|
1062
|
+
const value = this.source[i];
|
|
1063
|
+
if (isObservable(value)) {
|
|
1064
|
+
this.explicitObservables.add(i);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
853
1068
|
static proxyTraps = {
|
|
854
|
-
get(target, name) {
|
|
1069
|
+
get(target, name, receiver) {
|
|
855
1070
|
const adm = getAdministration(target);
|
|
856
1071
|
if (name === "length") {
|
|
857
1072
|
return adm.getArrayLength();
|
|
858
1073
|
}
|
|
859
|
-
if (
|
|
860
|
-
return adm.get(name);
|
|
861
|
-
}
|
|
862
|
-
if (typeof name === "string" && String(parseInt(name)) === name) {
|
|
863
|
-
return adm.get(parseInt(name));
|
|
1074
|
+
if (isArrayIndexKey(name)) {
|
|
1075
|
+
return adm.get(Number(name));
|
|
864
1076
|
}
|
|
865
1077
|
const arrayMethods = adm.constructor.methods;
|
|
866
1078
|
if (arrayMethods.hasOwnProperty(name)) {
|
|
867
1079
|
return arrayMethods[name];
|
|
868
1080
|
}
|
|
869
|
-
return adm.source
|
|
1081
|
+
return Reflect.get(adm.source, name, receiver);
|
|
870
1082
|
},
|
|
871
1083
|
set(target, name, value) {
|
|
872
1084
|
const adm = getAdministration(target);
|
|
873
1085
|
if (name === "length") {
|
|
874
|
-
adm.setArrayLength(value);
|
|
875
|
-
} else if (
|
|
876
|
-
adm.set(name, value);
|
|
877
|
-
} else if (typeof name === "string" && String(parseInt(name)) === name) {
|
|
878
|
-
adm.set(parseInt(name), value);
|
|
1086
|
+
return adm.setArrayLength(value);
|
|
1087
|
+
} else if (isArrayIndexKey(name)) {
|
|
1088
|
+
return adm.set(Number(name), value);
|
|
879
1089
|
} else {
|
|
880
|
-
adm.source
|
|
1090
|
+
return Reflect.set(adm.source, name, value, arguments[3]);
|
|
881
1091
|
}
|
|
882
|
-
|
|
1092
|
+
},
|
|
1093
|
+
defineProperty(target, name, descriptor) {
|
|
1094
|
+
const adm = getAdministration(target);
|
|
1095
|
+
const result = Reflect.defineProperty(adm.source, name, descriptor);
|
|
1096
|
+
if (result) {
|
|
1097
|
+
batch(() => {
|
|
1098
|
+
adm.flushChange();
|
|
1099
|
+
if (name === "length") {
|
|
1100
|
+
adm.keysAtom.reportChanged();
|
|
1101
|
+
adm.atom.reportChanged();
|
|
1102
|
+
} else if (isArrayIndexKey(name)) {
|
|
1103
|
+
const index = Number(name);
|
|
1104
|
+
adm.keysAtom.reportChanged();
|
|
1105
|
+
adm.onArrayChanged(false, index, 1);
|
|
1106
|
+
} else {
|
|
1107
|
+
adm.atom.reportChanged();
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
return result;
|
|
1112
|
+
},
|
|
1113
|
+
deleteProperty(target, name) {
|
|
1114
|
+
const adm = getAdministration(target);
|
|
1115
|
+
const isIndex = isArrayIndexKey(name);
|
|
1116
|
+
const had = name in adm.source;
|
|
1117
|
+
const result = Reflect.deleteProperty(adm.source, name);
|
|
1118
|
+
if (result && had && isIndex) {
|
|
1119
|
+
const index = Number(name);
|
|
1120
|
+
adm.onArrayChanged(true, index, 1);
|
|
1121
|
+
adm.explicitObservables.delete(index);
|
|
1122
|
+
}
|
|
1123
|
+
return result;
|
|
1124
|
+
},
|
|
1125
|
+
ownKeys(target) {
|
|
1126
|
+
const adm = getAdministration(target);
|
|
1127
|
+
batch(() => {
|
|
1128
|
+
adm.keysAtom.reportObserved();
|
|
1129
|
+
adm.atom.reportObserved();
|
|
1130
|
+
});
|
|
1131
|
+
return Reflect.ownKeys(adm.source);
|
|
1132
|
+
},
|
|
1133
|
+
has(target, name) {
|
|
1134
|
+
const adm = getAdministration(target);
|
|
1135
|
+
if (isArrayIndexKey(name)) {
|
|
1136
|
+
const index = Number(name);
|
|
1137
|
+
adm.atom.reportObserved();
|
|
1138
|
+
adm.valuesMap.reportObserved(index, adm.source[index]);
|
|
1139
|
+
return index in adm.source;
|
|
1140
|
+
}
|
|
1141
|
+
return Reflect.has(adm.source, name);
|
|
883
1142
|
}
|
|
884
1143
|
};
|
|
885
1144
|
static methods = {
|
|
886
1145
|
fill(value, start, end) {
|
|
887
1146
|
const adm = getAdministration(this);
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
adm.
|
|
1147
|
+
const shouldTrack = isObservable(value);
|
|
1148
|
+
const targetValue = getSource(value);
|
|
1149
|
+
adm.source.fill(targetValue, start, end);
|
|
1150
|
+
const length = adm.source.length;
|
|
1151
|
+
const from = start == null ? 0 : start < 0 ? Math.max(length + start, 0) : start;
|
|
1152
|
+
const to = end == null ? length : end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
|
|
1153
|
+
for (let i = from; i < to; i++) {
|
|
1154
|
+
if (shouldTrack) adm.explicitObservables.add(i);
|
|
1155
|
+
else adm.explicitObservables.delete(i);
|
|
1156
|
+
}
|
|
1157
|
+
if (from < to) {
|
|
1158
|
+
adm.onArrayChanged(false, from, to - from);
|
|
1159
|
+
}
|
|
891
1160
|
return this;
|
|
892
1161
|
},
|
|
893
1162
|
splice(index, deleteCount, ...newItems) {
|
|
@@ -923,16 +1192,43 @@ class ArrayAdministration extends Administration {
|
|
|
923
1192
|
},
|
|
924
1193
|
reverse() {
|
|
925
1194
|
const adm = getAdministration(this);
|
|
1195
|
+
adm.syncExplicitObservablesFromSource();
|
|
1196
|
+
const flags = new Array(adm.source.length);
|
|
1197
|
+
for (let i = 0; i < flags.length; i++) {
|
|
1198
|
+
flags[i] = adm.explicitObservables.has(i);
|
|
1199
|
+
}
|
|
926
1200
|
adm.source.reverse();
|
|
1201
|
+
flags.reverse();
|
|
1202
|
+
adm.explicitObservables.clear();
|
|
1203
|
+
for (let i = 0; i < flags.length; i++) {
|
|
1204
|
+
if (flags[i]) adm.explicitObservables.add(i);
|
|
1205
|
+
}
|
|
927
1206
|
adm.onArrayChanged(false, 0, adm.source.length);
|
|
928
1207
|
return this;
|
|
929
1208
|
},
|
|
930
1209
|
sort(compareFn) {
|
|
931
1210
|
const adm = getAdministration(this);
|
|
932
|
-
adm.
|
|
933
|
-
adm.source.
|
|
934
|
-
|
|
935
|
-
|
|
1211
|
+
adm.syncExplicitObservablesFromSource();
|
|
1212
|
+
const pairs = new Array(adm.source.length);
|
|
1213
|
+
for (let i = 0; i < adm.source.length; i++) {
|
|
1214
|
+
pairs[i] = {
|
|
1215
|
+
value: this[i],
|
|
1216
|
+
stored: adm.source[i],
|
|
1217
|
+
observed: adm.explicitObservables.has(i)
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
const comparator = compareFn ?? ((a, b) => {
|
|
1221
|
+
const as = String(a);
|
|
1222
|
+
const bs = String(b);
|
|
1223
|
+
return as < bs ? -1 : as > bs ? 1 : 0;
|
|
1224
|
+
});
|
|
1225
|
+
pairs.sort((a, b) => comparator(a.value, b.value));
|
|
1226
|
+
adm.explicitObservables.clear();
|
|
1227
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
1228
|
+
adm.source[i] = pairs[i].stored;
|
|
1229
|
+
if (pairs[i].observed) adm.explicitObservables.add(i);
|
|
1230
|
+
}
|
|
1231
|
+
adm.onArrayChanged(false, 0, adm.source.length);
|
|
936
1232
|
return this;
|
|
937
1233
|
},
|
|
938
1234
|
join: createStringMethod("join"),
|
|
@@ -944,7 +1240,22 @@ class ArrayAdministration extends Administration {
|
|
|
944
1240
|
slice: createCopyMethod("slice"),
|
|
945
1241
|
concat: createCopyMethod("concat"),
|
|
946
1242
|
flat: createCopyMethod("flat"),
|
|
947
|
-
copyWithin
|
|
1243
|
+
copyWithin(target, start, end) {
|
|
1244
|
+
const adm = getAdministration(this);
|
|
1245
|
+
adm.syncExplicitObservablesFromSource();
|
|
1246
|
+
const flags = new Array(adm.source.length);
|
|
1247
|
+
for (let i = 0; i < flags.length; i++) {
|
|
1248
|
+
flags[i] = adm.explicitObservables.has(i);
|
|
1249
|
+
}
|
|
1250
|
+
adm.source.copyWithin(target, start, end);
|
|
1251
|
+
flags.copyWithin(target, start, end);
|
|
1252
|
+
adm.explicitObservables.clear();
|
|
1253
|
+
for (let i = 0; i < flags.length; i++) {
|
|
1254
|
+
if (flags[i]) adm.explicitObservables.add(i);
|
|
1255
|
+
}
|
|
1256
|
+
adm.onArrayChanged(false, 0, adm.source.length);
|
|
1257
|
+
return this;
|
|
1258
|
+
},
|
|
948
1259
|
every: createMapMethod("every"),
|
|
949
1260
|
forEach: createMapMethod("forEach"),
|
|
950
1261
|
map: createMapMethod("map"),
|
|
@@ -958,17 +1269,9 @@ class ArrayAdministration extends Administration {
|
|
|
958
1269
|
};
|
|
959
1270
|
constructor(source2 = []) {
|
|
960
1271
|
super(source2);
|
|
961
|
-
this.valuesMap = new SignalMap();
|
|
1272
|
+
this.valuesMap = new SignalMap(this.atom);
|
|
962
1273
|
this.keysAtom = createAtom();
|
|
963
1274
|
}
|
|
964
|
-
reportObserveDeep() {
|
|
965
|
-
for (let i = 0; i < this.source.length; i++) {
|
|
966
|
-
const value = this.source[i];
|
|
967
|
-
if (value && typeof value === "object") {
|
|
968
|
-
getAdministration(getObservable(value))?.reportObserved();
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
1275
|
getNode(key) {
|
|
973
1276
|
if (key == null) {
|
|
974
1277
|
return this.atom;
|
|
@@ -978,49 +1281,98 @@ class ArrayAdministration extends Administration {
|
|
|
978
1281
|
get(index) {
|
|
979
1282
|
this.atom.reportObserved();
|
|
980
1283
|
this.valuesMap.reportObserved(index, this.source[index]);
|
|
981
|
-
return
|
|
1284
|
+
return this._getEffectiveValue(index);
|
|
1285
|
+
}
|
|
1286
|
+
_getEffectiveValue(index) {
|
|
1287
|
+
const value = this.source[index];
|
|
1288
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
1289
|
+
if (this.explicitObservables.has(index)) {
|
|
1290
|
+
const existingAdm = getAdministration(value);
|
|
1291
|
+
if (existingAdm) {
|
|
1292
|
+
if (existingAdm.proxy !== value) {
|
|
1293
|
+
const desc = Object.getOwnPropertyDescriptor(this.source, index);
|
|
1294
|
+
if (desc && !desc.configurable && !desc.writable) {
|
|
1295
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1296
|
+
console.warn(
|
|
1297
|
+
`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.`
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
this.explicitObservables.delete(index);
|
|
1301
|
+
return value;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
return existingAdm.proxy;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
return value;
|
|
982
1309
|
}
|
|
983
1310
|
set(index, newValue) {
|
|
984
1311
|
const values = this.source;
|
|
985
1312
|
const targetValue = getSource(newValue);
|
|
986
|
-
|
|
1313
|
+
const oldLength = values.length;
|
|
1314
|
+
let changed = true;
|
|
1315
|
+
if (index < oldLength) {
|
|
987
1316
|
const oldValue = values[index];
|
|
988
|
-
const
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1317
|
+
const oldExplicit = this.explicitObservables.has(index);
|
|
1318
|
+
const newExplicit = isObservable(newValue);
|
|
1319
|
+
changed = !isObservable(oldValue) && oldExplicit !== newExplicit || (isObservable(oldValue) ? newValue !== oldValue : targetValue !== oldValue);
|
|
1320
|
+
}
|
|
1321
|
+
if (!changed) return true;
|
|
1322
|
+
const result = Reflect.set(values, index, targetValue);
|
|
1323
|
+
if (!result) return false;
|
|
1324
|
+
const newLength = values.length;
|
|
1325
|
+
const lengthChanged = newLength !== oldLength;
|
|
1326
|
+
if (isObservable(newValue)) {
|
|
1327
|
+
this.explicitObservables.add(index);
|
|
995
1328
|
} else {
|
|
996
|
-
|
|
997
|
-
`Index out of bounds, ${index} is larger than ${values.length}`
|
|
998
|
-
);
|
|
1329
|
+
this.explicitObservables.delete(index);
|
|
999
1330
|
}
|
|
1331
|
+
this.onArrayChanged(lengthChanged, index, 1);
|
|
1332
|
+
return true;
|
|
1000
1333
|
}
|
|
1001
1334
|
getArrayLength() {
|
|
1002
1335
|
this.atom.reportObserved();
|
|
1003
1336
|
this.keysAtom.reportObserved();
|
|
1004
1337
|
return this.source.length;
|
|
1005
1338
|
}
|
|
1006
|
-
setArrayLength(
|
|
1007
|
-
|
|
1008
|
-
|
|
1339
|
+
setArrayLength(input) {
|
|
1340
|
+
const num = Number(input);
|
|
1341
|
+
const coerced = num >>> 0;
|
|
1342
|
+
if (coerced !== num) {
|
|
1343
|
+
throw new RangeError("Invalid array length");
|
|
1344
|
+
}
|
|
1345
|
+
const newLength = coerced;
|
|
1009
1346
|
const currentLength = this.source.length;
|
|
1010
|
-
if (newLength === currentLength) return;
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1347
|
+
if (newLength === currentLength) return true;
|
|
1348
|
+
const result = Reflect.set(this.source, "length", newLength);
|
|
1349
|
+
if (!result) return false;
|
|
1350
|
+
if (newLength < currentLength) {
|
|
1351
|
+
const toRemove = [];
|
|
1352
|
+
for (const index of this.explicitObservables) {
|
|
1353
|
+
if (index >= newLength) {
|
|
1354
|
+
toRemove.push(index);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
for (const index of toRemove) {
|
|
1358
|
+
this.explicitObservables.delete(index);
|
|
1359
|
+
}
|
|
1360
|
+
this.onArrayChanged(true, newLength, currentLength - newLength);
|
|
1361
|
+
} else {
|
|
1362
|
+
this.onArrayChanged(true, currentLength, newLength - currentLength);
|
|
1363
|
+
}
|
|
1364
|
+
return true;
|
|
1017
1365
|
}
|
|
1018
1366
|
spliceWithArray(index, deleteCount, newItems) {
|
|
1019
1367
|
const length = this.source.length;
|
|
1020
1368
|
const newTargetItems = [];
|
|
1369
|
+
const newObservableIndices = [];
|
|
1021
1370
|
if (newItems) {
|
|
1022
1371
|
for (let i = 0; i < newItems.length; i++) {
|
|
1023
1372
|
newTargetItems[i] = getSource(newItems[i]);
|
|
1373
|
+
if (isObservable(newItems[i])) {
|
|
1374
|
+
newObservableIndices.push(i);
|
|
1375
|
+
}
|
|
1024
1376
|
}
|
|
1025
1377
|
}
|
|
1026
1378
|
if (index === void 0) index = 0;
|
|
@@ -1029,15 +1381,39 @@ class ArrayAdministration extends Administration {
|
|
|
1029
1381
|
if (arguments.length === 1) deleteCount = length - index;
|
|
1030
1382
|
else if (deleteCount === void 0 || deleteCount === null) deleteCount = 0;
|
|
1031
1383
|
else deleteCount = Math.max(0, Math.min(deleteCount, length - index));
|
|
1032
|
-
const
|
|
1384
|
+
const removedItems = [];
|
|
1385
|
+
for (let i = index; i < index + deleteCount; i++) {
|
|
1386
|
+
removedItems.push(this._getEffectiveValue(i));
|
|
1387
|
+
}
|
|
1388
|
+
for (let i = index; i < index + deleteCount; i++) {
|
|
1389
|
+
this.explicitObservables.delete(i);
|
|
1390
|
+
}
|
|
1391
|
+
const shift = (newItems?.length ?? 0) - deleteCount;
|
|
1392
|
+
if (shift !== 0) {
|
|
1393
|
+
const newExplicitObservables = /* @__PURE__ */ new Set();
|
|
1394
|
+
for (const idx of this.explicitObservables) {
|
|
1395
|
+
if (idx < index) {
|
|
1396
|
+
newExplicitObservables.add(idx);
|
|
1397
|
+
} else if (idx >= index + deleteCount) {
|
|
1398
|
+
newExplicitObservables.add(idx + shift);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
this.explicitObservables.clear();
|
|
1402
|
+
for (const idx of newExplicitObservables) {
|
|
1403
|
+
this.explicitObservables.add(idx);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
for (const relativeIdx of newObservableIndices) {
|
|
1407
|
+
this.explicitObservables.add(index + relativeIdx);
|
|
1408
|
+
}
|
|
1409
|
+
this.spliceItemsIntoValues(index, deleteCount, newTargetItems);
|
|
1033
1410
|
if (deleteCount !== 0 || newTargetItems.length !== 0) {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
);
|
|
1411
|
+
const shift2 = (newItems?.length ?? 0) - deleteCount;
|
|
1412
|
+
const reindexing = shift2 !== 0 && index + deleteCount < length;
|
|
1413
|
+
const count = reindexing ? Number.POSITIVE_INFINITY : Math.max(deleteCount ?? 0, newItems?.length ?? 0);
|
|
1414
|
+
this.onArrayChanged(length !== this.source.length, index, count);
|
|
1039
1415
|
}
|
|
1040
|
-
return
|
|
1416
|
+
return removedItems;
|
|
1041
1417
|
}
|
|
1042
1418
|
spliceItemsIntoValues(index, deleteCount, newItems) {
|
|
1043
1419
|
return this.source.splice.apply(
|
|
@@ -1052,9 +1428,16 @@ class ArrayAdministration extends Administration {
|
|
|
1052
1428
|
}
|
|
1053
1429
|
if (index == null) {
|
|
1054
1430
|
this.atom.reportChanged();
|
|
1055
|
-
} else {
|
|
1056
|
-
|
|
1057
|
-
|
|
1431
|
+
} else if (count !== void 0 && count > 0) {
|
|
1432
|
+
const observedKeys = this.valuesMap.keys();
|
|
1433
|
+
const end = index + count;
|
|
1434
|
+
for (const key of observedKeys) {
|
|
1435
|
+
if (typeof key === "number" && key >= index && key < end) {
|
|
1436
|
+
const node = this.valuesMap.get(key);
|
|
1437
|
+
if (node) {
|
|
1438
|
+
node.reportChanged(this._getEffectiveValue(key));
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1058
1441
|
}
|
|
1059
1442
|
}
|
|
1060
1443
|
this.flushChange();
|
|
@@ -1070,7 +1453,7 @@ function createMethod(method, func) {
|
|
|
1070
1453
|
function createStringMethod(method) {
|
|
1071
1454
|
return createMethod(method, function() {
|
|
1072
1455
|
const adm = getAdministration(this);
|
|
1073
|
-
adm.reportObserved(
|
|
1456
|
+
adm.reportObserved();
|
|
1074
1457
|
const sourceArr = getSource(this);
|
|
1075
1458
|
return sourceArr[method].apply(sourceArr, arguments);
|
|
1076
1459
|
});
|
|
@@ -1078,7 +1461,7 @@ function createStringMethod(method) {
|
|
|
1078
1461
|
function createSearchMethod(method) {
|
|
1079
1462
|
return createMethod(method, function() {
|
|
1080
1463
|
const adm = getAdministration(this);
|
|
1081
|
-
adm.reportObserved(
|
|
1464
|
+
adm.reportObserved();
|
|
1082
1465
|
const target = arguments[0];
|
|
1083
1466
|
const source2 = getSource(target);
|
|
1084
1467
|
const sourceArr = getSource(this);
|
|
@@ -1094,10 +1477,38 @@ function createSearchMethod(method) {
|
|
|
1094
1477
|
function createCopyMethod(method) {
|
|
1095
1478
|
return createMethod(method, function() {
|
|
1096
1479
|
const adm = getAdministration(this);
|
|
1097
|
-
adm.reportObserved(
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
);
|
|
1480
|
+
adm.reportObserved();
|
|
1481
|
+
const observedInput = [];
|
|
1482
|
+
observedInput.length = adm.source.length;
|
|
1483
|
+
const keys = Object.keys(adm.source);
|
|
1484
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1485
|
+
const key = keys[i];
|
|
1486
|
+
const idx = Number(key);
|
|
1487
|
+
if (!Number.isNaN(idx)) {
|
|
1488
|
+
observedInput[idx] = this[idx];
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
const args = Array.from(arguments);
|
|
1492
|
+
if (method === "concat") {
|
|
1493
|
+
for (let i = 0; i < args.length; i++) {
|
|
1494
|
+
const arg = args[i];
|
|
1495
|
+
if (Array.isArray(arg) && isObservable(arg)) {
|
|
1496
|
+
const argAdm = getAdministration(arg);
|
|
1497
|
+
const argObserved = [];
|
|
1498
|
+
argObserved.length = argAdm.source.length;
|
|
1499
|
+
const argKeys = Object.keys(argAdm.source);
|
|
1500
|
+
for (let j = 0; j < argKeys.length; j++) {
|
|
1501
|
+
const argKey = argKeys[j];
|
|
1502
|
+
const argIdx = Number(argKey);
|
|
1503
|
+
if (!Number.isNaN(argIdx)) {
|
|
1504
|
+
argObserved[argIdx] = arg[argIdx];
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
args[i] = argObserved;
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
return Array.prototype[method].apply(observedInput, args);
|
|
1101
1512
|
});
|
|
1102
1513
|
}
|
|
1103
1514
|
function createMapMethod(method) {
|
|
@@ -1105,14 +1516,9 @@ function createMapMethod(method) {
|
|
|
1105
1516
|
method,
|
|
1106
1517
|
function(callback, thisArg) {
|
|
1107
1518
|
const adm = getAdministration(this);
|
|
1108
|
-
adm.reportObserved(
|
|
1109
|
-
return adm.source[method]((
|
|
1110
|
-
return callback.call(
|
|
1111
|
-
thisArg,
|
|
1112
|
-
element && typeof element === "object" ? getObservable(element) : element,
|
|
1113
|
-
index,
|
|
1114
|
-
this
|
|
1115
|
-
);
|
|
1519
|
+
adm.reportObserved();
|
|
1520
|
+
return adm.source[method]((_element, index) => {
|
|
1521
|
+
return callback.call(thisArg, this[index], index, this);
|
|
1116
1522
|
});
|
|
1117
1523
|
}
|
|
1118
1524
|
);
|
|
@@ -1122,28 +1528,17 @@ function createFilterMethod(method) {
|
|
|
1122
1528
|
method,
|
|
1123
1529
|
function(callback, thisArg) {
|
|
1124
1530
|
const adm = getAdministration(this);
|
|
1125
|
-
adm.reportObserved(
|
|
1126
|
-
return
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
thisArg,
|
|
1130
|
-
element && typeof element === "object" ? getObservable(element) : element,
|
|
1131
|
-
index,
|
|
1132
|
-
this
|
|
1133
|
-
);
|
|
1134
|
-
})
|
|
1135
|
-
);
|
|
1531
|
+
adm.reportObserved();
|
|
1532
|
+
return adm.source[method]((_element, index) => {
|
|
1533
|
+
return callback.call(thisArg, this[index], index, this);
|
|
1534
|
+
});
|
|
1136
1535
|
}
|
|
1137
1536
|
);
|
|
1138
1537
|
}
|
|
1139
1538
|
function createReduceMethod(method) {
|
|
1140
1539
|
return createMethod(method, function() {
|
|
1141
1540
|
const adm = getAdministration(this);
|
|
1142
|
-
adm.reportObserved(
|
|
1143
|
-
const callback = arguments[0];
|
|
1144
|
-
arguments[0] = (accumulator, currentValue, index) => {
|
|
1145
|
-
return callback(accumulator, getObservable(currentValue), index, this);
|
|
1146
|
-
};
|
|
1541
|
+
adm.reportObserved();
|
|
1147
1542
|
return adm.source[method].apply(adm.source, arguments);
|
|
1148
1543
|
});
|
|
1149
1544
|
}
|
|
@@ -1170,6 +1565,7 @@ function addDateSetMethod(method) {
|
|
|
1170
1565
|
const adm = getAdministration(this);
|
|
1171
1566
|
const res = adm.source[method].apply(adm.source, arguments);
|
|
1172
1567
|
adm.atom.reportChanged();
|
|
1568
|
+
adm.flushChange();
|
|
1173
1569
|
return res;
|
|
1174
1570
|
};
|
|
1175
1571
|
}
|
|
@@ -1205,9 +1601,15 @@ function getAction(fn) {
|
|
|
1205
1601
|
}
|
|
1206
1602
|
function getObservableClassInstance(value) {
|
|
1207
1603
|
const adm = new PreactObjectAdministration(value);
|
|
1604
|
+
administrationMap.set(adm.proxy, adm);
|
|
1208
1605
|
administrationMap.set(adm.source, adm);
|
|
1209
1606
|
return adm.proxy;
|
|
1210
1607
|
}
|
|
1608
|
+
class Observable {
|
|
1609
|
+
constructor() {
|
|
1610
|
+
return getObservableClassInstance(this);
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1211
1613
|
function createObservableWithCustomAdministration(value, Adm) {
|
|
1212
1614
|
const adm = new Adm(value);
|
|
1213
1615
|
administrationMap.set(adm.proxy, adm);
|
|
@@ -1218,28 +1620,47 @@ function getObservable(value) {
|
|
|
1218
1620
|
if (!value) {
|
|
1219
1621
|
return value;
|
|
1220
1622
|
}
|
|
1221
|
-
const
|
|
1222
|
-
if (
|
|
1223
|
-
return
|
|
1623
|
+
const existingAdm = getAdministration(value);
|
|
1624
|
+
if (existingAdm) {
|
|
1625
|
+
return existingAdm.proxy;
|
|
1224
1626
|
}
|
|
1225
|
-
if (
|
|
1627
|
+
if (typeof value === "function") {
|
|
1628
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1629
|
+
console.warn(
|
|
1630
|
+
`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.`
|
|
1631
|
+
);
|
|
1632
|
+
}
|
|
1633
|
+
return value;
|
|
1634
|
+
}
|
|
1635
|
+
if (typeof value === "object") {
|
|
1226
1636
|
const obj = value;
|
|
1227
|
-
let Adm =
|
|
1228
|
-
if (
|
|
1229
|
-
Adm = ArrayAdministration;
|
|
1230
|
-
} else if (obj instanceof Map || obj instanceof WeakMap) {
|
|
1637
|
+
let Adm = null;
|
|
1638
|
+
if (obj instanceof Map || obj instanceof WeakMap) {
|
|
1231
1639
|
Adm = CollectionAdministration;
|
|
1232
1640
|
} else if (obj instanceof Set || obj instanceof WeakSet) {
|
|
1233
1641
|
Adm = CollectionAdministration;
|
|
1234
1642
|
} else if (obj instanceof Date) {
|
|
1235
1643
|
Adm = DateAdministration;
|
|
1236
|
-
} else if (!
|
|
1237
|
-
|
|
1644
|
+
} else if (!Object.isFrozen(obj)) {
|
|
1645
|
+
if (Array.isArray(obj)) {
|
|
1646
|
+
Adm = ArrayAdministration;
|
|
1647
|
+
} else if (isPlainObject(obj)) {
|
|
1648
|
+
Adm = PreactObjectAdministration;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
if (Adm) {
|
|
1652
|
+
const adm = new Adm(obj);
|
|
1653
|
+
administrationMap.set(adm.proxy, adm);
|
|
1654
|
+
administrationMap.set(adm.source, adm);
|
|
1655
|
+
return adm.proxy;
|
|
1656
|
+
}
|
|
1657
|
+
if (process.env.NODE_ENV !== "production" && !Object.isFrozen(obj)) {
|
|
1658
|
+
const proto = Object.getPrototypeOf(obj);
|
|
1659
|
+
const typeName = proto?.constructor?.name && proto.constructor.name !== "Object" ? `instance of ${proto.constructor.name}` : "non-plain object";
|
|
1660
|
+
console.warn(
|
|
1661
|
+
`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'.`
|
|
1662
|
+
);
|
|
1238
1663
|
}
|
|
1239
|
-
const adm2 = new Adm(obj);
|
|
1240
|
-
administrationMap.set(adm2.proxy, adm2);
|
|
1241
|
-
administrationMap.set(adm2.source, adm2);
|
|
1242
|
-
return adm2.proxy;
|
|
1243
1664
|
}
|
|
1244
1665
|
return value;
|
|
1245
1666
|
}
|
|
@@ -1268,19 +1689,77 @@ function getPropertyDescriptor(obj, key) {
|
|
|
1268
1689
|
}
|
|
1269
1690
|
return void 0;
|
|
1270
1691
|
}
|
|
1271
|
-
function clone(val) {
|
|
1272
|
-
if (
|
|
1273
|
-
return val
|
|
1274
|
-
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1692
|
+
function clone(val, path = "") {
|
|
1693
|
+
if (val === null || val === void 0) {
|
|
1694
|
+
return val;
|
|
1695
|
+
}
|
|
1696
|
+
if (typeof val !== "object") {
|
|
1697
|
+
if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
|
|
1698
|
+
return val;
|
|
1699
|
+
}
|
|
1700
|
+
const atPath = path ? ` at path "${path}"` : "";
|
|
1701
|
+
if (typeof val === "bigint") {
|
|
1702
|
+
throw new Error(
|
|
1703
|
+
`r-state-tree: snapshots do not support bigint${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
|
|
1704
|
+
);
|
|
1280
1705
|
}
|
|
1281
|
-
|
|
1706
|
+
if (typeof val === "symbol") {
|
|
1707
|
+
throw new Error(
|
|
1708
|
+
`r-state-tree: snapshots do not support symbol${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1711
|
+
if (typeof val === "function") {
|
|
1712
|
+
throw new Error(
|
|
1713
|
+
`r-state-tree: snapshots do not support function${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
throw new Error(
|
|
1717
|
+
`r-state-tree: snapshots do not support ${typeof val}${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
|
|
1718
|
+
);
|
|
1282
1719
|
}
|
|
1283
|
-
|
|
1720
|
+
if (val instanceof Signal) {
|
|
1721
|
+
return clone(
|
|
1722
|
+
val.value,
|
|
1723
|
+
path
|
|
1724
|
+
);
|
|
1725
|
+
}
|
|
1726
|
+
if (val instanceof Date) {
|
|
1727
|
+
return val.toISOString();
|
|
1728
|
+
}
|
|
1729
|
+
if (Array.isArray(val)) {
|
|
1730
|
+
return val.map(
|
|
1731
|
+
(v, i) => clone(v, path ? `${path}[${i}]` : `[${i}]`)
|
|
1732
|
+
);
|
|
1733
|
+
}
|
|
1734
|
+
if (!isPlainObject(val)) {
|
|
1735
|
+
const typeName = getTypeName(val);
|
|
1736
|
+
const atPath = path ? ` at path "${path}"` : "";
|
|
1737
|
+
throw new Error(
|
|
1738
|
+
`r-state-tree: snapshots do not support ${typeName}${atPath}. Snapshots are JSON-only (primitives, arrays, plain objects, Dates as ISO strings).`
|
|
1739
|
+
);
|
|
1740
|
+
}
|
|
1741
|
+
const keys = Object.keys(val);
|
|
1742
|
+
const cloned = {};
|
|
1743
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1744
|
+
const key = keys[i];
|
|
1745
|
+
const keyPath = path ? `${path}.${key}` : key;
|
|
1746
|
+
cloned[key] = clone(val[key], keyPath);
|
|
1747
|
+
}
|
|
1748
|
+
return cloned;
|
|
1749
|
+
}
|
|
1750
|
+
function getTypeName(val) {
|
|
1751
|
+
if (val instanceof Map) return "Map";
|
|
1752
|
+
if (val instanceof Set) return "Set";
|
|
1753
|
+
if (val instanceof WeakMap) return "WeakMap";
|
|
1754
|
+
if (val instanceof WeakSet) return "WeakSet";
|
|
1755
|
+
if (val instanceof RegExp) return "RegExp";
|
|
1756
|
+
if (val instanceof Error) return "Error";
|
|
1757
|
+
if (val instanceof Promise) return "Promise";
|
|
1758
|
+
const proto = Object.getPrototypeOf(val);
|
|
1759
|
+
if (proto?.constructor?.name && proto.constructor.name !== "Object") {
|
|
1760
|
+
return `class instance (${proto.constructor.name})`;
|
|
1761
|
+
}
|
|
1762
|
+
return "non-plain object";
|
|
1284
1763
|
}
|
|
1285
1764
|
function getDiff(o1, o2, getConfig) {
|
|
1286
1765
|
const config = getConfig(o2);
|
|
@@ -1316,6 +1795,33 @@ function getDiff(o1, o2, getConfig) {
|
|
|
1316
1795
|
}
|
|
1317
1796
|
return Object.keys(diff).length > 0 ? diff : null;
|
|
1318
1797
|
}
|
|
1798
|
+
const MAX_MOUNT_DEPTH = 100;
|
|
1799
|
+
const mountingStack = [];
|
|
1800
|
+
function formatMountFrame(frame) {
|
|
1801
|
+
const childSegment = frame.childName === void 0 ? "" : `.${String(frame.childName)}`;
|
|
1802
|
+
return `${frame.storeName}${childSegment}`;
|
|
1803
|
+
}
|
|
1804
|
+
function formatMountChain(frame) {
|
|
1805
|
+
const chain = [...mountingStack, frame];
|
|
1806
|
+
const maxParts = 6;
|
|
1807
|
+
if (chain.length > maxParts) {
|
|
1808
|
+
const start = chain.slice(0, 3);
|
|
1809
|
+
const end = chain.slice(-2);
|
|
1810
|
+
return [
|
|
1811
|
+
...start,
|
|
1812
|
+
{ storeName: "...", modelsKeys: [], childName: void 0 },
|
|
1813
|
+
...end
|
|
1814
|
+
].map(formatMountFrame).join(" -> ");
|
|
1815
|
+
}
|
|
1816
|
+
return chain.map(formatMountFrame).join(" -> ");
|
|
1817
|
+
}
|
|
1818
|
+
function createCircularMountError(frame) {
|
|
1819
|
+
const chain = formatMountChain(frame);
|
|
1820
|
+
const models = frame.modelsKeys.length === 0 ? "no models provided" : `models: ${frame.modelsKeys.join(", ")}`;
|
|
1821
|
+
return new Error(
|
|
1822
|
+
`r-state-tree: detected circular store/model creation while mounting ${chain} (using ${models}). Passing models into child stores during mount can create recursive wiring. Move child store/model creation into storeDidMount or break the cycle.`
|
|
1823
|
+
);
|
|
1824
|
+
}
|
|
1319
1825
|
function updateProps(props, newProps) {
|
|
1320
1826
|
untracked(() => {
|
|
1321
1827
|
batch(() => {
|
|
@@ -1326,7 +1832,9 @@ function updateProps(props, newProps) {
|
|
|
1326
1832
|
}
|
|
1327
1833
|
});
|
|
1328
1834
|
if (newProps.models) {
|
|
1329
|
-
if (!props.models
|
|
1835
|
+
if (!props.models || !isObservable(props.models)) {
|
|
1836
|
+
props.models = getObservable(props.models || {});
|
|
1837
|
+
}
|
|
1330
1838
|
Object.assign(props.models, newProps.models);
|
|
1331
1839
|
}
|
|
1332
1840
|
});
|
|
@@ -1335,6 +1843,35 @@ function updateProps(props, newProps) {
|
|
|
1335
1843
|
function getStoreAdm(store) {
|
|
1336
1844
|
return getAdministration(store);
|
|
1337
1845
|
}
|
|
1846
|
+
function validateStoreChildValue(value, propertyName) {
|
|
1847
|
+
if (value === null || value === void 0) {
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
if (Array.isArray(value)) {
|
|
1851
|
+
const invalidItem = value.find(
|
|
1852
|
+
(item) => item !== null && (typeof item !== "object" || !("Type" in item) || !("props" in item) || typeof item.Type !== "function" || typeof item.props !== "object")
|
|
1853
|
+
);
|
|
1854
|
+
if (invalidItem !== void 0) {
|
|
1855
|
+
throw new Error(
|
|
1856
|
+
`r-state-tree: child property '${String(
|
|
1857
|
+
propertyName
|
|
1858
|
+
)}' must be a StoreElement ({ Type, props, key }), an array of StoreElements, or null/undefined. Found invalid array item: ${typeof invalidItem}`
|
|
1859
|
+
);
|
|
1860
|
+
}
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
if (typeof value === "object" && value !== null && "Type" in value && "props" in value) {
|
|
1864
|
+
const element = value;
|
|
1865
|
+
if (typeof element.Type === "function" && typeof element.props === "object") {
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
throw new Error(
|
|
1870
|
+
`r-state-tree: child property '${String(
|
|
1871
|
+
propertyName
|
|
1872
|
+
)}' must be a StoreElement ({ Type, props, key }), an array of StoreElements, or null/undefined. Found: ${typeof value}`
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1338
1875
|
class StoreAdministration extends PreactObjectAdministration {
|
|
1339
1876
|
static proxyTraps = Object.assign(
|
|
1340
1877
|
{},
|
|
@@ -1402,7 +1939,7 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
1402
1939
|
}
|
|
1403
1940
|
});
|
|
1404
1941
|
childStoreData.value.set(stores);
|
|
1405
|
-
stores.forEach((s) => getStoreAdm(s).mount(this));
|
|
1942
|
+
stores.forEach((s) => getStoreAdm(s).mount(this, name));
|
|
1406
1943
|
return stores;
|
|
1407
1944
|
}
|
|
1408
1945
|
const newStores = /* @__PURE__ */ new Set();
|
|
@@ -1453,7 +1990,7 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
1453
1990
|
batch(() => childStoreData.value.set(stores));
|
|
1454
1991
|
}
|
|
1455
1992
|
removedStores.forEach((s) => getStoreAdm(s).unmount());
|
|
1456
|
-
newStores.forEach((s) => getStoreAdm(s).mount(this));
|
|
1993
|
+
newStores.forEach((s) => getStoreAdm(s).mount(this, name));
|
|
1457
1994
|
return stores;
|
|
1458
1995
|
}
|
|
1459
1996
|
setSingleStore(name, element) {
|
|
@@ -1472,7 +2009,7 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
1472
2009
|
}
|
|
1473
2010
|
const childStore = this.createChildStore(element);
|
|
1474
2011
|
batch(() => childStoreData.value.set(childStore));
|
|
1475
|
-
getStoreAdm(childStore).mount(this);
|
|
2012
|
+
getStoreAdm(childStore).mount(this, name);
|
|
1476
2013
|
return childStore;
|
|
1477
2014
|
} else {
|
|
1478
2015
|
batch(() => updateProps(oldStore.props, props));
|
|
@@ -1484,6 +2021,7 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
1484
2021
|
const storeElement = childStoreData.listener.track(
|
|
1485
2022
|
() => childStoreData.computed.get()
|
|
1486
2023
|
);
|
|
2024
|
+
validateStoreChildValue(storeElement, name);
|
|
1487
2025
|
Array.isArray(storeElement) ? this.setStoreList(name, storeElement) : this.setSingleStore(name, storeElement);
|
|
1488
2026
|
}
|
|
1489
2027
|
getComputedGetter(name) {
|
|
@@ -1504,6 +2042,7 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
1504
2042
|
const storeElement = childStoreData.listener.track(
|
|
1505
2043
|
() => childStoreData.computed.get()
|
|
1506
2044
|
);
|
|
2045
|
+
validateStoreChildValue(storeElement, name);
|
|
1507
2046
|
Array.isArray(storeElement) ? this.setStoreList(name, storeElement) : this.setSingleStore(name, storeElement);
|
|
1508
2047
|
return childStoreData.value.get();
|
|
1509
2048
|
}
|
|
@@ -1513,12 +2052,15 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
1513
2052
|
return this.initializeStore(name);
|
|
1514
2053
|
} else {
|
|
1515
2054
|
const storeElement = untracked(() => childStoreData.computed.get());
|
|
2055
|
+
validateStoreChildValue(storeElement, name);
|
|
1516
2056
|
Array.isArray(storeElement) ? this.setStoreList(name, storeElement) : this.setSingleStore(name, storeElement);
|
|
1517
2057
|
return childStoreData.value.get();
|
|
1518
2058
|
}
|
|
1519
2059
|
}
|
|
1520
2060
|
getModelRef(name) {
|
|
1521
|
-
|
|
2061
|
+
const models = this.proxy.props.models;
|
|
2062
|
+
const ref = models?.[name] ?? null;
|
|
2063
|
+
return ref;
|
|
1522
2064
|
}
|
|
1523
2065
|
isRoot() {
|
|
1524
2066
|
return !this.parent;
|
|
@@ -1561,18 +2103,36 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
1561
2103
|
this.reactionsUnsub.push(unsub);
|
|
1562
2104
|
return unsub;
|
|
1563
2105
|
}
|
|
1564
|
-
mount(parent = null) {
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
2106
|
+
mount(parent = null, childName) {
|
|
2107
|
+
const frame = {
|
|
2108
|
+
storeName: this.proxy.constructor.name || "Store",
|
|
2109
|
+
childName,
|
|
2110
|
+
modelsKeys: Object.keys(this.proxy.props?.models ?? {})
|
|
2111
|
+
};
|
|
2112
|
+
if (mountingStack.length + 1 > MAX_MOUNT_DEPTH) {
|
|
2113
|
+
throw createCircularMountError(frame);
|
|
2114
|
+
}
|
|
2115
|
+
mountingStack.push(frame);
|
|
2116
|
+
try {
|
|
2117
|
+
this.parent = parent || null;
|
|
2118
|
+
this.childStoreDataMap.forEach(({ value }, name) => {
|
|
2119
|
+
const stores = value.get();
|
|
2120
|
+
if (Array.isArray(stores)) {
|
|
2121
|
+
stores?.forEach((s) => getStoreAdm(s)?.mount(this, name));
|
|
2122
|
+
} else if (stores) {
|
|
2123
|
+
getStoreAdm(stores)?.mount(this, name);
|
|
2124
|
+
}
|
|
2125
|
+
});
|
|
2126
|
+
this.mounted = true;
|
|
2127
|
+
batch(() => this.proxy.storeDidMount?.());
|
|
2128
|
+
} catch (error) {
|
|
2129
|
+
if (error instanceof RangeError && /call stack/i.test(error.message)) {
|
|
2130
|
+
throw createCircularMountError(frame);
|
|
1572
2131
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
2132
|
+
throw error;
|
|
2133
|
+
} finally {
|
|
2134
|
+
mountingStack.pop();
|
|
2135
|
+
}
|
|
1576
2136
|
}
|
|
1577
2137
|
unmount() {
|
|
1578
2138
|
this.proxy.storeWillUnmount?.();
|
|
@@ -1838,11 +2398,12 @@ class ObservableListener {
|
|
|
1838
2398
|
class ChildModelsAdministration extends ArrayAdministration {
|
|
1839
2399
|
set(index, newValue) {
|
|
1840
2400
|
return batch(() => {
|
|
1841
|
-
super.set(index, newValue);
|
|
2401
|
+
const result = super.set(index, newValue);
|
|
1842
2402
|
const sourceValue = getSource(newValue);
|
|
1843
2403
|
if (this.source[index] !== sourceValue) {
|
|
1844
2404
|
notifyArrayUpdate(this.proxy, index, this.source[index], sourceValue);
|
|
1845
2405
|
}
|
|
2406
|
+
return result;
|
|
1846
2407
|
});
|
|
1847
2408
|
}
|
|
1848
2409
|
spliceWithArray(index, deleteCount, newItems) {
|
|
@@ -1875,7 +2436,19 @@ function getIdKey(Ctor) {
|
|
|
1875
2436
|
function getModelRefSnapshot(modelRef2) {
|
|
1876
2437
|
const Ctor = Object.getPrototypeOf(modelRef2).constructor;
|
|
1877
2438
|
const idKey = getIdKey(Ctor);
|
|
1878
|
-
|
|
2439
|
+
if (!idKey) return null;
|
|
2440
|
+
let id2 = getIdentifier(modelRef2);
|
|
2441
|
+
if (id2 === void 0) {
|
|
2442
|
+
const source2 = getSource(modelRef2);
|
|
2443
|
+
id2 = getIdentifier(source2);
|
|
2444
|
+
if (id2 === void 0) {
|
|
2445
|
+
const adm = getAdministration(modelRef2);
|
|
2446
|
+
if (adm && adm.proxy !== modelRef2) {
|
|
2447
|
+
id2 = getIdentifier(adm.proxy);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
return { [idKey]: id2 };
|
|
1879
2452
|
}
|
|
1880
2453
|
function getSnapshotId(snapshot, Ctor) {
|
|
1881
2454
|
const idKey = getIdKey(Ctor);
|
|
@@ -1890,6 +2463,30 @@ function getSnapshotRefId(snapshot) {
|
|
|
1890
2463
|
}
|
|
1891
2464
|
return snapshot[keys[0]];
|
|
1892
2465
|
}
|
|
2466
|
+
function validateModelChildValue(value, propertyName) {
|
|
2467
|
+
if (value === null || value === void 0) {
|
|
2468
|
+
return;
|
|
2469
|
+
}
|
|
2470
|
+
if (value instanceof Model) {
|
|
2471
|
+
return;
|
|
2472
|
+
}
|
|
2473
|
+
if (Array.isArray(value)) {
|
|
2474
|
+
const invalidItem = value.find((item) => !(item instanceof Model));
|
|
2475
|
+
if (invalidItem !== void 0) {
|
|
2476
|
+
throw new Error(
|
|
2477
|
+
`r-state-tree: child property '${String(
|
|
2478
|
+
propertyName
|
|
2479
|
+
)}' must be a Model instance, an array of Model instances, or null/undefined. Found invalid array item: ${typeof invalidItem}`
|
|
2480
|
+
);
|
|
2481
|
+
}
|
|
2482
|
+
return;
|
|
2483
|
+
}
|
|
2484
|
+
throw new Error(
|
|
2485
|
+
`r-state-tree: child property '${String(
|
|
2486
|
+
propertyName
|
|
2487
|
+
)}' must be a Model instance, an array of Model instances, or null/undefined. Found: ${typeof value}`
|
|
2488
|
+
);
|
|
2489
|
+
}
|
|
1893
2490
|
class ModelAdministration extends PreactObjectAdministration {
|
|
1894
2491
|
static proxyTraps = Object.assign(
|
|
1895
2492
|
{},
|
|
@@ -1923,6 +2520,7 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
1923
2520
|
return true;
|
|
1924
2521
|
}
|
|
1925
2522
|
case CommonCfgTypes.child: {
|
|
2523
|
+
validateModelChildValue(value, name);
|
|
1926
2524
|
if (Array.isArray(value)) {
|
|
1927
2525
|
adm.setModels(name, value);
|
|
1928
2526
|
return true;
|
|
@@ -1974,9 +2572,60 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
1974
2572
|
modelsTraceUnsub = /* @__PURE__ */ new Map();
|
|
1975
2573
|
writeInProgress = /* @__PURE__ */ new Set();
|
|
1976
2574
|
computedSnapshot;
|
|
2575
|
+
snapshotAtom = createAtom();
|
|
1977
2576
|
snapshotMap = /* @__PURE__ */ new Map();
|
|
1978
2577
|
contextCache = /* @__PURE__ */ new Map();
|
|
1979
2578
|
parentName = null;
|
|
2579
|
+
/**
|
|
2580
|
+
* `@state` fields are shallow-reactive (property-level assignment triggers reactivity)
|
|
2581
|
+
* and participate in snapshots. Values stored in `@state` are not deep-wrapped.
|
|
2582
|
+
*
|
|
2583
|
+
* This helper walks a value and:
|
|
2584
|
+
* - observes any observable containers found (proxy or source) so in-place mutations
|
|
2585
|
+
* invalidate `getSnapshot()` / `toSnapshot()`
|
|
2586
|
+
* - avoids proxy traversal by preferring `getSource(...)`
|
|
2587
|
+
* - guards against cycles via `WeakSet`
|
|
2588
|
+
*/
|
|
2589
|
+
observeSnapshotValue(value, seen) {
|
|
2590
|
+
if (value == null) return;
|
|
2591
|
+
if (typeof value !== "object") return;
|
|
2592
|
+
if (!seen) seen = /* @__PURE__ */ new WeakSet();
|
|
2593
|
+
const obj = value;
|
|
2594
|
+
if (seen.has(obj)) return;
|
|
2595
|
+
seen.add(obj);
|
|
2596
|
+
const adm = getAdministration(obj);
|
|
2597
|
+
if (adm) {
|
|
2598
|
+
adm.reportObserved();
|
|
2599
|
+
}
|
|
2600
|
+
const src = getSource(value);
|
|
2601
|
+
if (src && typeof src === "object" && src !== value) {
|
|
2602
|
+
this.observeSnapshotValue(src, seen);
|
|
2603
|
+
return;
|
|
2604
|
+
}
|
|
2605
|
+
if (Array.isArray(value)) {
|
|
2606
|
+
for (let i = 0; i < value.length; i++) {
|
|
2607
|
+
this.observeSnapshotValue(value[i], seen);
|
|
2608
|
+
}
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
if (value instanceof Map) {
|
|
2612
|
+
value.forEach((v, k) => {
|
|
2613
|
+
this.observeSnapshotValue(k, seen);
|
|
2614
|
+
this.observeSnapshotValue(v, seen);
|
|
2615
|
+
});
|
|
2616
|
+
return;
|
|
2617
|
+
}
|
|
2618
|
+
if (value instanceof Set) {
|
|
2619
|
+
value.forEach((v) => this.observeSnapshotValue(v, seen));
|
|
2620
|
+
return;
|
|
2621
|
+
}
|
|
2622
|
+
if (value instanceof Date) {
|
|
2623
|
+
return;
|
|
2624
|
+
}
|
|
2625
|
+
for (const key of Object.keys(value)) {
|
|
2626
|
+
this.observeSnapshotValue(value[key], seen);
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
1980
2629
|
get parent() {
|
|
1981
2630
|
this.parentAtom.reportObserved();
|
|
1982
2631
|
return this._parent;
|
|
@@ -2005,12 +2654,15 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2005
2654
|
setState(name, value) {
|
|
2006
2655
|
const oldValue = this.source[name];
|
|
2007
2656
|
if (value !== oldValue) {
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2657
|
+
batch(() => {
|
|
2658
|
+
PreactObjectAdministration.proxyTraps.set(
|
|
2659
|
+
this.source,
|
|
2660
|
+
name,
|
|
2661
|
+
value,
|
|
2662
|
+
this.proxy
|
|
2663
|
+
);
|
|
2664
|
+
this.snapshotAtom.reportChanged();
|
|
2665
|
+
});
|
|
2014
2666
|
}
|
|
2015
2667
|
}
|
|
2016
2668
|
setId(name, v) {
|
|
@@ -2029,6 +2681,7 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2029
2681
|
}
|
|
2030
2682
|
}
|
|
2031
2683
|
setModel(name, newModel) {
|
|
2684
|
+
validateModelChildValue(newModel, name);
|
|
2032
2685
|
const currentValue = this.proxy[name];
|
|
2033
2686
|
if (currentValue === newModel) {
|
|
2034
2687
|
return;
|
|
@@ -2048,6 +2701,7 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2048
2701
|
}
|
|
2049
2702
|
}
|
|
2050
2703
|
setModels(name, newModelsSource) {
|
|
2704
|
+
validateModelChildValue(newModelsSource, name);
|
|
2051
2705
|
const newModels = createObservableWithCustomAdministration(
|
|
2052
2706
|
[],
|
|
2053
2707
|
ChildModelsAdministration
|
|
@@ -2062,9 +2716,9 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2062
2716
|
getModelAdm(currentValue).detach();
|
|
2063
2717
|
} else if (Array.isArray(currentValue)) {
|
|
2064
2718
|
const oldModels = currentValue;
|
|
2065
|
-
const newModelSet = new Set(newModels);
|
|
2719
|
+
const newModelSet = new Set(newModels.map((m) => getSource(m)));
|
|
2066
2720
|
oldModels.forEach(
|
|
2067
|
-
(child2) => newModelSet.has(child2) || getModelAdm(child2).detach()
|
|
2721
|
+
(child2) => newModelSet.has(getSource(child2)) || getModelAdm(child2).detach()
|
|
2068
2722
|
);
|
|
2069
2723
|
this.modelsTraceUnsub.get(name)?.();
|
|
2070
2724
|
}
|
|
@@ -2087,8 +2741,8 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2087
2741
|
})
|
|
2088
2742
|
);
|
|
2089
2743
|
newModels.forEach((child2) => {
|
|
2090
|
-
const oldModelSet = Array.isArray(currentValue) ? new Set(currentValue) : /* @__PURE__ */ new Set();
|
|
2091
|
-
if (!oldModelSet.has(child2)) {
|
|
2744
|
+
const oldModelSet = Array.isArray(currentValue) ? new Set(currentValue.map((m) => getSource(m))) : /* @__PURE__ */ new Set();
|
|
2745
|
+
if (!oldModelSet.has(getSource(child2))) {
|
|
2092
2746
|
const internalModel = getModelAdm(child2);
|
|
2093
2747
|
internalModel.attach(this, name);
|
|
2094
2748
|
}
|
|
@@ -2202,9 +2856,14 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2202
2856
|
toJSON() {
|
|
2203
2857
|
return Object.keys(this.configuration).reduce((json, key) => {
|
|
2204
2858
|
switch (this.configuration[key].type) {
|
|
2205
|
-
case ModelCfgTypes.state:
|
|
2859
|
+
case ModelCfgTypes.state: {
|
|
2860
|
+
const value = this.proxy[key];
|
|
2861
|
+
this.observeSnapshotValue(value);
|
|
2862
|
+
json[key] = clone(getSource(value), key);
|
|
2863
|
+
break;
|
|
2864
|
+
}
|
|
2206
2865
|
case ModelCfgTypes.id:
|
|
2207
|
-
json[key] = clone(getSource(this.proxy[key]));
|
|
2866
|
+
json[key] = clone(getSource(this.proxy[key]), key);
|
|
2208
2867
|
break;
|
|
2209
2868
|
case ModelCfgTypes.modelRef:
|
|
2210
2869
|
const model2 = this.proxy[key];
|
|
@@ -2343,6 +3002,7 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2343
3002
|
getSnapshot() {
|
|
2344
3003
|
if (!this.computedSnapshot) {
|
|
2345
3004
|
this.computedSnapshot = createComputed(() => {
|
|
3005
|
+
this.snapshotAtom.reportObserved();
|
|
2346
3006
|
const json = this.toJSON();
|
|
2347
3007
|
configMap.set(json, this.configuration);
|
|
2348
3008
|
return json;
|
|
@@ -2461,6 +3121,73 @@ function createContext(defaultValue) {
|
|
|
2461
3121
|
}
|
|
2462
3122
|
};
|
|
2463
3123
|
}
|
|
3124
|
+
function toObservableTree(value) {
|
|
3125
|
+
return toObservableTreeInternal(value, /* @__PURE__ */ new Set(), "");
|
|
3126
|
+
}
|
|
3127
|
+
function buildPath(currentPath, key) {
|
|
3128
|
+
if (typeof key === "number") {
|
|
3129
|
+
return `${currentPath}[${key}]`;
|
|
3130
|
+
}
|
|
3131
|
+
return currentPath ? `${currentPath}.${key}` : key;
|
|
3132
|
+
}
|
|
3133
|
+
function toObservableTreeInternal(value, ancestorPath, path) {
|
|
3134
|
+
if (value === null || typeof value !== "object") {
|
|
3135
|
+
return value;
|
|
3136
|
+
}
|
|
3137
|
+
if (Array.isArray(value)) {
|
|
3138
|
+
if (ancestorPath.has(value)) {
|
|
3139
|
+
throw new Error(
|
|
3140
|
+
`r-state-tree: toObservableTree does not support circular references (cycle detected at path "${path}")`
|
|
3141
|
+
);
|
|
3142
|
+
}
|
|
3143
|
+
ancestorPath.add(value);
|
|
3144
|
+
const toWrap = [];
|
|
3145
|
+
for (let i = 0; i < value.length; i++) {
|
|
3146
|
+
const element = value[i];
|
|
3147
|
+
if (Array.isArray(element) || isPlainObject(element)) {
|
|
3148
|
+
toWrap.push({ index: i, element });
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
const proxy = observable(value);
|
|
3152
|
+
for (const { index, element } of toWrap) {
|
|
3153
|
+
proxy[index] = toObservableTreeInternal(
|
|
3154
|
+
element,
|
|
3155
|
+
ancestorPath,
|
|
3156
|
+
buildPath(path, index)
|
|
3157
|
+
);
|
|
3158
|
+
}
|
|
3159
|
+
ancestorPath.delete(value);
|
|
3160
|
+
return proxy;
|
|
3161
|
+
}
|
|
3162
|
+
if (isPlainObject(value)) {
|
|
3163
|
+
if (ancestorPath.has(value)) {
|
|
3164
|
+
throw new Error(
|
|
3165
|
+
`r-state-tree: toObservableTree does not support circular references (cycle detected at path "${path}")`
|
|
3166
|
+
);
|
|
3167
|
+
}
|
|
3168
|
+
ancestorPath.add(value);
|
|
3169
|
+
const toWrap = [];
|
|
3170
|
+
const keys = Object.keys(value);
|
|
3171
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3172
|
+
const key = keys[i];
|
|
3173
|
+
const propValue = value[key];
|
|
3174
|
+
if (Array.isArray(propValue) || isPlainObject(propValue)) {
|
|
3175
|
+
toWrap.push({ key, propValue });
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
const proxy = observable(value);
|
|
3179
|
+
for (const { key, propValue } of toWrap) {
|
|
3180
|
+
proxy[key] = toObservableTreeInternal(
|
|
3181
|
+
propValue,
|
|
3182
|
+
ancestorPath,
|
|
3183
|
+
buildPath(path, key)
|
|
3184
|
+
);
|
|
3185
|
+
}
|
|
3186
|
+
ancestorPath.delete(value);
|
|
3187
|
+
return proxy;
|
|
3188
|
+
}
|
|
3189
|
+
return value;
|
|
3190
|
+
}
|
|
2464
3191
|
function makeDecorator(type) {
|
|
2465
3192
|
return function(value, context) {
|
|
2466
3193
|
context.metadata[context.name] = type;
|
|
@@ -2508,9 +3235,10 @@ export {
|
|
|
2508
3235
|
reaction,
|
|
2509
3236
|
reportChanged,
|
|
2510
3237
|
reportObserved,
|
|
2511
|
-
|
|
3238
|
+
signal,
|
|
2512
3239
|
source,
|
|
2513
3240
|
state,
|
|
3241
|
+
toObservableTree,
|
|
2514
3242
|
toSnapshot,
|
|
2515
3243
|
unmount,
|
|
2516
3244
|
untracked2 as untracked,
|