@xmachines/play-actor 2.0.0 → 2.1.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 +61 -54
- package/dist/abstract-actor.d.ts +97 -89
- package/dist/abstract-actor.d.ts.map +1 -1
- package/dist/abstract-actor.js +34 -33
- package/dist/abstract-actor.js.map +1 -1
- package/dist/context-projection.d.ts +74 -67
- package/dist/context-projection.d.ts.map +1 -1
- package/dist/context-projection.js +90 -82
- package/dist/context-projection.js.map +1 -1
- package/dist/index.d.ts +11 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -9
- package/dist/index.js.map +1 -1
- package/dist/provider-guards.d.ts +37 -33
- package/dist/provider-guards.d.ts.map +1 -1
- package/dist/provider-guards.js +34 -30
- package/dist/provider-guards.js.map +1 -1
- package/dist/view-store-lifecycle.d.ts +46 -41
- package/dist/view-store-lifecycle.d.ts.map +1 -1
- package/dist/view-store-lifecycle.js +28 -25
- package/dist/view-store-lifecycle.js.map +1 -1
- package/package.json +4 -3
|
@@ -1,54 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The shared provider guards of the ActorProvider implementation of each framework.
|
|
3
3
|
*
|
|
4
|
-
* Every framework integration (React, Vue, Solid, Svelte, DOM)
|
|
5
|
-
* two
|
|
4
|
+
* Every framework integration (React, Vue, Solid, Svelte, and DOM) does the same
|
|
5
|
+
* two steps when it connects the view of an actor to a json-render tree:
|
|
6
6
|
*
|
|
7
|
-
* 1.
|
|
7
|
+
* 1. It cleans `spec.state` before it seeds a new `@xstate/store` atom
|
|
8
8
|
* ({@link toAtomState}).
|
|
9
|
-
* 2.
|
|
10
|
-
* registry
|
|
9
|
+
* 2. It puts an `onRenderError` handler of the component level into the component
|
|
10
|
+
* registry, and it does not change the registry of the caller
|
|
11
11
|
* ({@link attachRenderErrorHandler}).
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* Both functions are here. Therefore the semantics of the guards are identical in
|
|
14
|
+
* every framework.
|
|
14
15
|
*
|
|
15
16
|
* @packageDocumentation
|
|
16
17
|
*/
|
|
17
18
|
import type { RenderErrorHandler } from "@xmachines/json-render-core";
|
|
18
19
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `spec.state`
|
|
22
|
-
* `
|
|
23
|
-
*
|
|
24
|
-
* its
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
20
|
+
* Converts the `state` field of a spec into a plain object for `createAtom`, in a safe way.
|
|
21
|
+
*
|
|
22
|
+
* `spec.state` has the type `unknown` in `PlaySpec`. At run time it is `null`,
|
|
23
|
+
* `undefined`, a primitive, or a plain object, and this depends on the value that
|
|
24
|
+
* the author of the machine put in the view spec. `createAtom` requires a plain
|
|
25
|
+
* object as its first value, because every other value makes a broken store at run
|
|
26
|
+
* time.
|
|
27
|
+
*
|
|
28
|
+
* The function accepts a plain object only, which means that its prototype is
|
|
29
|
+
* `Object.prototype` or `null`, and it returns that object without a change. Every
|
|
30
|
+
* other value becomes a new `{}`: `null`, `undefined`, a primitive, an array, an
|
|
31
|
+
* instance of a class, and a built-in object such as a Date, a Map, or a Set. A
|
|
32
|
+
* broken store therefore never appears at run time.
|
|
33
|
+
*
|
|
34
|
+
* @param state - The raw `spec.state` value of a `PlaySpec`.
|
|
35
|
+
* @returns `state` itself when it is a plain object. In every other case, a new empty object.
|
|
33
36
|
*/
|
|
34
37
|
export declare function toAtomState(state: unknown): Record<string, unknown>;
|
|
35
38
|
/**
|
|
36
|
-
*
|
|
39
|
+
* Copies a component registry, and puts an `onRenderError` handler into the copy.
|
|
37
40
|
*
|
|
38
|
-
* The
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
41
|
+
* The function defines the handler as an own property of the copy. That property is
|
|
42
|
+
* not enumerable, and it is configurable (D-19 gives one convention of the
|
|
43
|
+
* injection for every framework renderer). The handler therefore replaces each
|
|
44
|
+
* handler of the `defineRegistry` level, and it does not appear in an enumeration of
|
|
45
|
+
* the component entries of the registry.
|
|
42
46
|
*
|
|
43
|
-
* The
|
|
44
|
-
* that
|
|
45
|
-
* `
|
|
46
|
-
* providers
|
|
47
|
+
* The function never changes the registry of the caller: it returns a shallow copy.
|
|
48
|
+
* Therefore a caller that needs a handler for each instance, such as an
|
|
49
|
+
* `onRenderError` prop of `ActorProvider`, can share one result of `defineRegistry`
|
|
50
|
+
* between the providers in a safe way.
|
|
47
51
|
*
|
|
48
|
-
* @typeParam TRegistry - The
|
|
52
|
+
* @typeParam TRegistry - The component registry type of the framework.
|
|
49
53
|
* @param registry - The component registry from `defineRegistry().registry`.
|
|
50
|
-
* @param handler -
|
|
51
|
-
* @returns A shallow
|
|
54
|
+
* @param handler - The renderer calls it with `(error, componentName)` when a catalog component throws during a render.
|
|
55
|
+
* @returns A shallow copy of `registry`, with `onRenderError` on it.
|
|
52
56
|
*/
|
|
53
57
|
export declare function attachRenderErrorHandler<TRegistry extends object>(registry: TRegistry, handler: RenderErrorHandler): TRegistry;
|
|
54
58
|
//# sourceMappingURL=provider-guards.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-guards.d.ts","sourceRoot":"","sources":["../src/provider-guards.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"provider-guards.d.ts","sourceRoot":"","sources":["../src/provider-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEtE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQnE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,SAAS,MAAM,EAChE,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,kBAAkB,GACzB,SAAS,CAQX"}
|
package/dist/provider-guards.js
CHANGED
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The shared provider guards of the ActorProvider implementation of each framework.
|
|
3
3
|
*
|
|
4
|
-
* Every framework integration (React, Vue, Solid, Svelte, DOM)
|
|
5
|
-
* two
|
|
4
|
+
* Every framework integration (React, Vue, Solid, Svelte, and DOM) does the same
|
|
5
|
+
* two steps when it connects the view of an actor to a json-render tree:
|
|
6
6
|
*
|
|
7
|
-
* 1.
|
|
7
|
+
* 1. It cleans `spec.state` before it seeds a new `@xstate/store` atom
|
|
8
8
|
* ({@link toAtomState}).
|
|
9
|
-
* 2.
|
|
10
|
-
* registry
|
|
9
|
+
* 2. It puts an `onRenderError` handler of the component level into the component
|
|
10
|
+
* registry, and it does not change the registry of the caller
|
|
11
11
|
* ({@link attachRenderErrorHandler}).
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* Both functions are here. Therefore the semantics of the guards are identical in
|
|
14
|
+
* every framework.
|
|
14
15
|
*
|
|
15
16
|
* @packageDocumentation
|
|
16
17
|
*/
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
+
* Converts the `state` field of a spec into a plain object for `createAtom`, in a safe way.
|
|
19
20
|
*
|
|
20
|
-
* `spec.state`
|
|
21
|
-
* `
|
|
22
|
-
*
|
|
23
|
-
* its
|
|
21
|
+
* `spec.state` has the type `unknown` in `PlaySpec`. At run time it is `null`,
|
|
22
|
+
* `undefined`, a primitive, or a plain object, and this depends on the value that
|
|
23
|
+
* the author of the machine put in the view spec. `createAtom` requires a plain
|
|
24
|
+
* object as its first value, because every other value makes a broken store at run
|
|
25
|
+
* time.
|
|
24
26
|
*
|
|
25
|
-
*
|
|
26
|
-
* and
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* The function accepts a plain object only, which means that its prototype is
|
|
28
|
+
* `Object.prototype` or `null`, and it returns that object without a change. Every
|
|
29
|
+
* other value becomes a new `{}`: `null`, `undefined`, a primitive, an array, an
|
|
30
|
+
* instance of a class, and a built-in object such as a Date, a Map, or a Set. A
|
|
31
|
+
* broken store therefore never appears at run time.
|
|
29
32
|
*
|
|
30
|
-
* @param state - The raw `spec.state` value
|
|
31
|
-
* @returns `state` itself when it is a plain object,
|
|
33
|
+
* @param state - The raw `spec.state` value of a `PlaySpec`.
|
|
34
|
+
* @returns `state` itself when it is a plain object. In every other case, a new empty object.
|
|
32
35
|
*/
|
|
33
36
|
export function toAtomState(state) {
|
|
34
37
|
if (state !== null && typeof state === "object" && !Array.isArray(state)) {
|
|
@@ -40,22 +43,23 @@ export function toAtomState(state) {
|
|
|
40
43
|
return {};
|
|
41
44
|
}
|
|
42
45
|
/**
|
|
43
|
-
*
|
|
46
|
+
* Copies a component registry, and puts an `onRenderError` handler into the copy.
|
|
44
47
|
*
|
|
45
|
-
* The
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
48
|
+
* The function defines the handler as an own property of the copy. That property is
|
|
49
|
+
* not enumerable, and it is configurable (D-19 gives one convention of the
|
|
50
|
+
* injection for every framework renderer). The handler therefore replaces each
|
|
51
|
+
* handler of the `defineRegistry` level, and it does not appear in an enumeration of
|
|
52
|
+
* the component entries of the registry.
|
|
49
53
|
*
|
|
50
|
-
* The
|
|
51
|
-
* that
|
|
52
|
-
* `
|
|
53
|
-
* providers
|
|
54
|
+
* The function never changes the registry of the caller: it returns a shallow copy.
|
|
55
|
+
* Therefore a caller that needs a handler for each instance, such as an
|
|
56
|
+
* `onRenderError` prop of `ActorProvider`, can share one result of `defineRegistry`
|
|
57
|
+
* between the providers in a safe way.
|
|
54
58
|
*
|
|
55
|
-
* @typeParam TRegistry - The
|
|
59
|
+
* @typeParam TRegistry - The component registry type of the framework.
|
|
56
60
|
* @param registry - The component registry from `defineRegistry().registry`.
|
|
57
|
-
* @param handler -
|
|
58
|
-
* @returns A shallow
|
|
61
|
+
* @param handler - The renderer calls it with `(error, componentName)` when a catalog component throws during a render.
|
|
62
|
+
* @returns A shallow copy of `registry`, with `onRenderError` on it.
|
|
59
63
|
*/
|
|
60
64
|
export function attachRenderErrorHandler(registry, handler) {
|
|
61
65
|
const clone = { ...registry };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-guards.js","sourceRoot":"","sources":["../src/provider-guards.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"provider-guards.js","sourceRoot":"","sources":["../src/provider-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACzC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAY,CAAC;QACtD,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAClD,OAAO,KAAgC,CAAC;QACzC,CAAC;IACF,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,wBAAwB,CACvC,QAAmB,EACnB,OAA2B;IAE3B,MAAM,KAAK,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC9B,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE;QAC7C,KAAK,EAAE,OAAO;QACd,UAAU,EAAE,KAAK;QACjB,YAAY,EAAE,IAAI;KAClB,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -1,77 +1,82 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* The lifecycle of the view store — the framework-agnostic decision between a new
|
|
3
|
+
* seed and a refresh. Each provider connects it to its own reactivity.
|
|
4
4
|
*
|
|
5
|
-
* The policy in one place
|
|
6
|
-
* copies
|
|
5
|
+
* The policy is in one place now. Each renderer held a copy of it before, and those
|
|
6
|
+
* copies moved apart into real faults:
|
|
7
7
|
*
|
|
8
|
-
* - `viewKey` changed
|
|
9
|
-
* store from the
|
|
10
|
-
* - `viewKey`
|
|
11
|
-
* `/context` subtree
|
|
12
|
-
*
|
|
13
|
-
* - No `viewKey
|
|
14
|
-
* EMISSION, the safe
|
|
15
|
-
*
|
|
16
|
-
* -
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
8
|
+
* - The `viewKey` changed, or this is the first resolve, or the tree provides a
|
|
9
|
+
* different actor → NEW SEED: a new store, from the composed state of the view.
|
|
10
|
+
* - The `viewKey` did not change → REFRESH: only the /context projection moved.
|
|
11
|
+
* Therefore the code replaces the `/context` subtree in place, and the ephemeral
|
|
12
|
+
* state at the root level, such as a draft or a toggle, stays.
|
|
13
|
+
* - No `viewKey`, from a Viewable that a person built and that stamps no key → a new
|
|
14
|
+
* seed for each EMISSION, which is the safe behavior from the time before the
|
|
15
|
+
* viewKey.
|
|
16
|
+
* - A different actor → the store that stays alive dies with its actor. This is the
|
|
17
|
+
* rule of the lifetime.
|
|
18
|
+
* - The controlled mode, where the caller gives the store → the caller owns the seed
|
|
19
|
+
* and the lifecycle. The machinery owns /context in both modes, and this file
|
|
20
|
+
* refreshes it. The caller can move that refresh to a later moment
|
|
21
|
+
* ({@link ResolveViewStoreOptions}), and the render path of React needs this,
|
|
22
|
+
* because a store must notify no subscriber during a render. The effects of React
|
|
23
|
+
* then do the refresh.
|
|
21
24
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
25
|
+
* Each provider therefore holds the wiring of its reactivity only: the moment of
|
|
26
|
+
* the resolve, and the path of the result to the children.
|
|
24
27
|
*
|
|
25
28
|
* @packageDocumentation
|
|
26
29
|
*/
|
|
27
30
|
import type { StateStore } from "@xmachines/json-render-core";
|
|
28
31
|
import type { PlaySpec } from "./abstract-actor.js";
|
|
29
|
-
/**
|
|
32
|
+
/** The result of a resolve — see {@link ViewStoreLifecycle.resolve}. */
|
|
30
33
|
export interface ViewStoreResolution {
|
|
31
|
-
/** The
|
|
34
|
+
/** The store WITHOUT the guard — the reference of the machinery for its own refresh. */
|
|
32
35
|
store: StateStore;
|
|
33
36
|
/**
|
|
34
|
-
* The store to
|
|
35
|
-
* under /context
|
|
36
|
-
*
|
|
37
|
+
* The store to give to the children ($bindState, setState, and a chained set): a
|
|
38
|
+
* write under /context throws. There is one wrapper for each store below it, and
|
|
39
|
+
* the code caches the identity. Therefore a consumer in the style of
|
|
40
|
+
* `useSyncExternalStore` stays stable.
|
|
37
41
|
*/
|
|
38
42
|
guardedStore: StateStore;
|
|
39
43
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* subtree
|
|
44
|
+
* It is true when this resolve made a new store: at the first resolve, on a change
|
|
45
|
+
* of the viewKey, in the fallback for each emission, and on a change of the actor. A
|
|
46
|
+
* provider that mounts a subtree again for each store, such as the storeKey of Vue,
|
|
47
|
+
* uses this field as its key.
|
|
43
48
|
*/
|
|
44
49
|
reseeded: boolean;
|
|
45
50
|
}
|
|
46
51
|
export interface ResolveViewStoreOptions {
|
|
47
52
|
/**
|
|
48
|
-
*
|
|
49
|
-
* resolve
|
|
50
|
-
*
|
|
51
|
-
* effect instead.
|
|
53
|
+
* The controlled mode only: refresh the /context subtree of the external store
|
|
54
|
+
* during this resolve. The default is true. Give false where the call site permits
|
|
55
|
+
* no notification of the store subscribers, which is the render path of React, and
|
|
56
|
+
* refresh from an effect instead.
|
|
52
57
|
*/
|
|
53
58
|
refreshExternalStore?: boolean;
|
|
54
59
|
}
|
|
55
60
|
export interface ViewStoreLifecycle {
|
|
56
61
|
/**
|
|
57
|
-
*
|
|
62
|
+
* Brings the store in line with an emission, and returns it with its guard.
|
|
58
63
|
*
|
|
59
|
-
* @param actor - The actor the emission
|
|
60
|
-
* @param view - The derived view
|
|
61
|
-
* new view
|
|
62
|
-
* @param externalStore -
|
|
64
|
+
* @param actor - The actor of the emission. A different actor drops the store that the code kept.
|
|
65
|
+
* @param view - The derived view. It is not null: a null emission is a GAP, and not
|
|
66
|
+
* a new view. A caller resolves nothing on a null value, and it keeps the store.
|
|
67
|
+
* @param externalStore - The controlled mode: the store of the caller.
|
|
63
68
|
* @param options - See {@link ResolveViewStoreOptions}.
|
|
64
69
|
*/
|
|
65
70
|
resolve(actor: unknown, view: PlaySpec, externalStore?: StateStore | undefined, options?: ResolveViewStoreOptions): ViewStoreResolution;
|
|
66
|
-
/**
|
|
71
|
+
/** Drops everything, on an unmount or a disconnect. The next resolve makes a new seed. */
|
|
67
72
|
reset(): void;
|
|
68
73
|
}
|
|
69
74
|
/**
|
|
70
|
-
*
|
|
75
|
+
* Creates a coordinator of the lifecycle.
|
|
71
76
|
*
|
|
72
|
-
* @param createStore -
|
|
73
|
-
*
|
|
74
|
-
* carries /context
|
|
77
|
+
* @param createStore - The store factory of the framework. It receives the seed
|
|
78
|
+
* that is safe for the prototype (`toAtomState(view.state)`), and the composed
|
|
79
|
+
* state carries /context already.
|
|
75
80
|
*/
|
|
76
81
|
export declare function createViewStoreLifecycle(createStore: (seed: Record<string, unknown>) => StateStore): ViewStoreLifecycle;
|
|
77
82
|
//# sourceMappingURL=view-store-lifecycle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-store-lifecycle.d.ts","sourceRoot":"","sources":["../src/view-store-lifecycle.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"view-store-lifecycle.d.ts","sourceRoot":"","sources":["../src/view-store-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,wEAAwE;AACxE,MAAM,WAAW,mBAAmB;IACnC,wFAAwF;IACxF,KAAK,EAAE,UAAU,CAAC;IAClB;;;;;OAKG;IACH,YAAY,EAAE,UAAU,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACvC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IAClC;;;;;;;;OAQG;IACH,OAAO,CACN,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,QAAQ,EACd,aAAa,CAAC,EAAE,UAAU,GAAG,SAAS,EACtC,OAAO,CAAC,EAAE,uBAAuB,GAC/B,mBAAmB,CAAC;IACvB,0FAA0F;IAC1F,KAAK,IAAI,IAAI,CAAC;CACd;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,UAAU,GACxD,kBAAkB,CA4DpB"}
|
|
@@ -1,44 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* The lifecycle of the view store — the framework-agnostic decision between a new
|
|
3
|
+
* seed and a refresh. Each provider connects it to its own reactivity.
|
|
4
4
|
*
|
|
5
|
-
* The policy in one place
|
|
6
|
-
* copies
|
|
5
|
+
* The policy is in one place now. Each renderer held a copy of it before, and those
|
|
6
|
+
* copies moved apart into real faults:
|
|
7
7
|
*
|
|
8
|
-
* - `viewKey` changed
|
|
9
|
-
* store from the
|
|
10
|
-
* - `viewKey`
|
|
11
|
-
* `/context` subtree
|
|
12
|
-
*
|
|
13
|
-
* - No `viewKey
|
|
14
|
-
* EMISSION, the safe
|
|
15
|
-
*
|
|
16
|
-
* -
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
8
|
+
* - The `viewKey` changed, or this is the first resolve, or the tree provides a
|
|
9
|
+
* different actor → NEW SEED: a new store, from the composed state of the view.
|
|
10
|
+
* - The `viewKey` did not change → REFRESH: only the /context projection moved.
|
|
11
|
+
* Therefore the code replaces the `/context` subtree in place, and the ephemeral
|
|
12
|
+
* state at the root level, such as a draft or a toggle, stays.
|
|
13
|
+
* - No `viewKey`, from a Viewable that a person built and that stamps no key → a new
|
|
14
|
+
* seed for each EMISSION, which is the safe behavior from the time before the
|
|
15
|
+
* viewKey.
|
|
16
|
+
* - A different actor → the store that stays alive dies with its actor. This is the
|
|
17
|
+
* rule of the lifetime.
|
|
18
|
+
* - The controlled mode, where the caller gives the store → the caller owns the seed
|
|
19
|
+
* and the lifecycle. The machinery owns /context in both modes, and this file
|
|
20
|
+
* refreshes it. The caller can move that refresh to a later moment
|
|
21
|
+
* ({@link ResolveViewStoreOptions}), and the render path of React needs this,
|
|
22
|
+
* because a store must notify no subscriber during a render. The effects of React
|
|
23
|
+
* then do the refresh.
|
|
21
24
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
25
|
+
* Each provider therefore holds the wiring of its reactivity only: the moment of
|
|
26
|
+
* the resolve, and the path of the result to the children.
|
|
24
27
|
*
|
|
25
28
|
* @packageDocumentation
|
|
26
29
|
*/
|
|
27
30
|
import { guardContextWrites, refreshContextSubtree } from "./context-projection.js";
|
|
28
31
|
import { toAtomState } from "./provider-guards.js";
|
|
29
32
|
/**
|
|
30
|
-
*
|
|
33
|
+
* Creates a coordinator of the lifecycle.
|
|
31
34
|
*
|
|
32
|
-
* @param createStore -
|
|
33
|
-
*
|
|
34
|
-
* carries /context
|
|
35
|
+
* @param createStore - The store factory of the framework. It receives the seed
|
|
36
|
+
* that is safe for the prototype (`toAtomState(view.state)`), and the composed
|
|
37
|
+
* state carries /context already.
|
|
35
38
|
*/
|
|
36
39
|
export function createViewStoreLifecycle(createStore) {
|
|
37
40
|
let internalStore = null;
|
|
38
41
|
let lastViewKey = undefined;
|
|
39
42
|
let lastView = null;
|
|
40
43
|
let lastActor = null;
|
|
41
|
-
//
|
|
44
|
+
// The identity cache of the guard: one wrapper for each store below it.
|
|
42
45
|
let guardedSource = null;
|
|
43
46
|
let guardedStore = null;
|
|
44
47
|
const reset = () => {
|
|
@@ -52,7 +55,7 @@ export function createViewStoreLifecycle(createStore) {
|
|
|
52
55
|
return {
|
|
53
56
|
reset,
|
|
54
57
|
resolve(actor, view, externalStore, options) {
|
|
55
|
-
//
|
|
58
|
+
// The rule of the lifetime: a store that stays alive must not outlive its actor.
|
|
56
59
|
if (lastActor !== actor) {
|
|
57
60
|
const firstResolve = lastActor === null && internalStore === null;
|
|
58
61
|
if (!firstResolve)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-store-lifecycle.js","sourceRoot":"","sources":["../src/view-store-lifecycle.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"view-store-lifecycle.js","sourceRoot":"","sources":["../src/view-store-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAoDnD;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACvC,WAA0D;IAE1D,IAAI,aAAa,GAAsB,IAAI,CAAC;IAC5C,IAAI,WAAW,GAAuB,SAAS,CAAC;IAChD,IAAI,QAAQ,GAAoB,IAAI,CAAC;IACrC,IAAI,SAAS,GAAY,IAAI,CAAC;IAC9B,wEAAwE;IACxE,IAAI,aAAa,GAAsB,IAAI,CAAC;IAC5C,IAAI,YAAY,GAAsB,IAAI,CAAC;IAE3C,MAAM,KAAK,GAAG,GAAS,EAAE;QACxB,aAAa,GAAG,IAAI,CAAC;QACrB,WAAW,GAAG,SAAS,CAAC;QACxB,QAAQ,GAAG,IAAI,CAAC;QAChB,SAAS,GAAG,IAAI,CAAC;QACjB,aAAa,GAAG,IAAI,CAAC;QACrB,YAAY,GAAG,IAAI,CAAC;IACrB,CAAC,CAAC;IAEF,OAAO;QACN,KAAK;QACL,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO;YAC1C,iFAAiF;YACjF,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;gBACzB,MAAM,YAAY,GAAG,SAAS,KAAK,IAAI,IAAI,aAAa,KAAK,IAAI,CAAC;gBAClE,IAAI,CAAC,YAAY;oBAAE,KAAK,EAAE,CAAC;gBAC3B,SAAS,GAAG,KAAK,CAAC;YACnB,CAAC;YAED,IAAI,QAAoB,CAAC;YACzB,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,IAAI,aAAa,EAAE,CAAC;gBACnB,QAAQ,GAAG,aAAa,CAAC;gBACzB,IAAI,OAAO,EAAE,oBAAoB,KAAK,KAAK,EAAE,CAAC;oBAC7C,qBAAqB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACvC,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;gBAC7B,IAAI,SAAS,GAAsB,aAAa,CAAC;gBACjD,IACC,SAAS,KAAK,IAAI;oBAClB,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,EACpE,CAAC;oBACF,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;oBACjD,aAAa,GAAG,SAAS,CAAC;oBAC1B,WAAW,GAAG,OAAO,CAAC;oBACtB,QAAQ,GAAG,IAAI,CAAC;gBACjB,CAAC;qBAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAClC,qBAAqB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;gBACxC,CAAC;gBACD,QAAQ,GAAG,IAAI,CAAC;gBAChB,QAAQ,GAAG,SAAS,CAAC;YACtB,CAAC;YAED,IAAI,aAAa,KAAK,QAAQ,EAAE,CAAC;gBAChC,aAAa,GAAG,QAAQ,CAAC;gBACzB,YAAY,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,YAA0B,EAAE,QAAQ,EAAE,CAAC;QAChF,CAAC;KACD,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmachines/play-actor",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Abstract Actor base class for XMachines Play Architecture",
|
|
6
6
|
"keywords": [
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"build": "vite build && tsc --build",
|
|
41
41
|
"clean": "rm -rf dist *.tsbuildinfo coverage node_modules/.svelte2tsx-* node_modules/.vite*",
|
|
42
42
|
"test": "vitest",
|
|
43
|
+
"test:coverage": "vitest run --coverage",
|
|
43
44
|
"lint": "oxlint .",
|
|
44
45
|
"lint:fix": "oxlint --fix .",
|
|
45
46
|
"format": "oxfmt .",
|
|
@@ -57,8 +58,8 @@
|
|
|
57
58
|
},
|
|
58
59
|
"peerDependencies": {
|
|
59
60
|
"@xmachines/json-render-core": "^0.20.0-xm.2",
|
|
60
|
-
"@xmachines/play": "2.
|
|
61
|
-
"@xmachines/play-signals": "2.
|
|
61
|
+
"@xmachines/play": "2.1.0",
|
|
62
|
+
"@xmachines/play-signals": "2.1.0",
|
|
62
63
|
"xstate": "^5.31.0"
|
|
63
64
|
},
|
|
64
65
|
"engines": {
|