r-state-tree 0.7.0 → 0.8.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.
- package/README.md +97 -51
- package/dist/api.d.ts +2 -2
- package/dist/decorators.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/model/Model.d.ts +5 -9
- package/dist/model/ModelAdministration.d.ts +11 -0
- package/dist/model/idMap.d.ts +4 -4
- package/dist/observables/preact.d.ts +1 -1
- package/dist/r-state-tree.cjs +460 -267
- package/dist/r-state-tree.js +460 -267
- package/dist/store/Store.d.ts +5 -4
- package/dist/store/StoreAdministration.d.ts +10 -5
- package/package.json +1 -1
package/dist/r-state-tree.js
CHANGED
|
@@ -84,7 +84,15 @@ function makeChildDecorator(typeObj) {
|
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
const child = makeChildDecorator(childType);
|
|
87
|
-
const
|
|
87
|
+
const modelRefDecorator = makeChildDecorator(modelRefType);
|
|
88
|
+
function modelRef(childCtor, context) {
|
|
89
|
+
if (context !== void 0) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
"r-state-tree: @modelRef requires a model constructor, for example `@modelRef(User)`"
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return modelRefDecorator(childCtor);
|
|
95
|
+
}
|
|
88
96
|
const model = makeDecorator(modelType);
|
|
89
97
|
const id = makeDecorator(idType);
|
|
90
98
|
const state = makeDecorator(stateType);
|
|
@@ -102,7 +110,11 @@ function normalizeEntry(entry) {
|
|
|
102
110
|
if (entry === state) return stateType;
|
|
103
111
|
if (entry === model) return modelType;
|
|
104
112
|
if (entry === child) return childType;
|
|
105
|
-
if (entry === modelRef)
|
|
113
|
+
if (entry === modelRef) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
"r-state-tree: modelRef requires a model constructor, for example `modelRef(User)`"
|
|
116
|
+
);
|
|
117
|
+
}
|
|
106
118
|
return void 0;
|
|
107
119
|
}
|
|
108
120
|
return void 0;
|
|
@@ -668,9 +680,10 @@ function reaction(fn, callback) {
|
|
|
668
680
|
if (Object.is(currentValue, nextValue)) {
|
|
669
681
|
return;
|
|
670
682
|
}
|
|
683
|
+
const previousValue = currentValue;
|
|
671
684
|
currentValue = nextValue;
|
|
672
685
|
untracked(() => {
|
|
673
|
-
callback(nextValue);
|
|
686
|
+
callback(nextValue, previousValue);
|
|
674
687
|
});
|
|
675
688
|
});
|
|
676
689
|
}
|
|
@@ -1925,7 +1938,7 @@ function createCircularMountError(frame) {
|
|
|
1925
1938
|
const chain = formatMountChain(frame);
|
|
1926
1939
|
const models = frame.modelsKeys.length === 0 ? "no models provided" : `models: ${frame.modelsKeys.join(", ")}`;
|
|
1927
1940
|
return new Error(
|
|
1928
|
-
`r-state-tree: detected circular store/model creation while mounting ${chain} (using ${models}). Passing models into child stores during mount can create recursive wiring.
|
|
1941
|
+
`r-state-tree: detected circular store/model creation while mounting ${chain} (using ${models}). Passing models into child stores during mount can create recursive wiring. Break the ownership cycle.`
|
|
1929
1942
|
);
|
|
1930
1943
|
}
|
|
1931
1944
|
function updateProps(props, newProps) {
|
|
@@ -1984,8 +1997,8 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
1984
1997
|
PreactObjectAdministration.proxyTraps,
|
|
1985
1998
|
{
|
|
1986
1999
|
get(target, name) {
|
|
1987
|
-
if (name === "key") {
|
|
1988
|
-
return target
|
|
2000
|
+
if (name === "key" || name === Symbol.dispose) {
|
|
2001
|
+
return Reflect.get(target, name);
|
|
1989
2002
|
}
|
|
1990
2003
|
const adm = getAdministration(target);
|
|
1991
2004
|
switch (getConfigType(adm.configuration[name])) {
|
|
@@ -2018,10 +2031,11 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2018
2031
|
}
|
|
2019
2032
|
);
|
|
2020
2033
|
parent = null;
|
|
2021
|
-
|
|
2034
|
+
mountedSignal = createSignal(false);
|
|
2035
|
+
disposed = false;
|
|
2022
2036
|
contextCache = /* @__PURE__ */ new Map();
|
|
2023
2037
|
childStoreDataMap = /* @__PURE__ */ new Map();
|
|
2024
|
-
|
|
2038
|
+
reactiveRegistrations = /* @__PURE__ */ new Set();
|
|
2025
2039
|
configurationGetter;
|
|
2026
2040
|
setConfiguration(configurationGetter) {
|
|
2027
2041
|
this.configurationGetter = configurationGetter;
|
|
@@ -2045,7 +2059,9 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2045
2059
|
}
|
|
2046
2060
|
});
|
|
2047
2061
|
childStoreData.value.set(stores);
|
|
2048
|
-
|
|
2062
|
+
if (this.isMounted) {
|
|
2063
|
+
stores.forEach((s) => getStoreAdm(s).mount(this, name));
|
|
2064
|
+
}
|
|
2049
2065
|
return stores;
|
|
2050
2066
|
}
|
|
2051
2067
|
const newStores = /* @__PURE__ */ new Set();
|
|
@@ -2095,8 +2111,10 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2095
2111
|
if (newStores.size || removedStores.size || keyedIndexChanged) {
|
|
2096
2112
|
batch(() => childStoreData.value.set(stores));
|
|
2097
2113
|
}
|
|
2098
|
-
removedStores.forEach((s) => getStoreAdm(s).
|
|
2099
|
-
|
|
2114
|
+
removedStores.forEach((s) => getStoreAdm(s).dispose(true));
|
|
2115
|
+
if (this.isMounted) {
|
|
2116
|
+
newStores.forEach((s) => getStoreAdm(s).mount(this, name));
|
|
2117
|
+
}
|
|
2100
2118
|
return stores;
|
|
2101
2119
|
}
|
|
2102
2120
|
setSingleStore(name, element) {
|
|
@@ -2106,16 +2124,18 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2106
2124
|
);
|
|
2107
2125
|
const { key, Type, props } = element || {};
|
|
2108
2126
|
if (!element) {
|
|
2109
|
-
oldStore && getStoreAdm(oldStore).
|
|
2127
|
+
oldStore && getStoreAdm(oldStore).dispose(true);
|
|
2110
2128
|
batch(() => childStoreData.value.set(null));
|
|
2111
2129
|
return null;
|
|
2112
2130
|
} else if (!oldStore || oldStore.props.key !== key || !(oldStore instanceof Type)) {
|
|
2113
2131
|
if (oldStore) {
|
|
2114
|
-
getStoreAdm(oldStore).
|
|
2132
|
+
getStoreAdm(oldStore).dispose(true);
|
|
2115
2133
|
}
|
|
2116
2134
|
const childStore = this.createChildStore(element);
|
|
2117
2135
|
batch(() => childStoreData.value.set(childStore));
|
|
2118
|
-
|
|
2136
|
+
if (this.isMounted) {
|
|
2137
|
+
getStoreAdm(childStore).mount(this, name);
|
|
2138
|
+
}
|
|
2119
2139
|
return childStore;
|
|
2120
2140
|
} else {
|
|
2121
2141
|
batch(() => updateProps(oldStore.props, props));
|
|
@@ -2155,7 +2175,8 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2155
2175
|
getStore(name) {
|
|
2156
2176
|
const childStoreData = this.childStoreDataMap.get(name);
|
|
2157
2177
|
if (!childStoreData) {
|
|
2158
|
-
|
|
2178
|
+
untracked(() => this.initializeStore(name));
|
|
2179
|
+
return this.childStoreDataMap.get(name).value.get();
|
|
2159
2180
|
} else {
|
|
2160
2181
|
const storeElement = untracked(() => childStoreData.computed.get());
|
|
2161
2182
|
validateStoreChildValue(storeElement, name);
|
|
@@ -2171,6 +2192,9 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2171
2192
|
isRoot() {
|
|
2172
2193
|
return !this.parent;
|
|
2173
2194
|
}
|
|
2195
|
+
get isMounted() {
|
|
2196
|
+
return this.mountedSignal.get();
|
|
2197
|
+
}
|
|
2174
2198
|
getContextValue(contextId, provideSymbol, defaultValue, hasDefault) {
|
|
2175
2199
|
let computed2 = this.contextCache.get(contextId);
|
|
2176
2200
|
if (!computed2) {
|
|
@@ -2204,12 +2228,43 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2204
2228
|
}
|
|
2205
2229
|
return void 0;
|
|
2206
2230
|
}
|
|
2231
|
+
register(start) {
|
|
2232
|
+
if (this.disposed) {
|
|
2233
|
+
throw new Error(
|
|
2234
|
+
"r-state-tree: cannot register reactive resources on a disposed store"
|
|
2235
|
+
);
|
|
2236
|
+
}
|
|
2237
|
+
const registration = { start, disposed: false };
|
|
2238
|
+
this.reactiveRegistrations.add(registration);
|
|
2239
|
+
if (this.isMounted) registration.stop = registration.start();
|
|
2240
|
+
return () => {
|
|
2241
|
+
if (registration.disposed) return;
|
|
2242
|
+
registration.disposed = true;
|
|
2243
|
+
this.reactiveRegistrations.delete(registration);
|
|
2244
|
+
registration.stop?.();
|
|
2245
|
+
registration.stop = void 0;
|
|
2246
|
+
};
|
|
2247
|
+
}
|
|
2248
|
+
startReactiveRegistrations() {
|
|
2249
|
+
this.reactiveRegistrations.forEach((registration) => {
|
|
2250
|
+
if (!registration.disposed && !registration.stop) {
|
|
2251
|
+
registration.stop = registration.start();
|
|
2252
|
+
}
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2207
2255
|
reaction(track, callback) {
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2256
|
+
return this.register(() => reaction(track, callback));
|
|
2257
|
+
}
|
|
2258
|
+
effect(callback) {
|
|
2259
|
+
return this.register(() => effect(callback));
|
|
2211
2260
|
}
|
|
2212
|
-
mount(parent = null, childName) {
|
|
2261
|
+
mount(parent = null, childName, activationQueue) {
|
|
2262
|
+
if (this.disposed) {
|
|
2263
|
+
throw new Error("r-state-tree: cannot mount a disposed store");
|
|
2264
|
+
}
|
|
2265
|
+
if (this.isMounted) {
|
|
2266
|
+
throw new Error("r-state-tree: store is already mounted");
|
|
2267
|
+
}
|
|
2213
2268
|
const frame = {
|
|
2214
2269
|
storeName: this.proxy.constructor.name || "Store",
|
|
2215
2270
|
childName,
|
|
@@ -2219,20 +2274,31 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2219
2274
|
throw createCircularMountError(frame);
|
|
2220
2275
|
}
|
|
2221
2276
|
mountingStack.push(frame);
|
|
2277
|
+
const isOutermostMount = activationQueue === void 0;
|
|
2278
|
+
const registrationsToStart = activationQueue ?? [];
|
|
2222
2279
|
try {
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2280
|
+
batch(() => {
|
|
2281
|
+
this.parent = parent || null;
|
|
2282
|
+
this.childStoreDataMap.forEach(({ value }, name) => {
|
|
2283
|
+
const stores = value.get();
|
|
2284
|
+
if (Array.isArray(stores)) {
|
|
2285
|
+
stores?.forEach(
|
|
2286
|
+
(s) => getStoreAdm(s)?.mount(this, name, registrationsToStart)
|
|
2287
|
+
);
|
|
2288
|
+
} else if (stores) {
|
|
2289
|
+
getStoreAdm(stores)?.mount(this, name, registrationsToStart);
|
|
2290
|
+
}
|
|
2291
|
+
});
|
|
2292
|
+
this.mountedSignal.set(true);
|
|
2293
|
+
registrationsToStart.push(this);
|
|
2231
2294
|
});
|
|
2232
|
-
|
|
2233
|
-
|
|
2295
|
+
if (isOutermostMount) {
|
|
2296
|
+
registrationsToStart.forEach(
|
|
2297
|
+
(store) => store.startReactiveRegistrations()
|
|
2298
|
+
);
|
|
2299
|
+
}
|
|
2234
2300
|
} catch (error) {
|
|
2235
|
-
if (error instanceof RangeError && /call stack/i.test(error.message)) {
|
|
2301
|
+
if (error instanceof Error && (error instanceof RangeError && /call stack/i.test(error.message) || /cycle detected/i.test(error.message))) {
|
|
2236
2302
|
throw createCircularMountError(frame);
|
|
2237
2303
|
}
|
|
2238
2304
|
throw error;
|
|
@@ -2240,25 +2306,36 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2240
2306
|
mountingStack.pop();
|
|
2241
2307
|
}
|
|
2242
2308
|
}
|
|
2243
|
-
|
|
2244
|
-
this.
|
|
2245
|
-
this.
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2309
|
+
dispose(internal = false) {
|
|
2310
|
+
if (this.disposed) return;
|
|
2311
|
+
if (!internal && !this.isRoot()) {
|
|
2312
|
+
throw new Error("r-state-tree: can only dispose root stores");
|
|
2313
|
+
}
|
|
2314
|
+
batch(() => {
|
|
2315
|
+
this.childStoreDataMap.forEach((data) => {
|
|
2316
|
+
const { value, computed: computed2, listener } = data;
|
|
2317
|
+
const stores = value.get();
|
|
2318
|
+
if (Array.isArray(stores)) {
|
|
2319
|
+
stores?.forEach((s) => getStoreAdm(s)?.dispose(true));
|
|
2320
|
+
} else if (stores) {
|
|
2321
|
+
getStoreAdm(stores)?.dispose(true);
|
|
2322
|
+
}
|
|
2323
|
+
computed2.clear();
|
|
2324
|
+
listener.dispose();
|
|
2325
|
+
});
|
|
2326
|
+
this.childStoreDataMap.clear();
|
|
2327
|
+
this.contextCache.forEach((computed2) => computed2.clear());
|
|
2328
|
+
this.contextCache.clear();
|
|
2329
|
+
this.parent = null;
|
|
2256
2330
|
});
|
|
2257
|
-
this.
|
|
2258
|
-
this.
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2331
|
+
this.disposed = true;
|
|
2332
|
+
this.reactiveRegistrations.forEach((registration) => {
|
|
2333
|
+
registration.disposed = true;
|
|
2334
|
+
registration.stop?.();
|
|
2335
|
+
registration.stop = void 0;
|
|
2336
|
+
});
|
|
2337
|
+
this.reactiveRegistrations.clear();
|
|
2338
|
+
this.mountedSignal.set(false);
|
|
2262
2339
|
}
|
|
2263
2340
|
}
|
|
2264
2341
|
let initEnabled$1 = false;
|
|
@@ -2304,141 +2381,109 @@ class Store {
|
|
|
2304
2381
|
get key() {
|
|
2305
2382
|
return this.props.key;
|
|
2306
2383
|
}
|
|
2384
|
+
get isMounted() {
|
|
2385
|
+
return getStoreAdm(this).isMounted;
|
|
2386
|
+
}
|
|
2307
2387
|
reaction(track, callback) {
|
|
2308
2388
|
return getStoreAdm(this).reaction(track, callback);
|
|
2309
2389
|
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2390
|
+
effect(callback) {
|
|
2391
|
+
return getStoreAdm(this).effect(callback);
|
|
2312
2392
|
}
|
|
2313
|
-
|
|
2314
|
-
|
|
2393
|
+
[Symbol.dispose]() {
|
|
2394
|
+
getStoreAdm(this).dispose();
|
|
2315
2395
|
}
|
|
2316
2396
|
}
|
|
2317
2397
|
const attachedIdMap = /* @__PURE__ */ new WeakMap();
|
|
2318
2398
|
const idMap = /* @__PURE__ */ new WeakMap();
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
throw new Error(
|
|
2342
|
-
"r-state-tree duplicate ids detected after snapshot was loaded"
|
|
2343
|
-
);
|
|
2344
|
-
}
|
|
2345
|
-
set.add(id2);
|
|
2346
|
-
}
|
|
2347
|
-
});
|
|
2348
|
-
} finally {
|
|
2349
|
-
potentialDups.clear();
|
|
2350
|
-
}
|
|
2399
|
+
function getModelType(model2) {
|
|
2400
|
+
return Object.getPrototypeOf(model2).constructor;
|
|
2401
|
+
}
|
|
2402
|
+
function entriesFor(model2) {
|
|
2403
|
+
const entries = [];
|
|
2404
|
+
attachedIdMap.get(model2)?.forEach((ids, Type) => {
|
|
2405
|
+
ids.forEach((value, id22) => {
|
|
2406
|
+
if (value) entries.push([Type, id22, value]);
|
|
2407
|
+
});
|
|
2408
|
+
});
|
|
2409
|
+
const id2 = idMap.get(model2);
|
|
2410
|
+
if (id2 != null) entries.push([getModelType(model2), id2, model2]);
|
|
2411
|
+
return entries;
|
|
2412
|
+
}
|
|
2413
|
+
function assertAvailable(node, entries) {
|
|
2414
|
+
const map = attachedIdMap.get(node);
|
|
2415
|
+
for (const [Type, id2, model2] of entries) {
|
|
2416
|
+
const existing = map?.get(Type)?.get(id2);
|
|
2417
|
+
if (existing && existing !== model2) {
|
|
2418
|
+
throw new Error(
|
|
2419
|
+
`r-state-tree: id: ${id2} is already assigned to another model`
|
|
2420
|
+
);
|
|
2351
2421
|
}
|
|
2352
2422
|
}
|
|
2353
2423
|
}
|
|
2424
|
+
function bucket(node, Type) {
|
|
2425
|
+
let map = attachedIdMap.get(node);
|
|
2426
|
+
if (!map) {
|
|
2427
|
+
map = observable(/* @__PURE__ */ new Map());
|
|
2428
|
+
attachedIdMap.set(node, map);
|
|
2429
|
+
}
|
|
2430
|
+
let ids = map.get(Type);
|
|
2431
|
+
if (!ids) {
|
|
2432
|
+
ids = observable(/* @__PURE__ */ new Map());
|
|
2433
|
+
map.set(Type, ids);
|
|
2434
|
+
}
|
|
2435
|
+
return ids;
|
|
2436
|
+
}
|
|
2354
2437
|
function setIdentifier(model2, id2) {
|
|
2355
|
-
const
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2438
|
+
const previousId = idMap.get(model2);
|
|
2439
|
+
if (previousId === id2) return;
|
|
2440
|
+
const Type = getModelType(model2);
|
|
2441
|
+
const ancestors = [];
|
|
2442
|
+
let node = model2.parent;
|
|
2443
|
+
while (node) {
|
|
2444
|
+
assertAvailable(node, [[Type, id2, model2]]);
|
|
2445
|
+
ancestors.push(node);
|
|
2446
|
+
node = node.parent;
|
|
2363
2447
|
}
|
|
2448
|
+
for (const ancestor of ancestors) {
|
|
2449
|
+
const ids = bucket(ancestor, Type);
|
|
2450
|
+
if (previousId != null && ids.get(previousId) === model2)
|
|
2451
|
+
ids.delete(previousId);
|
|
2452
|
+
ids.set(id2, model2);
|
|
2453
|
+
}
|
|
2454
|
+
idMap.set(model2, id2);
|
|
2364
2455
|
}
|
|
2365
2456
|
function getIdentifier(model2) {
|
|
2366
2457
|
return idMap.get(model2);
|
|
2367
2458
|
}
|
|
2368
|
-
function getModelById(root, id2) {
|
|
2369
|
-
|
|
2370
|
-
return map?.get(id2);
|
|
2459
|
+
function getModelById(root, Type, id2) {
|
|
2460
|
+
return attachedIdMap.get(root)?.get(Type)?.get(id2);
|
|
2371
2461
|
}
|
|
2372
|
-
function
|
|
2373
|
-
const
|
|
2462
|
+
function onModelAttached(model2) {
|
|
2463
|
+
const entries = entriesFor(model2);
|
|
2464
|
+
if (!entries.length) return;
|
|
2465
|
+
const ancestors = [];
|
|
2374
2466
|
let node = model2.parent;
|
|
2375
2467
|
while (node) {
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
map.set(id2, model2);
|
|
2379
|
-
}
|
|
2468
|
+
assertAvailable(node, entries);
|
|
2469
|
+
ancestors.push(node);
|
|
2380
2470
|
node = node.parent;
|
|
2381
2471
|
}
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
const id2 = idMap.get(model2);
|
|
2386
|
-
if (attachedMap || id2 != null) {
|
|
2387
|
-
const id22 = idMap.get(model2);
|
|
2388
|
-
let node = model2.parent;
|
|
2389
|
-
while (node) {
|
|
2390
|
-
let map = attachedIdMap.get(node);
|
|
2391
|
-
if (!map) {
|
|
2392
|
-
map = observable(/* @__PURE__ */ new Map());
|
|
2393
|
-
attachedIdMap.set(node, map);
|
|
2394
|
-
}
|
|
2395
|
-
attachedMap?.forEach((value, key) => {
|
|
2396
|
-
if (map.has(key)) {
|
|
2397
|
-
if (loadingSnapshot) {
|
|
2398
|
-
potentialDups.add(model2);
|
|
2399
|
-
potentialDups.add(map.get(key));
|
|
2400
|
-
} else {
|
|
2401
|
-
throw new Error(
|
|
2402
|
-
`r-state-tree: id: ${key} is already assigned to another model`
|
|
2403
|
-
);
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
map.set(key, value);
|
|
2407
|
-
});
|
|
2408
|
-
if (id22 != null) {
|
|
2409
|
-
if (map.has(id22)) {
|
|
2410
|
-
if (loadingSnapshot) {
|
|
2411
|
-
potentialDups.add(model2);
|
|
2412
|
-
potentialDups.add(map.get(id22));
|
|
2413
|
-
} else {
|
|
2414
|
-
throw new Error(
|
|
2415
|
-
`r-state-tree: id: ${id22} is already assigned to another model`
|
|
2416
|
-
);
|
|
2417
|
-
}
|
|
2418
|
-
}
|
|
2419
|
-
map.set(id22, model2);
|
|
2420
|
-
}
|
|
2421
|
-
node = node.parent;
|
|
2422
|
-
}
|
|
2472
|
+
for (const ancestor of ancestors) {
|
|
2473
|
+
for (const [Type, id2, value] of entries)
|
|
2474
|
+
bucket(ancestor, Type).set(id2, value);
|
|
2423
2475
|
}
|
|
2424
2476
|
}
|
|
2425
2477
|
function onModelDetached(model2) {
|
|
2426
|
-
const
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
const
|
|
2432
|
-
if (
|
|
2433
|
-
attachedMap?.forEach((value, key) => {
|
|
2434
|
-
map.delete(key);
|
|
2435
|
-
});
|
|
2436
|
-
if (id2 != null) {
|
|
2437
|
-
map.delete(id2);
|
|
2438
|
-
}
|
|
2439
|
-
}
|
|
2440
|
-
node = node.parent;
|
|
2478
|
+
const entries = entriesFor(model2);
|
|
2479
|
+
let node = model2.parent;
|
|
2480
|
+
while (node) {
|
|
2481
|
+
const map = attachedIdMap.get(node);
|
|
2482
|
+
for (const [Type, id2, value] of entries) {
|
|
2483
|
+
const ids = map?.get(Type);
|
|
2484
|
+
if (ids?.get(id2) === value) ids.delete(id2);
|
|
2441
2485
|
}
|
|
2486
|
+
node = node.parent;
|
|
2442
2487
|
}
|
|
2443
2488
|
}
|
|
2444
2489
|
const listenerMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -2494,19 +2539,28 @@ class ObservableListener {
|
|
|
2494
2539
|
notify(ev) {
|
|
2495
2540
|
if (!this.listeners) return;
|
|
2496
2541
|
this.notifying = true;
|
|
2497
|
-
|
|
2498
|
-
this.listeners
|
|
2542
|
+
try {
|
|
2543
|
+
for (let i = 0; i < this.listeners.length; i++) {
|
|
2544
|
+
this.listeners[i](ev);
|
|
2545
|
+
}
|
|
2546
|
+
} finally {
|
|
2547
|
+
this.notifying = false;
|
|
2499
2548
|
}
|
|
2500
|
-
this.notifying = false;
|
|
2501
2549
|
}
|
|
2502
2550
|
}
|
|
2503
2551
|
class ChildModelsAdministration extends ArrayAdministration {
|
|
2504
2552
|
set(index, newValue) {
|
|
2505
2553
|
return batch(() => {
|
|
2554
|
+
const oldValue = this.source[index];
|
|
2506
2555
|
const result = super.set(index, newValue);
|
|
2507
2556
|
const sourceValue = getSource(newValue);
|
|
2508
|
-
if (
|
|
2509
|
-
|
|
2557
|
+
if (oldValue !== sourceValue) {
|
|
2558
|
+
try {
|
|
2559
|
+
notifyArrayUpdate(this.proxy, index, oldValue, sourceValue);
|
|
2560
|
+
} catch (error) {
|
|
2561
|
+
super.set(index, oldValue);
|
|
2562
|
+
throw error;
|
|
2563
|
+
}
|
|
2510
2564
|
}
|
|
2511
2565
|
return result;
|
|
2512
2566
|
});
|
|
@@ -2515,7 +2569,12 @@ class ChildModelsAdministration extends ArrayAdministration {
|
|
|
2515
2569
|
return batch(() => {
|
|
2516
2570
|
const deleted = super.spliceWithArray(index, deleteCount, newItems);
|
|
2517
2571
|
if (deleteCount || newItems?.length) {
|
|
2518
|
-
|
|
2572
|
+
try {
|
|
2573
|
+
notifySpliceArray(this.proxy, index, newItems ?? [], deleted);
|
|
2574
|
+
} catch (error) {
|
|
2575
|
+
super.spliceWithArray(index, newItems?.length ?? 0, deleted);
|
|
2576
|
+
throw error;
|
|
2577
|
+
}
|
|
2519
2578
|
}
|
|
2520
2579
|
return deleted;
|
|
2521
2580
|
});
|
|
@@ -2594,6 +2653,9 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2594
2653
|
{
|
|
2595
2654
|
get(target, prop, proxy) {
|
|
2596
2655
|
const adm = getAdministration(target);
|
|
2656
|
+
if (prop === Symbol.dispose) {
|
|
2657
|
+
return Reflect.get(target, prop, proxy);
|
|
2658
|
+
}
|
|
2597
2659
|
if (prop === "parent") {
|
|
2598
2660
|
return target.parent;
|
|
2599
2661
|
}
|
|
@@ -2612,6 +2674,7 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2612
2674
|
},
|
|
2613
2675
|
set(target, name, value) {
|
|
2614
2676
|
const adm = getAdministration(target);
|
|
2677
|
+
adm.assertUsable();
|
|
2615
2678
|
adm.writeInProgress.add(name);
|
|
2616
2679
|
try {
|
|
2617
2680
|
switch (adm.getCfgType(name)) {
|
|
@@ -2674,6 +2737,8 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2674
2737
|
computedSnapshot;
|
|
2675
2738
|
snapshotMap = /* @__PURE__ */ new Map();
|
|
2676
2739
|
contextCache = /* @__PURE__ */ new Map();
|
|
2740
|
+
ownedDisposers = /* @__PURE__ */ new Set();
|
|
2741
|
+
disposed = false;
|
|
2677
2742
|
parentName = null;
|
|
2678
2743
|
get parent() {
|
|
2679
2744
|
this.parentAtom.reportObserved();
|
|
@@ -2688,6 +2753,29 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2688
2753
|
setConfiguration(configurationGetter) {
|
|
2689
2754
|
this.configurationGetter = configurationGetter;
|
|
2690
2755
|
}
|
|
2756
|
+
assertUsable() {
|
|
2757
|
+
if (this.disposed) {
|
|
2758
|
+
throw new Error("r-state-tree: cannot use a disposed model");
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
own(disposer) {
|
|
2762
|
+
this.assertUsable();
|
|
2763
|
+
let active = true;
|
|
2764
|
+
const wrapped = () => {
|
|
2765
|
+
if (!active) return;
|
|
2766
|
+
active = false;
|
|
2767
|
+
this.ownedDisposers.delete(wrapped);
|
|
2768
|
+
disposer();
|
|
2769
|
+
};
|
|
2770
|
+
this.ownedDisposers.add(wrapped);
|
|
2771
|
+
return wrapped;
|
|
2772
|
+
}
|
|
2773
|
+
reaction(track, callback) {
|
|
2774
|
+
return this.own(reaction(track, callback));
|
|
2775
|
+
}
|
|
2776
|
+
effect(callback) {
|
|
2777
|
+
return this.own(effect(callback));
|
|
2778
|
+
}
|
|
2691
2779
|
get configuration() {
|
|
2692
2780
|
return this.configurationGetter?.() ?? {};
|
|
2693
2781
|
}
|
|
@@ -2757,8 +2845,8 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2757
2845
|
);
|
|
2758
2846
|
}
|
|
2759
2847
|
if (v !== void 0) {
|
|
2760
|
-
this.source[name] = v;
|
|
2761
2848
|
setIdentifier(this.proxy, v);
|
|
2849
|
+
this.source[name] = v;
|
|
2762
2850
|
}
|
|
2763
2851
|
}
|
|
2764
2852
|
setModel(name, newModel) {
|
|
@@ -2813,11 +2901,30 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2813
2901
|
name,
|
|
2814
2902
|
observe(this.proxy[name], (event) => {
|
|
2815
2903
|
if (event.type === "updateArray") {
|
|
2816
|
-
getModelAdm(event.oldValue)
|
|
2817
|
-
getModelAdm(event.newValue)
|
|
2904
|
+
const oldAdm = getModelAdm(event.oldValue);
|
|
2905
|
+
const newAdm = getModelAdm(event.newValue);
|
|
2906
|
+
oldAdm.detach();
|
|
2907
|
+
try {
|
|
2908
|
+
newAdm.attach(this, name);
|
|
2909
|
+
} catch (error) {
|
|
2910
|
+
oldAdm.attach(this, name);
|
|
2911
|
+
throw error;
|
|
2912
|
+
}
|
|
2818
2913
|
} else if (event.type === "spliceArray") {
|
|
2914
|
+
const attached = [];
|
|
2819
2915
|
event.removed.forEach((model2) => getModelAdm(model2).detach());
|
|
2820
|
-
|
|
2916
|
+
try {
|
|
2917
|
+
event.added.forEach((model2) => {
|
|
2918
|
+
getModelAdm(model2).attach(this, name);
|
|
2919
|
+
attached.push(model2);
|
|
2920
|
+
});
|
|
2921
|
+
} catch (error) {
|
|
2922
|
+
attached.forEach((model2) => getModelAdm(model2).detach());
|
|
2923
|
+
event.removed.forEach(
|
|
2924
|
+
(model2) => getModelAdm(model2).attach(this, name)
|
|
2925
|
+
);
|
|
2926
|
+
throw error;
|
|
2927
|
+
}
|
|
2821
2928
|
}
|
|
2822
2929
|
})
|
|
2823
2930
|
);
|
|
@@ -2832,7 +2939,9 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2832
2939
|
getModelRef(name) {
|
|
2833
2940
|
const a = this.getReferencedAtom(name);
|
|
2834
2941
|
a.reportObserved();
|
|
2835
|
-
|
|
2942
|
+
const Type = this.getRequiredModelRefType(name);
|
|
2943
|
+
const root = this.getReactiveRoot().proxy;
|
|
2944
|
+
return this.source[name] != null ? getModelById(root, Type, this.source[name]) : void 0;
|
|
2836
2945
|
}
|
|
2837
2946
|
getModelRefs(name) {
|
|
2838
2947
|
const a = this.getReferencedAtom(name);
|
|
@@ -2841,7 +2950,9 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2841
2950
|
if (!this.referencedModels) this.referencedModels = /* @__PURE__ */ new Map();
|
|
2842
2951
|
c = createComputed(() => {
|
|
2843
2952
|
a.reportObserved();
|
|
2844
|
-
const
|
|
2953
|
+
const Type = this.getRequiredModelRefType(name);
|
|
2954
|
+
const root = this.getReactiveRoot().proxy;
|
|
2955
|
+
const models = (this.source[name] || []).map((id2) => getModelById(root, Type, id2)).filter((m) => !!m);
|
|
2845
2956
|
return models;
|
|
2846
2957
|
});
|
|
2847
2958
|
this.referencedModels.set(name, c);
|
|
@@ -2851,6 +2962,7 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2851
2962
|
setModelRef(name, modelValue) {
|
|
2852
2963
|
let id2 = void 0;
|
|
2853
2964
|
if (modelValue) {
|
|
2965
|
+
this.assertModelRefType(name, modelValue);
|
|
2854
2966
|
id2 = getIdentifier(modelValue);
|
|
2855
2967
|
if (id2 == null) {
|
|
2856
2968
|
throw new Error(
|
|
@@ -2863,6 +2975,7 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2863
2975
|
}
|
|
2864
2976
|
setModelRefs(name, modelValue) {
|
|
2865
2977
|
const ids = modelValue.map((model2) => {
|
|
2978
|
+
this.assertModelRefType(name, model2);
|
|
2866
2979
|
const id2 = getIdentifier(model2);
|
|
2867
2980
|
if (id2 == null) {
|
|
2868
2981
|
throw new Error(
|
|
@@ -2874,31 +2987,87 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2874
2987
|
this.source[name] = ids;
|
|
2875
2988
|
this.referencedAtoms?.get(name)?.reportChanged();
|
|
2876
2989
|
}
|
|
2990
|
+
getRequiredModelRefType(name) {
|
|
2991
|
+
const Type = this.getCfgChildType(name);
|
|
2992
|
+
if (!Type) {
|
|
2993
|
+
throw new Error(
|
|
2994
|
+
`r-state-tree: modelRef '${String(name)}' requires a model constructor`
|
|
2995
|
+
);
|
|
2996
|
+
}
|
|
2997
|
+
return Type;
|
|
2998
|
+
}
|
|
2999
|
+
assertModelRefType(name, model2) {
|
|
3000
|
+
const Type = this.getRequiredModelRefType(name);
|
|
3001
|
+
if (!(model2 instanceof Type)) {
|
|
3002
|
+
throw new Error(
|
|
3003
|
+
`r-state-tree: modelRef '${String(name)}' must reference ${Type.name}`
|
|
3004
|
+
);
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
2877
3007
|
attach(parent = null, parentName = null) {
|
|
3008
|
+
this.assertUsable();
|
|
2878
3009
|
if (this.parent) {
|
|
2879
3010
|
throw new Error(
|
|
2880
3011
|
"r-state-tree: child model already attached to a parent. Did you mean to use modelRef?"
|
|
2881
3012
|
);
|
|
2882
3013
|
}
|
|
2883
|
-
if (parent) {
|
|
2884
|
-
this.parent = parent;
|
|
2885
|
-
this.root = parent.root;
|
|
2886
|
-
this.parentName = parentName;
|
|
2887
|
-
}
|
|
2888
3014
|
batch(() => {
|
|
2889
|
-
|
|
2890
|
-
|
|
3015
|
+
if (parent) {
|
|
3016
|
+
this.parent = parent;
|
|
3017
|
+
this.root = parent.root;
|
|
3018
|
+
this.parentName = parentName;
|
|
3019
|
+
}
|
|
3020
|
+
try {
|
|
3021
|
+
onModelAttached(this.proxy);
|
|
3022
|
+
} catch (error) {
|
|
3023
|
+
this.parent = null;
|
|
3024
|
+
this.root = this;
|
|
3025
|
+
this.parentName = null;
|
|
3026
|
+
throw error;
|
|
3027
|
+
}
|
|
2891
3028
|
});
|
|
2892
3029
|
}
|
|
3030
|
+
getReactiveRoot() {
|
|
3031
|
+
const parent = this.parent;
|
|
3032
|
+
return parent ? parent.getReactiveRoot() : this;
|
|
3033
|
+
}
|
|
2893
3034
|
detach() {
|
|
2894
3035
|
batch(() => {
|
|
2895
|
-
this.proxy.modelWillDetach();
|
|
2896
3036
|
onModelDetached(this.proxy);
|
|
3037
|
+
this.contextCache.forEach((computed2) => computed2.clear());
|
|
3038
|
+
this.contextCache.clear();
|
|
3039
|
+
this.parent = null;
|
|
3040
|
+
this.parentName = null;
|
|
3041
|
+
this.root = this;
|
|
2897
3042
|
});
|
|
3043
|
+
}
|
|
3044
|
+
dispose(internal = false) {
|
|
3045
|
+
if (this.disposed) return;
|
|
3046
|
+
if (!internal && this.parent) {
|
|
3047
|
+
throw new Error(
|
|
3048
|
+
"r-state-tree: cannot directly dispose an attached child model"
|
|
3049
|
+
);
|
|
3050
|
+
}
|
|
3051
|
+
batch(() => {
|
|
3052
|
+
this.activeModels.forEach((name) => {
|
|
3053
|
+
const child2 = this.proxy[name];
|
|
3054
|
+
if (Array.isArray(child2)) {
|
|
3055
|
+
child2.forEach((model2) => getModelAdm(model2).dispose(true));
|
|
3056
|
+
} else if (child2) {
|
|
3057
|
+
getModelAdm(child2).dispose(true);
|
|
3058
|
+
}
|
|
3059
|
+
});
|
|
3060
|
+
if (this.parent) onModelDetached(this.proxy);
|
|
3061
|
+
this.parent = null;
|
|
3062
|
+
this.parentName = null;
|
|
3063
|
+
this.root = this;
|
|
3064
|
+
});
|
|
3065
|
+
this.disposed = true;
|
|
3066
|
+
this.modelsTraceUnsub.forEach((dispose) => dispose());
|
|
3067
|
+
this.modelsTraceUnsub.clear();
|
|
2898
3068
|
this.contextCache.forEach((computed2) => computed2.clear());
|
|
2899
3069
|
this.contextCache.clear();
|
|
2900
|
-
this.
|
|
2901
|
-
this.root = this;
|
|
3070
|
+
Array.from(this.ownedDisposers).forEach((dispose) => dispose());
|
|
2902
3071
|
}
|
|
2903
3072
|
getContextValue(contextId, provideSymbol, defaultValue, hasDefault) {
|
|
2904
3073
|
let computed2 = this.contextCache.get(contextId);
|
|
@@ -3001,85 +3170,94 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
3001
3170
|
}
|
|
3002
3171
|
return true;
|
|
3003
3172
|
};
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
if (
|
|
3017
|
-
if (value?.[0] instanceof Model) {
|
|
3018
|
-
this.proxy[key] = value;
|
|
3019
|
-
} else {
|
|
3020
|
-
this.source[key] = value.map(
|
|
3021
|
-
(snapshot2) => getSnapshotRefId(snapshot2)
|
|
3022
|
-
);
|
|
3023
|
-
this.referencedAtoms?.get(key)?.reportChanged();
|
|
3024
|
-
}
|
|
3025
|
-
break;
|
|
3026
|
-
} else if (value instanceof Model) {
|
|
3173
|
+
untracked(() => {
|
|
3174
|
+
batch(() => {
|
|
3175
|
+
Object.keys(snapshot).forEach((key) => {
|
|
3176
|
+
const type = this.getCfgType(key);
|
|
3177
|
+
const childType2 = this.getCfgChildType(key);
|
|
3178
|
+
const value = snapshot[key];
|
|
3179
|
+
switch (type) {
|
|
3180
|
+
case ModelCfgTypes.state:
|
|
3181
|
+
this.proxy[key] = this.hydrateStateValue(this.proxy[key], value);
|
|
3182
|
+
break;
|
|
3183
|
+
case ModelCfgTypes.modelRef:
|
|
3184
|
+
if (Array.isArray(value)) {
|
|
3185
|
+
if (value?.[0] instanceof Model) {
|
|
3027
3186
|
this.proxy[key] = value;
|
|
3028
3187
|
} else {
|
|
3029
|
-
this.source[key] =
|
|
3188
|
+
this.source[key] = value.map(
|
|
3189
|
+
(snapshot2) => getSnapshotRefId(snapshot2)
|
|
3190
|
+
);
|
|
3030
3191
|
this.referencedAtoms?.get(key)?.reportChanged();
|
|
3031
3192
|
}
|
|
3032
3193
|
break;
|
|
3033
|
-
|
|
3034
|
-
this.
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3194
|
+
} else if (value instanceof Model) {
|
|
3195
|
+
this.proxy[key] = value;
|
|
3196
|
+
} else {
|
|
3197
|
+
this.source[key] = getSnapshotRefId(value);
|
|
3198
|
+
this.referencedAtoms?.get(key)?.reportChanged();
|
|
3199
|
+
}
|
|
3200
|
+
break;
|
|
3201
|
+
case ModelCfgTypes.id:
|
|
3202
|
+
this.setId(key, value);
|
|
3203
|
+
break;
|
|
3204
|
+
case CommonCfgTypes.child:
|
|
3205
|
+
let model2;
|
|
3206
|
+
if (Array.isArray(value)) {
|
|
3207
|
+
const Ctor = childType2;
|
|
3208
|
+
const snapshotIds = /* @__PURE__ */ new Set();
|
|
3209
|
+
for (const childSnapshot of value) {
|
|
3210
|
+
if (childSnapshot instanceof Model) continue;
|
|
3211
|
+
const snapshotId = childType2 ? getSnapshotId(childSnapshot ?? {}, Ctor) : null;
|
|
3212
|
+
if (snapshotId != null && snapshotIds.has(snapshotId)) {
|
|
3213
|
+
throw new Error(
|
|
3214
|
+
"r-state-tree duplicate ids detected after snapshot was loaded"
|
|
3215
|
+
);
|
|
3216
|
+
}
|
|
3217
|
+
if (snapshotId != null) snapshotIds.add(snapshotId);
|
|
3218
|
+
}
|
|
3219
|
+
this.proxy[key] = value?.map(
|
|
3220
|
+
(snapshot2, index) => {
|
|
3221
|
+
snapshot2 = snapshot2 ?? {};
|
|
3222
|
+
let model22;
|
|
3223
|
+
if (snapshot2 instanceof Model) {
|
|
3224
|
+
model22 = snapshot2;
|
|
3225
|
+
} else {
|
|
3226
|
+
ensureChildTypes(key);
|
|
3227
|
+
const id2 = childType2 && getSnapshotId(snapshot2, Ctor);
|
|
3228
|
+
const foundModel = id2 != null ? getModelById(this.root.proxy, Ctor, id2) : this.proxy[key][index];
|
|
3229
|
+
const adm = foundModel && getModelAdm(foundModel);
|
|
3230
|
+
if (adm && foundModel.parent === this.proxy && adm?.parentName === key) {
|
|
3231
|
+
adm.loadSnapshot(snapshot2);
|
|
3232
|
+
model22 = foundModel;
|
|
3046
3233
|
} else {
|
|
3047
|
-
|
|
3048
|
-
const id2 = childType2 && getSnapshotId(snapshot2, Ctor);
|
|
3049
|
-
const foundModel = id2 != null ? getModelById(this.root.proxy, id2) : this.proxy[key][index];
|
|
3050
|
-
const adm = foundModel && getModelAdm(foundModel);
|
|
3051
|
-
if (adm && foundModel.parent === this.proxy && adm?.parentName === key) {
|
|
3052
|
-
adm.loadSnapshot(snapshot2);
|
|
3053
|
-
model22 = foundModel;
|
|
3054
|
-
} else {
|
|
3055
|
-
model22 = Ctor.create(snapshot2);
|
|
3056
|
-
}
|
|
3234
|
+
model22 = Ctor.create(snapshot2);
|
|
3057
3235
|
}
|
|
3058
|
-
return model22;
|
|
3059
3236
|
}
|
|
3060
|
-
|
|
3061
|
-
break;
|
|
3062
|
-
} else if (value instanceof Model) {
|
|
3063
|
-
model2 = value;
|
|
3064
|
-
} else {
|
|
3065
|
-
ensureChildTypes(key);
|
|
3066
|
-
const id2 = childType2 && getSnapshotId(value, childType2);
|
|
3067
|
-
if (id2 != null && this.proxy[key] && id2 === getIdentifier(this.proxy[key])) {
|
|
3068
|
-
const adm = getModelAdm(this.proxy[key]);
|
|
3069
|
-
adm.loadSnapshot(value);
|
|
3070
|
-
model2 = this.proxy[key];
|
|
3071
|
-
} else {
|
|
3072
|
-
model2 = childType2.create(value);
|
|
3237
|
+
return model22;
|
|
3073
3238
|
}
|
|
3074
|
-
}
|
|
3075
|
-
this.proxy[key] = model2;
|
|
3076
|
-
break;
|
|
3077
|
-
default:
|
|
3078
|
-
console.warn(
|
|
3079
|
-
`r-state-tree: invalid key '${key}' found in snapshot, ignored.`
|
|
3080
3239
|
);
|
|
3081
|
-
|
|
3082
|
-
|
|
3240
|
+
break;
|
|
3241
|
+
} else if (value instanceof Model) {
|
|
3242
|
+
model2 = value;
|
|
3243
|
+
} else {
|
|
3244
|
+
ensureChildTypes(key);
|
|
3245
|
+
const id2 = childType2 && getSnapshotId(value, childType2);
|
|
3246
|
+
if (id2 != null && this.proxy[key] && this.proxy[key] instanceof childType2 && id2 === getIdentifier(this.proxy[key])) {
|
|
3247
|
+
const adm = getModelAdm(this.proxy[key]);
|
|
3248
|
+
adm.loadSnapshot(value);
|
|
3249
|
+
model2 = this.proxy[key];
|
|
3250
|
+
} else {
|
|
3251
|
+
model2 = childType2.create(value);
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3254
|
+
this.proxy[key] = model2;
|
|
3255
|
+
break;
|
|
3256
|
+
default:
|
|
3257
|
+
console.warn(
|
|
3258
|
+
`r-state-tree: invalid key '${key}' found in snapshot, ignored.`
|
|
3259
|
+
);
|
|
3260
|
+
}
|
|
3083
3261
|
});
|
|
3084
3262
|
});
|
|
3085
3263
|
});
|
|
@@ -3094,11 +3272,14 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
3094
3272
|
}
|
|
3095
3273
|
return this.computedSnapshot.get();
|
|
3096
3274
|
}
|
|
3275
|
+
getSnapshotForRollback() {
|
|
3276
|
+
return this.toJSON();
|
|
3277
|
+
}
|
|
3097
3278
|
}
|
|
3098
3279
|
let initEnabled = false;
|
|
3099
3280
|
class Model {
|
|
3100
3281
|
static childTypes = {};
|
|
3101
|
-
static create(snapshot
|
|
3282
|
+
static create(snapshot) {
|
|
3102
3283
|
let instance;
|
|
3103
3284
|
try {
|
|
3104
3285
|
initEnabled = true;
|
|
@@ -3107,8 +3288,12 @@ class Model {
|
|
|
3107
3288
|
initEnabled = false;
|
|
3108
3289
|
}
|
|
3109
3290
|
const adm = getModelAdm(instance);
|
|
3110
|
-
|
|
3111
|
-
|
|
3291
|
+
try {
|
|
3292
|
+
snapshot && adm.loadSnapshot(snapshot);
|
|
3293
|
+
} catch (error) {
|
|
3294
|
+
adm.dispose(true);
|
|
3295
|
+
throw error;
|
|
3296
|
+
}
|
|
3112
3297
|
return instance;
|
|
3113
3298
|
}
|
|
3114
3299
|
constructor() {
|
|
@@ -3132,31 +3317,33 @@ class Model {
|
|
|
3132
3317
|
get parent() {
|
|
3133
3318
|
return getModelAdm(this).parent?.proxy ?? null;
|
|
3134
3319
|
}
|
|
3135
|
-
|
|
3136
|
-
|
|
3320
|
+
reaction(track, callback) {
|
|
3321
|
+
return getModelAdm(this).reaction(track, callback);
|
|
3137
3322
|
}
|
|
3138
|
-
|
|
3139
|
-
|
|
3323
|
+
effect(callback) {
|
|
3324
|
+
return getModelAdm(this).effect(callback);
|
|
3140
3325
|
}
|
|
3141
|
-
|
|
3142
|
-
|
|
3326
|
+
[Symbol.dispose]() {
|
|
3327
|
+
getModelAdm(this).dispose();
|
|
3143
3328
|
}
|
|
3144
3329
|
}
|
|
3330
|
+
function findModelById(root, ModelType, id2) {
|
|
3331
|
+
return getModelById(getModelAdm(root).root.proxy, ModelType, id2);
|
|
3332
|
+
}
|
|
3145
3333
|
function mount(container) {
|
|
3146
3334
|
return allowNewStore(() => {
|
|
3147
3335
|
const element = container;
|
|
3148
3336
|
const s = new element.Type(element.props);
|
|
3149
|
-
getStoreAdm(s)
|
|
3337
|
+
const adm = getStoreAdm(s);
|
|
3338
|
+
try {
|
|
3339
|
+
adm.mount();
|
|
3340
|
+
} catch (error) {
|
|
3341
|
+
adm.dispose(true);
|
|
3342
|
+
throw error;
|
|
3343
|
+
}
|
|
3150
3344
|
return s;
|
|
3151
3345
|
});
|
|
3152
3346
|
}
|
|
3153
|
-
function unmount(container) {
|
|
3154
|
-
const internalStore = getStoreAdm(container);
|
|
3155
|
-
if (!internalStore.isRoot()) {
|
|
3156
|
-
throw new Error("r-state-tree: can only unmount root stores");
|
|
3157
|
-
}
|
|
3158
|
-
internalStore.unmount();
|
|
3159
|
-
}
|
|
3160
3347
|
function toSnapshot(model2) {
|
|
3161
3348
|
return getModelAdm(model2).getSnapshot();
|
|
3162
3349
|
}
|
|
@@ -3176,7 +3363,13 @@ function onSnapshotDiff(model2, callback) {
|
|
|
3176
3363
|
}
|
|
3177
3364
|
function applySnapshot(model2, snapshot) {
|
|
3178
3365
|
const adm = getModelAdm(model2);
|
|
3179
|
-
adm.
|
|
3366
|
+
const previousSnapshot = adm.getSnapshotForRollback();
|
|
3367
|
+
try {
|
|
3368
|
+
adm.loadSnapshot(snapshot);
|
|
3369
|
+
} catch (error) {
|
|
3370
|
+
adm.loadSnapshot(previousSnapshot);
|
|
3371
|
+
throw error;
|
|
3372
|
+
}
|
|
3180
3373
|
return model2;
|
|
3181
3374
|
}
|
|
3182
3375
|
const CONTEXT_SYMBOL = Symbol("context");
|
|
@@ -3283,6 +3476,7 @@ export {
|
|
|
3283
3476
|
createContext,
|
|
3284
3477
|
createStore,
|
|
3285
3478
|
effect2 as effect,
|
|
3479
|
+
findModelById,
|
|
3286
3480
|
getSignal,
|
|
3287
3481
|
id,
|
|
3288
3482
|
isObservable,
|
|
@@ -3300,7 +3494,6 @@ export {
|
|
|
3300
3494
|
state,
|
|
3301
3495
|
toObservableTree,
|
|
3302
3496
|
toSnapshot,
|
|
3303
|
-
unmount,
|
|
3304
3497
|
untracked2 as untracked,
|
|
3305
3498
|
updateStore
|
|
3306
3499
|
};
|