r-state-tree 0.8.0 → 0.8.2
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 +19 -25
- package/dist/model/Model.d.ts +0 -2
- package/dist/model/ModelAdministration.d.ts +0 -4
- package/dist/r-state-tree.cjs +76 -54
- package/dist/r-state-tree.js +76 -54
- package/dist/store/Store.d.ts +0 -1
- package/dist/store/StoreAdministration.d.ts +9 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -139,7 +139,7 @@ app.todo.title;
|
|
|
139
139
|
|
|
140
140
|
- Always create with `createStore()` and attach with `mount()`. Stores cannot be constructed with `new` directly.
|
|
141
141
|
- Prefer no custom constructor. Type stores as `Store<Props>` and access props via `this.props`.
|
|
142
|
-
- Constructors may register framework-owned reactions and effects after `super(props)`.
|
|
142
|
+
- Constructors may register framework-owned reactions and effects after `super(props)`. Store registrations activate when mounting and are disposed with the store; return cleanup from effects to release resources.
|
|
143
143
|
- Do not shadow or re-declare `props` as a class field; `props` is read-only. Use the generic `Store<{ ... }>` for typing.
|
|
144
144
|
|
|
145
145
|
```ts
|
|
@@ -205,14 +205,13 @@ class ItemsStore extends Store {
|
|
|
205
205
|
|
|
206
206
|
### Store lifetime and owned effects
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
Stores implement `Disposable`, and their owned effects run only during the mounted lifetime:
|
|
209
209
|
|
|
210
210
|
```ts
|
|
211
211
|
class TodoStore extends Store {
|
|
212
212
|
constructor(props) {
|
|
213
213
|
super(props);
|
|
214
214
|
this.effect(() => {
|
|
215
|
-
if (!this.isMounted) return;
|
|
216
215
|
const connection = connect();
|
|
217
216
|
return () => connection.close();
|
|
218
217
|
});
|
|
@@ -243,6 +242,10 @@ class TodoStore extends Store {
|
|
|
243
242
|
}
|
|
244
243
|
```
|
|
245
244
|
|
|
245
|
+
`Store.effect()` and `Store.reaction()` register mount-scoped behavior. Mounting first links the complete store tree and commits its private mounted state bottom-up in one transaction. Registrations then activate bottom-up, so even a grandchild's initial effect sees a complete tree. A reaction establishes its initial value at activation and still skips its initial callback. Calling the disposer returned during construction cancels the pending registration; after mount, it disposes the live subscription. All registrations are disposed automatically with the store.
|
|
246
|
+
|
|
247
|
+
Registration activation is non-reentrant. If an active effect or reaction lazily materializes another child store, the new child's registrations are queued until the current callback and child getter stack have returned. This prevents initialization behavior from running inside the getter that created the store.
|
|
248
|
+
|
|
246
249
|
### Context
|
|
247
250
|
|
|
248
251
|
Share data across the store tree without prop drilling:
|
|
@@ -875,23 +878,19 @@ This keeps snapshot hydration predictable: `create(snapshot)` and `applySnapshot
|
|
|
875
878
|
|
|
876
879
|
### Model attachment and disposal
|
|
877
880
|
|
|
878
|
-
The public `parent` relationship
|
|
881
|
+
Models are inert state trees: creating or attaching one does not start reactions or effects. The public `parent` relationship remains reactive, so an external owner may observe it explicitly when needed:
|
|
879
882
|
|
|
880
883
|
```ts
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
this.reaction(() => this.parent, (parent, previousParent) => {
|
|
887
|
-
if (previousParent) console.log("detached", previousParent);
|
|
888
|
-
if (parent) console.log("attached", parent);
|
|
889
|
-
});
|
|
884
|
+
const stop = reaction(
|
|
885
|
+
() => todo.parent,
|
|
886
|
+
(parent, previousParent) => {
|
|
887
|
+
if (previousParent) console.log("detached", previousParent);
|
|
888
|
+
if (parent) console.log("attached", parent);
|
|
890
889
|
}
|
|
891
|
-
|
|
890
|
+
);
|
|
892
891
|
```
|
|
893
892
|
|
|
894
|
-
|
|
893
|
+
The external caller owns `stop`. Detachment is reversible. `model[Symbol.dispose]()` is terminal and recursively disposes owned child models, but never model refs.
|
|
895
894
|
|
|
896
895
|
### Model configuration
|
|
897
896
|
|
|
@@ -1204,20 +1203,15 @@ class ListModel extends Model {
|
|
|
1204
1203
|
}
|
|
1205
1204
|
```
|
|
1206
1205
|
|
|
1207
|
-
|
|
1206
|
+
Store lifecycle registration:
|
|
1208
1207
|
|
|
1209
1208
|
```ts
|
|
1210
|
-
class M extends Model {
|
|
1211
|
-
constructor() {
|
|
1212
|
-
super();
|
|
1213
|
-
this.reaction(() => this.parent, (parent, previousParent) => {});
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
1209
|
class S extends Store {
|
|
1217
1210
|
constructor(props) {
|
|
1218
1211
|
super(props);
|
|
1219
1212
|
this.effect(() => {
|
|
1220
|
-
|
|
1213
|
+
const resource = acquireResource();
|
|
1214
|
+
return () => resource.dispose();
|
|
1221
1215
|
});
|
|
1222
1216
|
}
|
|
1223
1217
|
}
|
|
@@ -1280,8 +1274,8 @@ When child stores are created during mount with `models` that point back into th
|
|
|
1280
1274
|
- Decorators (Stores): `@child`, `@model`
|
|
1281
1275
|
- Core: `createStore`, `mount`, `Symbol.dispose`, `updateStore`
|
|
1282
1276
|
- Snapshots: `onSnapshot`, `toSnapshot`, `applySnapshot`, `onSnapshotDiff`
|
|
1283
|
-
- Lifecycle:
|
|
1284
|
-
- Best practices: domain in Models; delegate from Stores; stable keys for `@child`;
|
|
1277
|
+
- Lifecycle: Store-owned `reaction`/`effect`, reactive `Model.parent`, and `Symbol.dispose`
|
|
1278
|
+
- Best practices: domain in Models; delegate from Stores; stable keys for `@child`; return cleanup from store effects; don’t shadow `props`.
|
|
1285
1279
|
|
|
1286
1280
|
## Testing
|
|
1287
1281
|
|
package/dist/model/Model.d.ts
CHANGED
|
@@ -7,7 +7,5 @@ export default class Model implements Disposable {
|
|
|
7
7
|
}, snapshot?: Snapshot<T>): T;
|
|
8
8
|
constructor();
|
|
9
9
|
get parent(): Model | null;
|
|
10
|
-
reaction<T>(track: () => T, callback: (value: T, previousValue: T) => void): () => void;
|
|
11
|
-
effect(callback: () => void | (() => void)): () => void;
|
|
12
10
|
[Symbol.dispose](): void;
|
|
13
11
|
}
|
|
@@ -20,16 +20,12 @@ export declare class ModelAdministration extends PreactObjectAdministration<any>
|
|
|
20
20
|
private computedSnapshot;
|
|
21
21
|
private snapshotMap;
|
|
22
22
|
private contextCache;
|
|
23
|
-
private ownedDisposers;
|
|
24
23
|
private disposed;
|
|
25
24
|
parentName: PropertyKey | null;
|
|
26
25
|
get parent(): ModelAdministration | null;
|
|
27
26
|
set parent(value: ModelAdministration | null);
|
|
28
27
|
setConfiguration(configurationGetter: () => ModelConfiguration<any>): void;
|
|
29
28
|
assertUsable(): void;
|
|
30
|
-
private own;
|
|
31
|
-
reaction<T>(track: () => T, callback: (value: T, previousValue: T) => void): () => void;
|
|
32
|
-
effect(callback: () => void | (() => void)): () => void;
|
|
33
29
|
private get configuration();
|
|
34
30
|
private getReferencedAtom;
|
|
35
31
|
private setState;
|
package/dist/r-state-tree.cjs
CHANGED
|
@@ -1993,6 +1993,32 @@ function validateStoreChildValue(value, propertyName) {
|
|
|
1993
1993
|
);
|
|
1994
1994
|
}
|
|
1995
1995
|
class StoreAdministration extends PreactObjectAdministration {
|
|
1996
|
+
static pendingActivations = [];
|
|
1997
|
+
static isFlushingActivations = false;
|
|
1998
|
+
static currentActivationDepth = 0;
|
|
1999
|
+
static flushReactiveRegistrations(stores) {
|
|
2000
|
+
const depth = this.isFlushingActivations ? this.currentActivationDepth + 1 : 0;
|
|
2001
|
+
this.pendingActivations.push(...stores.map((store) => ({ store, depth })));
|
|
2002
|
+
if (this.isFlushingActivations) return;
|
|
2003
|
+
this.isFlushingActivations = true;
|
|
2004
|
+
try {
|
|
2005
|
+
let entry;
|
|
2006
|
+
while (entry = this.pendingActivations.shift()) {
|
|
2007
|
+
this.currentActivationDepth = entry.depth;
|
|
2008
|
+
if (entry.depth > MAX_MOUNT_DEPTH) {
|
|
2009
|
+
throw createCircularMountError({
|
|
2010
|
+
storeName: entry.store.proxy.constructor.name || "Store",
|
|
2011
|
+
modelsKeys: Object.keys(entry.store.proxy.props?.models ?? {})
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
entry.store.startReactiveRegistrations();
|
|
2015
|
+
}
|
|
2016
|
+
} finally {
|
|
2017
|
+
this.pendingActivations.length = 0;
|
|
2018
|
+
this.currentActivationDepth = 0;
|
|
2019
|
+
this.isFlushingActivations = false;
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
1996
2022
|
static proxyTraps = Object.assign(
|
|
1997
2023
|
{},
|
|
1998
2024
|
PreactObjectAdministration.proxyTraps,
|
|
@@ -2032,11 +2058,11 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2032
2058
|
}
|
|
2033
2059
|
);
|
|
2034
2060
|
parent = null;
|
|
2035
|
-
|
|
2061
|
+
mounted = false;
|
|
2036
2062
|
disposed = false;
|
|
2037
2063
|
contextCache = /* @__PURE__ */ new Map();
|
|
2038
2064
|
childStoreDataMap = /* @__PURE__ */ new Map();
|
|
2039
|
-
|
|
2065
|
+
reactiveRegistrations = /* @__PURE__ */ new Set();
|
|
2040
2066
|
configurationGetter;
|
|
2041
2067
|
setConfiguration(configurationGetter) {
|
|
2042
2068
|
this.configurationGetter = configurationGetter;
|
|
@@ -2060,7 +2086,9 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2060
2086
|
}
|
|
2061
2087
|
});
|
|
2062
2088
|
childStoreData.value.set(stores);
|
|
2063
|
-
|
|
2089
|
+
if (this.isMounted) {
|
|
2090
|
+
stores.forEach((s) => getStoreAdm(s).mount(this, name));
|
|
2091
|
+
}
|
|
2064
2092
|
return stores;
|
|
2065
2093
|
}
|
|
2066
2094
|
const newStores = /* @__PURE__ */ new Set();
|
|
@@ -2111,7 +2139,9 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2111
2139
|
signalsCore.batch(() => childStoreData.value.set(stores));
|
|
2112
2140
|
}
|
|
2113
2141
|
removedStores.forEach((s) => getStoreAdm(s).dispose(true));
|
|
2114
|
-
|
|
2142
|
+
if (this.isMounted) {
|
|
2143
|
+
newStores.forEach((s) => getStoreAdm(s).mount(this, name));
|
|
2144
|
+
}
|
|
2115
2145
|
return stores;
|
|
2116
2146
|
}
|
|
2117
2147
|
setSingleStore(name, element) {
|
|
@@ -2130,7 +2160,9 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2130
2160
|
}
|
|
2131
2161
|
const childStore = this.createChildStore(element);
|
|
2132
2162
|
signalsCore.batch(() => childStoreData.value.set(childStore));
|
|
2133
|
-
|
|
2163
|
+
if (this.isMounted) {
|
|
2164
|
+
getStoreAdm(childStore).mount(this, name);
|
|
2165
|
+
}
|
|
2134
2166
|
return childStore;
|
|
2135
2167
|
} else {
|
|
2136
2168
|
signalsCore.batch(() => updateProps(oldStore.props, props));
|
|
@@ -2188,7 +2220,7 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2188
2220
|
return !this.parent;
|
|
2189
2221
|
}
|
|
2190
2222
|
get isMounted() {
|
|
2191
|
-
return this.
|
|
2223
|
+
return this.mounted;
|
|
2192
2224
|
}
|
|
2193
2225
|
getContextValue(contextId, provideSymbol, defaultValue, hasDefault) {
|
|
2194
2226
|
let computed2 = this.contextCache.get(contextId);
|
|
@@ -2223,31 +2255,37 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2223
2255
|
}
|
|
2224
2256
|
return void 0;
|
|
2225
2257
|
}
|
|
2226
|
-
|
|
2258
|
+
register(start) {
|
|
2227
2259
|
if (this.disposed) {
|
|
2228
|
-
disposer();
|
|
2229
2260
|
throw new Error(
|
|
2230
2261
|
"r-state-tree: cannot register reactive resources on a disposed store"
|
|
2231
2262
|
);
|
|
2232
2263
|
}
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2264
|
+
const registration = { start, disposed: false };
|
|
2265
|
+
this.reactiveRegistrations.add(registration);
|
|
2266
|
+
if (this.isMounted) registration.stop = registration.start();
|
|
2267
|
+
return () => {
|
|
2268
|
+
if (registration.disposed) return;
|
|
2269
|
+
registration.disposed = true;
|
|
2270
|
+
this.reactiveRegistrations.delete(registration);
|
|
2271
|
+
registration.stop?.();
|
|
2272
|
+
registration.stop = void 0;
|
|
2239
2273
|
};
|
|
2240
|
-
|
|
2241
|
-
|
|
2274
|
+
}
|
|
2275
|
+
startReactiveRegistrations() {
|
|
2276
|
+
this.reactiveRegistrations.forEach((registration) => {
|
|
2277
|
+
if (!registration.disposed && !registration.stop) {
|
|
2278
|
+
registration.stop = registration.start();
|
|
2279
|
+
}
|
|
2280
|
+
});
|
|
2242
2281
|
}
|
|
2243
2282
|
reaction(track, callback) {
|
|
2244
|
-
|
|
2245
|
-
return this.own(unsub);
|
|
2283
|
+
return this.register(() => reaction(track, callback));
|
|
2246
2284
|
}
|
|
2247
2285
|
effect(callback) {
|
|
2248
|
-
return this.
|
|
2286
|
+
return this.register(() => signalsCore.effect(callback));
|
|
2249
2287
|
}
|
|
2250
|
-
mount(parent = null, childName) {
|
|
2288
|
+
mount(parent = null, childName, activationQueue) {
|
|
2251
2289
|
if (this.disposed) {
|
|
2252
2290
|
throw new Error("r-state-tree: cannot mount a disposed store");
|
|
2253
2291
|
}
|
|
@@ -2263,19 +2301,27 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2263
2301
|
throw createCircularMountError(frame);
|
|
2264
2302
|
}
|
|
2265
2303
|
mountingStack.push(frame);
|
|
2304
|
+
const isOutermostMount = activationQueue === void 0;
|
|
2305
|
+
const registrationsToStart = activationQueue ?? [];
|
|
2266
2306
|
try {
|
|
2267
2307
|
signalsCore.batch(() => {
|
|
2268
2308
|
this.parent = parent || null;
|
|
2269
2309
|
this.childStoreDataMap.forEach(({ value }, name) => {
|
|
2270
2310
|
const stores = value.get();
|
|
2271
2311
|
if (Array.isArray(stores)) {
|
|
2272
|
-
stores?.forEach(
|
|
2312
|
+
stores?.forEach(
|
|
2313
|
+
(s) => getStoreAdm(s)?.mount(this, name, registrationsToStart)
|
|
2314
|
+
);
|
|
2273
2315
|
} else if (stores) {
|
|
2274
|
-
getStoreAdm(stores)?.mount(this, name);
|
|
2316
|
+
getStoreAdm(stores)?.mount(this, name, registrationsToStart);
|
|
2275
2317
|
}
|
|
2276
2318
|
});
|
|
2277
|
-
this.
|
|
2319
|
+
this.mounted = true;
|
|
2320
|
+
registrationsToStart.push(this);
|
|
2278
2321
|
});
|
|
2322
|
+
if (isOutermostMount) {
|
|
2323
|
+
StoreAdministration.flushReactiveRegistrations(registrationsToStart);
|
|
2324
|
+
}
|
|
2279
2325
|
} catch (error) {
|
|
2280
2326
|
if (error instanceof Error && (error instanceof RangeError && /call stack/i.test(error.message) || /cycle detected/i.test(error.message))) {
|
|
2281
2327
|
throw createCircularMountError(frame);
|
|
@@ -2307,9 +2353,14 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2307
2353
|
this.contextCache.clear();
|
|
2308
2354
|
this.parent = null;
|
|
2309
2355
|
});
|
|
2310
|
-
this.mountedSignal.set(false);
|
|
2311
2356
|
this.disposed = true;
|
|
2312
|
-
|
|
2357
|
+
this.reactiveRegistrations.forEach((registration) => {
|
|
2358
|
+
registration.disposed = true;
|
|
2359
|
+
registration.stop?.();
|
|
2360
|
+
registration.stop = void 0;
|
|
2361
|
+
});
|
|
2362
|
+
this.reactiveRegistrations.clear();
|
|
2363
|
+
this.mounted = false;
|
|
2313
2364
|
}
|
|
2314
2365
|
}
|
|
2315
2366
|
let initEnabled$1 = false;
|
|
@@ -2355,9 +2406,6 @@ class Store {
|
|
|
2355
2406
|
get key() {
|
|
2356
2407
|
return this.props.key;
|
|
2357
2408
|
}
|
|
2358
|
-
get isMounted() {
|
|
2359
|
-
return getStoreAdm(this).isMounted;
|
|
2360
|
-
}
|
|
2361
2409
|
reaction(track, callback) {
|
|
2362
2410
|
return getStoreAdm(this).reaction(track, callback);
|
|
2363
2411
|
}
|
|
@@ -2711,7 +2759,6 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2711
2759
|
computedSnapshot;
|
|
2712
2760
|
snapshotMap = /* @__PURE__ */ new Map();
|
|
2713
2761
|
contextCache = /* @__PURE__ */ new Map();
|
|
2714
|
-
ownedDisposers = /* @__PURE__ */ new Set();
|
|
2715
2762
|
disposed = false;
|
|
2716
2763
|
parentName = null;
|
|
2717
2764
|
get parent() {
|
|
@@ -2732,24 +2779,6 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2732
2779
|
throw new Error("r-state-tree: cannot use a disposed model");
|
|
2733
2780
|
}
|
|
2734
2781
|
}
|
|
2735
|
-
own(disposer) {
|
|
2736
|
-
this.assertUsable();
|
|
2737
|
-
let active = true;
|
|
2738
|
-
const wrapped = () => {
|
|
2739
|
-
if (!active) return;
|
|
2740
|
-
active = false;
|
|
2741
|
-
this.ownedDisposers.delete(wrapped);
|
|
2742
|
-
disposer();
|
|
2743
|
-
};
|
|
2744
|
-
this.ownedDisposers.add(wrapped);
|
|
2745
|
-
return wrapped;
|
|
2746
|
-
}
|
|
2747
|
-
reaction(track, callback) {
|
|
2748
|
-
return this.own(reaction(track, callback));
|
|
2749
|
-
}
|
|
2750
|
-
effect(callback) {
|
|
2751
|
-
return this.own(signalsCore.effect(callback));
|
|
2752
|
-
}
|
|
2753
2782
|
get configuration() {
|
|
2754
2783
|
return this.configurationGetter?.() ?? {};
|
|
2755
2784
|
}
|
|
@@ -3041,7 +3070,6 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
3041
3070
|
this.modelsTraceUnsub.clear();
|
|
3042
3071
|
this.contextCache.forEach((computed2) => computed2.clear());
|
|
3043
3072
|
this.contextCache.clear();
|
|
3044
|
-
Array.from(this.ownedDisposers).forEach((dispose) => dispose());
|
|
3045
3073
|
}
|
|
3046
3074
|
getContextValue(contextId, provideSymbol, defaultValue, hasDefault) {
|
|
3047
3075
|
let computed2 = this.contextCache.get(contextId);
|
|
@@ -3291,12 +3319,6 @@ class Model {
|
|
|
3291
3319
|
get parent() {
|
|
3292
3320
|
return getModelAdm(this).parent?.proxy ?? null;
|
|
3293
3321
|
}
|
|
3294
|
-
reaction(track, callback) {
|
|
3295
|
-
return getModelAdm(this).reaction(track, callback);
|
|
3296
|
-
}
|
|
3297
|
-
effect(callback) {
|
|
3298
|
-
return getModelAdm(this).effect(callback);
|
|
3299
|
-
}
|
|
3300
3322
|
[Symbol.dispose]() {
|
|
3301
3323
|
getModelAdm(this).dispose();
|
|
3302
3324
|
}
|
package/dist/r-state-tree.js
CHANGED
|
@@ -1992,6 +1992,32 @@ function validateStoreChildValue(value, propertyName) {
|
|
|
1992
1992
|
);
|
|
1993
1993
|
}
|
|
1994
1994
|
class StoreAdministration extends PreactObjectAdministration {
|
|
1995
|
+
static pendingActivations = [];
|
|
1996
|
+
static isFlushingActivations = false;
|
|
1997
|
+
static currentActivationDepth = 0;
|
|
1998
|
+
static flushReactiveRegistrations(stores) {
|
|
1999
|
+
const depth = this.isFlushingActivations ? this.currentActivationDepth + 1 : 0;
|
|
2000
|
+
this.pendingActivations.push(...stores.map((store) => ({ store, depth })));
|
|
2001
|
+
if (this.isFlushingActivations) return;
|
|
2002
|
+
this.isFlushingActivations = true;
|
|
2003
|
+
try {
|
|
2004
|
+
let entry;
|
|
2005
|
+
while (entry = this.pendingActivations.shift()) {
|
|
2006
|
+
this.currentActivationDepth = entry.depth;
|
|
2007
|
+
if (entry.depth > MAX_MOUNT_DEPTH) {
|
|
2008
|
+
throw createCircularMountError({
|
|
2009
|
+
storeName: entry.store.proxy.constructor.name || "Store",
|
|
2010
|
+
modelsKeys: Object.keys(entry.store.proxy.props?.models ?? {})
|
|
2011
|
+
});
|
|
2012
|
+
}
|
|
2013
|
+
entry.store.startReactiveRegistrations();
|
|
2014
|
+
}
|
|
2015
|
+
} finally {
|
|
2016
|
+
this.pendingActivations.length = 0;
|
|
2017
|
+
this.currentActivationDepth = 0;
|
|
2018
|
+
this.isFlushingActivations = false;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
1995
2021
|
static proxyTraps = Object.assign(
|
|
1996
2022
|
{},
|
|
1997
2023
|
PreactObjectAdministration.proxyTraps,
|
|
@@ -2031,11 +2057,11 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2031
2057
|
}
|
|
2032
2058
|
);
|
|
2033
2059
|
parent = null;
|
|
2034
|
-
|
|
2060
|
+
mounted = false;
|
|
2035
2061
|
disposed = false;
|
|
2036
2062
|
contextCache = /* @__PURE__ */ new Map();
|
|
2037
2063
|
childStoreDataMap = /* @__PURE__ */ new Map();
|
|
2038
|
-
|
|
2064
|
+
reactiveRegistrations = /* @__PURE__ */ new Set();
|
|
2039
2065
|
configurationGetter;
|
|
2040
2066
|
setConfiguration(configurationGetter) {
|
|
2041
2067
|
this.configurationGetter = configurationGetter;
|
|
@@ -2059,7 +2085,9 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2059
2085
|
}
|
|
2060
2086
|
});
|
|
2061
2087
|
childStoreData.value.set(stores);
|
|
2062
|
-
|
|
2088
|
+
if (this.isMounted) {
|
|
2089
|
+
stores.forEach((s) => getStoreAdm(s).mount(this, name));
|
|
2090
|
+
}
|
|
2063
2091
|
return stores;
|
|
2064
2092
|
}
|
|
2065
2093
|
const newStores = /* @__PURE__ */ new Set();
|
|
@@ -2110,7 +2138,9 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2110
2138
|
batch(() => childStoreData.value.set(stores));
|
|
2111
2139
|
}
|
|
2112
2140
|
removedStores.forEach((s) => getStoreAdm(s).dispose(true));
|
|
2113
|
-
|
|
2141
|
+
if (this.isMounted) {
|
|
2142
|
+
newStores.forEach((s) => getStoreAdm(s).mount(this, name));
|
|
2143
|
+
}
|
|
2114
2144
|
return stores;
|
|
2115
2145
|
}
|
|
2116
2146
|
setSingleStore(name, element) {
|
|
@@ -2129,7 +2159,9 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2129
2159
|
}
|
|
2130
2160
|
const childStore = this.createChildStore(element);
|
|
2131
2161
|
batch(() => childStoreData.value.set(childStore));
|
|
2132
|
-
|
|
2162
|
+
if (this.isMounted) {
|
|
2163
|
+
getStoreAdm(childStore).mount(this, name);
|
|
2164
|
+
}
|
|
2133
2165
|
return childStore;
|
|
2134
2166
|
} else {
|
|
2135
2167
|
batch(() => updateProps(oldStore.props, props));
|
|
@@ -2187,7 +2219,7 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2187
2219
|
return !this.parent;
|
|
2188
2220
|
}
|
|
2189
2221
|
get isMounted() {
|
|
2190
|
-
return this.
|
|
2222
|
+
return this.mounted;
|
|
2191
2223
|
}
|
|
2192
2224
|
getContextValue(contextId, provideSymbol, defaultValue, hasDefault) {
|
|
2193
2225
|
let computed2 = this.contextCache.get(contextId);
|
|
@@ -2222,31 +2254,37 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2222
2254
|
}
|
|
2223
2255
|
return void 0;
|
|
2224
2256
|
}
|
|
2225
|
-
|
|
2257
|
+
register(start) {
|
|
2226
2258
|
if (this.disposed) {
|
|
2227
|
-
disposer();
|
|
2228
2259
|
throw new Error(
|
|
2229
2260
|
"r-state-tree: cannot register reactive resources on a disposed store"
|
|
2230
2261
|
);
|
|
2231
2262
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2263
|
+
const registration = { start, disposed: false };
|
|
2264
|
+
this.reactiveRegistrations.add(registration);
|
|
2265
|
+
if (this.isMounted) registration.stop = registration.start();
|
|
2266
|
+
return () => {
|
|
2267
|
+
if (registration.disposed) return;
|
|
2268
|
+
registration.disposed = true;
|
|
2269
|
+
this.reactiveRegistrations.delete(registration);
|
|
2270
|
+
registration.stop?.();
|
|
2271
|
+
registration.stop = void 0;
|
|
2238
2272
|
};
|
|
2239
|
-
|
|
2240
|
-
|
|
2273
|
+
}
|
|
2274
|
+
startReactiveRegistrations() {
|
|
2275
|
+
this.reactiveRegistrations.forEach((registration) => {
|
|
2276
|
+
if (!registration.disposed && !registration.stop) {
|
|
2277
|
+
registration.stop = registration.start();
|
|
2278
|
+
}
|
|
2279
|
+
});
|
|
2241
2280
|
}
|
|
2242
2281
|
reaction(track, callback) {
|
|
2243
|
-
|
|
2244
|
-
return this.own(unsub);
|
|
2282
|
+
return this.register(() => reaction(track, callback));
|
|
2245
2283
|
}
|
|
2246
2284
|
effect(callback) {
|
|
2247
|
-
return this.
|
|
2285
|
+
return this.register(() => effect(callback));
|
|
2248
2286
|
}
|
|
2249
|
-
mount(parent = null, childName) {
|
|
2287
|
+
mount(parent = null, childName, activationQueue) {
|
|
2250
2288
|
if (this.disposed) {
|
|
2251
2289
|
throw new Error("r-state-tree: cannot mount a disposed store");
|
|
2252
2290
|
}
|
|
@@ -2262,19 +2300,27 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2262
2300
|
throw createCircularMountError(frame);
|
|
2263
2301
|
}
|
|
2264
2302
|
mountingStack.push(frame);
|
|
2303
|
+
const isOutermostMount = activationQueue === void 0;
|
|
2304
|
+
const registrationsToStart = activationQueue ?? [];
|
|
2265
2305
|
try {
|
|
2266
2306
|
batch(() => {
|
|
2267
2307
|
this.parent = parent || null;
|
|
2268
2308
|
this.childStoreDataMap.forEach(({ value }, name) => {
|
|
2269
2309
|
const stores = value.get();
|
|
2270
2310
|
if (Array.isArray(stores)) {
|
|
2271
|
-
stores?.forEach(
|
|
2311
|
+
stores?.forEach(
|
|
2312
|
+
(s) => getStoreAdm(s)?.mount(this, name, registrationsToStart)
|
|
2313
|
+
);
|
|
2272
2314
|
} else if (stores) {
|
|
2273
|
-
getStoreAdm(stores)?.mount(this, name);
|
|
2315
|
+
getStoreAdm(stores)?.mount(this, name, registrationsToStart);
|
|
2274
2316
|
}
|
|
2275
2317
|
});
|
|
2276
|
-
this.
|
|
2318
|
+
this.mounted = true;
|
|
2319
|
+
registrationsToStart.push(this);
|
|
2277
2320
|
});
|
|
2321
|
+
if (isOutermostMount) {
|
|
2322
|
+
StoreAdministration.flushReactiveRegistrations(registrationsToStart);
|
|
2323
|
+
}
|
|
2278
2324
|
} catch (error) {
|
|
2279
2325
|
if (error instanceof Error && (error instanceof RangeError && /call stack/i.test(error.message) || /cycle detected/i.test(error.message))) {
|
|
2280
2326
|
throw createCircularMountError(frame);
|
|
@@ -2306,9 +2352,14 @@ class StoreAdministration extends PreactObjectAdministration {
|
|
|
2306
2352
|
this.contextCache.clear();
|
|
2307
2353
|
this.parent = null;
|
|
2308
2354
|
});
|
|
2309
|
-
this.mountedSignal.set(false);
|
|
2310
2355
|
this.disposed = true;
|
|
2311
|
-
|
|
2356
|
+
this.reactiveRegistrations.forEach((registration) => {
|
|
2357
|
+
registration.disposed = true;
|
|
2358
|
+
registration.stop?.();
|
|
2359
|
+
registration.stop = void 0;
|
|
2360
|
+
});
|
|
2361
|
+
this.reactiveRegistrations.clear();
|
|
2362
|
+
this.mounted = false;
|
|
2312
2363
|
}
|
|
2313
2364
|
}
|
|
2314
2365
|
let initEnabled$1 = false;
|
|
@@ -2354,9 +2405,6 @@ class Store {
|
|
|
2354
2405
|
get key() {
|
|
2355
2406
|
return this.props.key;
|
|
2356
2407
|
}
|
|
2357
|
-
get isMounted() {
|
|
2358
|
-
return getStoreAdm(this).isMounted;
|
|
2359
|
-
}
|
|
2360
2408
|
reaction(track, callback) {
|
|
2361
2409
|
return getStoreAdm(this).reaction(track, callback);
|
|
2362
2410
|
}
|
|
@@ -2710,7 +2758,6 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2710
2758
|
computedSnapshot;
|
|
2711
2759
|
snapshotMap = /* @__PURE__ */ new Map();
|
|
2712
2760
|
contextCache = /* @__PURE__ */ new Map();
|
|
2713
|
-
ownedDisposers = /* @__PURE__ */ new Set();
|
|
2714
2761
|
disposed = false;
|
|
2715
2762
|
parentName = null;
|
|
2716
2763
|
get parent() {
|
|
@@ -2731,24 +2778,6 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
2731
2778
|
throw new Error("r-state-tree: cannot use a disposed model");
|
|
2732
2779
|
}
|
|
2733
2780
|
}
|
|
2734
|
-
own(disposer) {
|
|
2735
|
-
this.assertUsable();
|
|
2736
|
-
let active = true;
|
|
2737
|
-
const wrapped = () => {
|
|
2738
|
-
if (!active) return;
|
|
2739
|
-
active = false;
|
|
2740
|
-
this.ownedDisposers.delete(wrapped);
|
|
2741
|
-
disposer();
|
|
2742
|
-
};
|
|
2743
|
-
this.ownedDisposers.add(wrapped);
|
|
2744
|
-
return wrapped;
|
|
2745
|
-
}
|
|
2746
|
-
reaction(track, callback) {
|
|
2747
|
-
return this.own(reaction(track, callback));
|
|
2748
|
-
}
|
|
2749
|
-
effect(callback) {
|
|
2750
|
-
return this.own(effect(callback));
|
|
2751
|
-
}
|
|
2752
2781
|
get configuration() {
|
|
2753
2782
|
return this.configurationGetter?.() ?? {};
|
|
2754
2783
|
}
|
|
@@ -3040,7 +3069,6 @@ class ModelAdministration extends PreactObjectAdministration {
|
|
|
3040
3069
|
this.modelsTraceUnsub.clear();
|
|
3041
3070
|
this.contextCache.forEach((computed2) => computed2.clear());
|
|
3042
3071
|
this.contextCache.clear();
|
|
3043
|
-
Array.from(this.ownedDisposers).forEach((dispose) => dispose());
|
|
3044
3072
|
}
|
|
3045
3073
|
getContextValue(contextId, provideSymbol, defaultValue, hasDefault) {
|
|
3046
3074
|
let computed2 = this.contextCache.get(contextId);
|
|
@@ -3290,12 +3318,6 @@ class Model {
|
|
|
3290
3318
|
get parent() {
|
|
3291
3319
|
return getModelAdm(this).parent?.proxy ?? null;
|
|
3292
3320
|
}
|
|
3293
|
-
reaction(track, callback) {
|
|
3294
|
-
return getModelAdm(this).reaction(track, callback);
|
|
3295
|
-
}
|
|
3296
|
-
effect(callback) {
|
|
3297
|
-
return getModelAdm(this).effect(callback);
|
|
3298
|
-
}
|
|
3299
3321
|
[Symbol.dispose]() {
|
|
3300
3322
|
getModelAdm(this).dispose();
|
|
3301
3323
|
}
|
package/dist/store/Store.d.ts
CHANGED
|
@@ -13,7 +13,6 @@ export default class Store<PropsType extends Record<string, any> = StoreProps<Pr
|
|
|
13
13
|
props: StoreProps<PropsType>;
|
|
14
14
|
constructor(props: StoreProps<PropsType>);
|
|
15
15
|
get key(): string | number | undefined;
|
|
16
|
-
get isMounted(): boolean;
|
|
17
16
|
reaction<T>(track: () => T, callback: (value: T, previousValue: T) => void): () => void;
|
|
18
17
|
effect(callback: () => void | (() => void)): () => void;
|
|
19
18
|
[Symbol.dispose](): void;
|
|
@@ -4,13 +4,17 @@ import type { StoreConfiguration, Props } from "../types";
|
|
|
4
4
|
export declare function updateProps(props: Props, newProps: Props): void;
|
|
5
5
|
export declare function getStoreAdm(store: Store): StoreAdministration;
|
|
6
6
|
export declare class StoreAdministration<StoreType extends Store = Store> extends ObjectAdministration<Store> {
|
|
7
|
+
private static pendingActivations;
|
|
8
|
+
private static isFlushingActivations;
|
|
9
|
+
private static currentActivationDepth;
|
|
10
|
+
private static flushReactiveRegistrations;
|
|
7
11
|
static proxyTraps: ProxyHandler<object>;
|
|
8
12
|
parent: StoreAdministration | null;
|
|
9
|
-
private
|
|
13
|
+
private mounted;
|
|
10
14
|
private disposed;
|
|
11
15
|
private contextCache;
|
|
12
16
|
private childStoreDataMap;
|
|
13
|
-
private
|
|
17
|
+
private reactiveRegistrations;
|
|
14
18
|
private configurationGetter?;
|
|
15
19
|
setConfiguration(configurationGetter: () => StoreConfiguration<StoreType>): void;
|
|
16
20
|
private get configuration();
|
|
@@ -26,9 +30,10 @@ export declare class StoreAdministration<StoreType extends Store = Store> extend
|
|
|
26
30
|
get isMounted(): boolean;
|
|
27
31
|
getContextValue<T>(contextId: symbol, provideSymbol: symbol, defaultValue: T | undefined, hasDefault: boolean): T;
|
|
28
32
|
private lookupContextValue;
|
|
29
|
-
private
|
|
33
|
+
private register;
|
|
34
|
+
private startReactiveRegistrations;
|
|
30
35
|
reaction<T>(track: () => T, callback: (value: T, previousValue: T) => void): () => void;
|
|
31
36
|
effect(callback: () => void | (() => void)): () => void;
|
|
32
|
-
mount(parent?: StoreAdministration | null, childName?: PropertyKey): void;
|
|
37
|
+
mount(parent?: StoreAdministration | null, childName?: PropertyKey, activationQueue?: StoreAdministration[]): void;
|
|
33
38
|
dispose(internal?: boolean): void;
|
|
34
39
|
}
|