@yiin/reactive-proxy-state 1.0.44 → 2.0.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 +41 -0
- package/dist/index.cjs +3344 -1131
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3474 -1254
- package/dist/location.d.ts +288 -0
- package/dist/reactive.d.ts +5 -1
- package/dist/utils.d.ts +150 -9
- package/dist/wrap-array.d.ts +2 -2
- package/dist/wrap-map.d.ts +2 -2
- package/dist/wrap-set.d.ts +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import type { EmitFunction, Path, StateEvent } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Where each wrapped object sits in its state tree.
|
|
4
|
+
*
|
|
5
|
+
* Every raw object that has a proxy has a location node. A node records the
|
|
6
|
+
* places that hold it (a parent node and a key), so a path is read when an
|
|
7
|
+
* event is made, never fixed when the proxy is made. Structural changes move
|
|
8
|
+
* places: `relinkArray` gives array items their new index, `attachValue` and
|
|
9
|
+
* `detachPlace` follow assignments and removals. A node with no place under a
|
|
10
|
+
* root is detached and emits nothing.
|
|
11
|
+
*
|
|
12
|
+
* One object can sit at several places (`list[0] = list[1]`). The wire cannot
|
|
13
|
+
* carry shared identity, so the remote holds copies; a write through the
|
|
14
|
+
* shared object then emits one event per place. Places of such aliases come
|
|
15
|
+
* from the walk that stores a value (root creation, assignment, insertion,
|
|
16
|
+
* array reorders), so they do not depend on what was read before.
|
|
17
|
+
*
|
|
18
|
+
* A place names its parent weakly: a child never keeps a removed parent or
|
|
19
|
+
* an abandoned root alive.
|
|
20
|
+
*
|
|
21
|
+
* An object reachable from two roots emits to one of them (see `locate`).
|
|
22
|
+
*/
|
|
23
|
+
export declare const enum ContainerKind {
|
|
24
|
+
Plain = 0,
|
|
25
|
+
Map = 1,
|
|
26
|
+
Set = 2
|
|
27
|
+
}
|
|
28
|
+
export interface LocationRoot {
|
|
29
|
+
emit: EmitFunction | undefined;
|
|
30
|
+
path: Path;
|
|
31
|
+
/**
|
|
32
|
+
* The root emits on a later microtask (`{ async: true }`): its events
|
|
33
|
+
* wait, so they also copy what a write removes (see `copyPayload`).
|
|
34
|
+
*/
|
|
35
|
+
async: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Events made under this root and not delivered yet, oldest first, while
|
|
38
|
+
* a write that made several is delivering them (see `deliver`).
|
|
39
|
+
*/
|
|
40
|
+
undelivered: Undelivered | undefined;
|
|
41
|
+
}
|
|
42
|
+
/** A root's queue: `events[next]` is the oldest event not delivered yet. */
|
|
43
|
+
interface Undelivered {
|
|
44
|
+
events: StateEvent[];
|
|
45
|
+
next: number;
|
|
46
|
+
}
|
|
47
|
+
export declare class Place {
|
|
48
|
+
private readonly parentRef;
|
|
49
|
+
/** The container node's `id`: compares places without reading the WeakRef. */
|
|
50
|
+
readonly parentId: number;
|
|
51
|
+
/** Property name, array index (number), map key; unused for set members. */
|
|
52
|
+
key: unknown;
|
|
53
|
+
constructor(parent: LocationNode, key: unknown);
|
|
54
|
+
/** The container's node; undefined once the container was collected. */
|
|
55
|
+
get parent(): LocationNode | undefined;
|
|
56
|
+
}
|
|
57
|
+
export interface LocationNode {
|
|
58
|
+
/** Unique per node, never reused. */
|
|
59
|
+
id: number;
|
|
60
|
+
raw: object;
|
|
61
|
+
kind: ContainerKind;
|
|
62
|
+
places: Place[];
|
|
63
|
+
root: LocationRoot | undefined;
|
|
64
|
+
/** The root this object was first read under; it wins when two roots hold the object. */
|
|
65
|
+
scope: LocationRoot | undefined;
|
|
66
|
+
/** The object's live proxy (its `globalSeen` entry), read without a second map lookup. */
|
|
67
|
+
proxy: object | undefined;
|
|
68
|
+
/** The proxy this object had before it was evicted, to reuse it if the object comes back. */
|
|
69
|
+
evicted: WeakRef<object> | undefined;
|
|
70
|
+
/** The last `relinkArray` call that placed this object (tells repeats apart). */
|
|
71
|
+
relinked: number;
|
|
72
|
+
/** In that call: how many of its old places in the array it has not met again yet. */
|
|
73
|
+
relinkedPlaces: number;
|
|
74
|
+
/**
|
|
75
|
+
* A child's place under this object, or under an object below it, was
|
|
76
|
+
* dropped while this object was detached. Storing it again walks its
|
|
77
|
+
* children to give those places back.
|
|
78
|
+
*/
|
|
79
|
+
lostLink: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* The object had no own accessor property when its proxy first wrote to
|
|
82
|
+
* it (see `writesThroughSetter`); undefined before that write.
|
|
83
|
+
*/
|
|
84
|
+
dataOnly: boolean | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* How many places name this node as their container: every `Place` made
|
|
87
|
+
* with it counts, and each place dropped from its object's `places` stops
|
|
88
|
+
* counting. A place whose object was collected still counts, so the
|
|
89
|
+
* number is never below the places there are (see `relink`).
|
|
90
|
+
*/
|
|
91
|
+
childPlaces: number;
|
|
92
|
+
/** The last store walk that met this object (see `enterAdopt`). */
|
|
93
|
+
walk: number;
|
|
94
|
+
/** The last store that put this node on its list of nodes to prune (see `touch`). */
|
|
95
|
+
touched: number;
|
|
96
|
+
/** How many places the node kept at its last full `prunePlaces`. */
|
|
97
|
+
pruned: number;
|
|
98
|
+
/** The places of a node with more than `WIDE` of them, by container and key (see `findPlace`). */
|
|
99
|
+
index: PlaceIndex | undefined;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The places of one node by container id, then by key when one container
|
|
103
|
+
* holds the object at several keys. It belongs to `places` while that array
|
|
104
|
+
* keeps `length` items; a change of an item in place (a splice, a new key)
|
|
105
|
+
* drops it. A push through `pushPlace` keeps it.
|
|
106
|
+
*/
|
|
107
|
+
interface PlaceIndex {
|
|
108
|
+
places: Place[];
|
|
109
|
+
length: number;
|
|
110
|
+
byParent: Map<number, Place | Map<unknown, Place>>;
|
|
111
|
+
}
|
|
112
|
+
export declare function getLocationNode(raw: object): LocationNode | undefined;
|
|
113
|
+
export declare function ensureLocationNode(raw: object): LocationNode;
|
|
114
|
+
/**
|
|
115
|
+
* Does a write to `prop` of `target` (raw; its node is `node`) call an own
|
|
116
|
+
* setter? Read from the property's descriptor, unless the object had no own
|
|
117
|
+
* accessor when its proxy first wrote to it: a write through a proxy adds
|
|
118
|
+
* only data properties, so then there is none to find, and no descriptor
|
|
119
|
+
* is made per write. An accessor added later (`Object.defineProperty`) is
|
|
120
|
+
* outside the supported input. An object with more than 64 own keys is not
|
|
121
|
+
* scanned and reads the descriptor at every write.
|
|
122
|
+
*/
|
|
123
|
+
export declare function writesThroughSetter(target: object, prop: PropertyKey, node: LocationNode): boolean;
|
|
124
|
+
/** Where an event goes: one root and every path of the object under it. */
|
|
125
|
+
export interface Target {
|
|
126
|
+
root: LocationRoot;
|
|
127
|
+
paths: Path[];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Where an event about `node` (plus `tail`) goes: every current place of the
|
|
131
|
+
* object, under one root. Undefined when the object is detached or that root
|
|
132
|
+
* has no emit function.
|
|
133
|
+
*
|
|
134
|
+
* An object under two roots (a replica built on raw objects it shares with
|
|
135
|
+
* its source) emits only to its scope, the root it was first read under, so
|
|
136
|
+
* applying an event to the replica cannot echo back to the source.
|
|
137
|
+
*
|
|
138
|
+
* A write that finds no root is counted in `proxyStats.detachedWrites`.
|
|
139
|
+
*/
|
|
140
|
+
export declare function locate(node: LocationNode, tail?: PropertyKey): Target | undefined;
|
|
141
|
+
/** Is the object somewhere under a root (with or without an emit function)? */
|
|
142
|
+
export declare function isAttached(node: LocationNode): boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Send `event` to every path of `target`. Its payload holds copies already
|
|
145
|
+
* (`copyPayload` or `copyPayloadAfter`, made before the write). Every
|
|
146
|
+
* further path gets copies of the stored values (`newValue`, `value`,
|
|
147
|
+
* `items`), all made before the first emit, so a listener that changes one
|
|
148
|
+
* cannot change another, and two remote places never share one object.
|
|
149
|
+
* The first path gets `event` itself. What the write removed is copied per
|
|
150
|
+
* path only where `copyPayload` copied it (an async root); otherwise every
|
|
151
|
+
* path carries the removed value itself, shared by the events.
|
|
152
|
+
*/
|
|
153
|
+
export declare function dispatch(target: Target, event: StateEvent): void;
|
|
154
|
+
/**
|
|
155
|
+
* Deliver the `events` of one write to `root.emit`, in order, after the
|
|
156
|
+
* events earlier writes left undelivered under this root.
|
|
157
|
+
*
|
|
158
|
+
* A listener can write while it receives an event. That write changed the
|
|
159
|
+
* state after the events still waiting (the other places of an alias), so
|
|
160
|
+
* its own events go after them: it adds them to the root's queue, then
|
|
161
|
+
* delivers the queue from the oldest event, before it returns. So events
|
|
162
|
+
* reach `emit` in the order the state changed, every write is delivered
|
|
163
|
+
* before it returns, and a write made while nothing waits is delivered at
|
|
164
|
+
* once, inside the listener call that made it.
|
|
165
|
+
*
|
|
166
|
+
* An `emit` that throws does not stop the others: every event in the queue
|
|
167
|
+
* is delivered once, each for a write that already changed the state, then
|
|
168
|
+
* the first error reaches the write that was delivering them. A listener
|
|
169
|
+
* that called that write may catch it and go on.
|
|
170
|
+
*/
|
|
171
|
+
export declare function deliver(root: LocationRoot, events: StateEvent[]): void;
|
|
172
|
+
/** What `copyPayload` did. */
|
|
173
|
+
export declare const enum Copied {
|
|
174
|
+
/** Nothing: the payload reaches its container (see `copyPayloadReaching`). */
|
|
175
|
+
Reaches = 0,
|
|
176
|
+
/** Copied the payload. */
|
|
177
|
+
Done = 1,
|
|
178
|
+
/**
|
|
179
|
+
* Copied the payload, and the values it stores (`newValue`, `value`,
|
|
180
|
+
* `items`) are fresh (see `cloneStored`): the place walk of this store
|
|
181
|
+
* would find nothing in them, so `attachValue` and `relinkArray` skip it.
|
|
182
|
+
* The finding holds for this store only; a later store of the same
|
|
183
|
+
* values walks them again.
|
|
184
|
+
*/
|
|
185
|
+
Fresh = 2
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Replace the payload fields of `event` (live values) with deep copies, made
|
|
189
|
+
* before the write that changes `container` (raw). `items` and `oldValues`
|
|
190
|
+
* are arrays the wrapper made for this event and only reads; each is one
|
|
191
|
+
* payload, copied whole, with one copy limit, and kept as it is when it
|
|
192
|
+
* holds no object. A payload too large to copy throws a `SnapshotLimitError`
|
|
193
|
+
* and leaves `event` as it was, so the write is never made.
|
|
194
|
+
*
|
|
195
|
+
* What the write stores (`newValue`, `value`, `items`) is always copied: it
|
|
196
|
+
* stays in the tree, where later writes change it, and a replica needs it
|
|
197
|
+
* as it was. What the write removes (`oldValue`, `oldValues`, and the
|
|
198
|
+
* `value` of a `set-delete`) is copied only for an async root
|
|
199
|
+
* (`target.root.async`), whose events wait for a microtask. A synchronous
|
|
200
|
+
* root delivers the event before the write returns, and sends the removed
|
|
201
|
+
* value itself, as 1.0.44 did, so it never refuses a removal. Assignment
|
|
202
|
+
* `newValue` copies keep array items only. Reorders keep properties on
|
|
203
|
+
* nested arrays; the other fields keep every array's properties (see `Named`).
|
|
204
|
+
*
|
|
205
|
+
* A payload that reaches `container` would be copied as `container` is
|
|
206
|
+
* before the write. Then nothing is copied and the result is
|
|
207
|
+
* `Copied.Reaches`: the caller makes the write on `shallowCopy(container)`
|
|
208
|
+
* and copies with `copyPayloadReaching`, still before the write.
|
|
209
|
+
*
|
|
210
|
+
* `held` comes from `heldItems` for the store of `newValue`: the place walk
|
|
211
|
+
* of that store skips those items, so the copy does not check freshness.
|
|
212
|
+
*/
|
|
213
|
+
export declare function copyPayload(event: StateEvent | undefined, target: Target | undefined, container: object, held?: Set<object>): Copied;
|
|
214
|
+
/**
|
|
215
|
+
* `copyPayloadAfter` for a write that `copyPayload` refused because its
|
|
216
|
+
* payload reaches `container`. A getter in that payload would be read
|
|
217
|
+
* before the write, and could give another value after it, so an accessor
|
|
218
|
+
* property in it is refused (an `UnsupportedStateError`) without being
|
|
219
|
+
* read. `after` comes from `shallowCopy`, which refuses the container's own.
|
|
220
|
+
*/
|
|
221
|
+
export declare function copyPayloadReaching(event: StateEvent, target: Target, container: object, after: object): void;
|
|
222
|
+
/**
|
|
223
|
+
* Like `copyPayload`, for a payload that reaches `container`: `after` (a
|
|
224
|
+
* `shallowCopy` of `container` with the write made on it) stands in for
|
|
225
|
+
* `container`, so the payload is copied as it will be after the write,
|
|
226
|
+
* before the write. Throws a `SnapshotLimitError` when it is too large to
|
|
227
|
+
* copy; the write is then never made, and nothing needs to be put back.
|
|
228
|
+
*/
|
|
229
|
+
export declare function copyPayloadAfter(event: StateEvent, target: Target, container: object, after: object): void;
|
|
230
|
+
/**
|
|
231
|
+
* A copy of `container` (raw) that holds the same entries, of the same kind
|
|
232
|
+
* and prototype: an array holds the same items, a map the same entries, a
|
|
233
|
+
* set the same members, an object the same own enumerable properties (as
|
|
234
|
+
* data). A write is made on it to copy a payload as it will be after that
|
|
235
|
+
* write (see `copyPayloadReaching`). An own enumerable accessor of an object
|
|
236
|
+
* is refused (an `UnsupportedStateError`) without being read.
|
|
237
|
+
*/
|
|
238
|
+
export declare function shallowCopy(container: object): any;
|
|
239
|
+
/**
|
|
240
|
+
* Record that a proxy read found `raw` at `parent[key]`. Called on every read
|
|
241
|
+
* of a nested object, so the common case (place already known) is one
|
|
242
|
+
* compare, and a wide node finds the place in its index.
|
|
243
|
+
*/
|
|
244
|
+
export declare function notePlace(node: LocationNode, parent: LocationNode, key: unknown): void;
|
|
245
|
+
/** `parent[key]` no longer holds `value`. */
|
|
246
|
+
export declare function detachPlace(value: object, parent: LocationNode, key: unknown): void;
|
|
247
|
+
/**
|
|
248
|
+
* `heldBefore` for a store of `value` over `replaced`, the value it writes
|
|
249
|
+
* over when its container was in the tree (see `attachedBefore`); undefined
|
|
250
|
+
* when `replaced` has no node. Made before the write, for `copyPayload` and
|
|
251
|
+
* `attachValue`.
|
|
252
|
+
*/
|
|
253
|
+
export declare function heldItems(value: unknown, replaced: unknown): Set<object> | undefined;
|
|
254
|
+
/**
|
|
255
|
+
* `parent[key]` now holds `value` (a raw object). A `fresh` value (the copy
|
|
256
|
+
* this store made found it fresh, see `cloneStored`) has nothing to place.
|
|
257
|
+
* `replaced` is the value the store wrote over, when `parent` was in the
|
|
258
|
+
* tree before the store (see `attachedBefore`), and `held` is
|
|
259
|
+
* `heldItems(value, replaced)`.
|
|
260
|
+
*/
|
|
261
|
+
export declare function attachValue(value: object, parent: LocationNode, key: unknown, fresh: boolean, replaced?: unknown, held?: Set<object>): void;
|
|
262
|
+
/**
|
|
263
|
+
* A new root: give places to the objects in its initial value that need
|
|
264
|
+
* them now, which are the aliases (an object at two places) and the
|
|
265
|
+
* containers above them. Other objects get their place when they are read.
|
|
266
|
+
*/
|
|
267
|
+
export declare function adoptRoot(node: LocationNode): void;
|
|
268
|
+
/**
|
|
269
|
+
* After a structural change of `array` (its node `arrayNode`): items from
|
|
270
|
+
* index `from` to the end get their current index, `removed` items lose
|
|
271
|
+
* their place here, and `inserted` items (raw) join the tree.
|
|
272
|
+
*/
|
|
273
|
+
export declare function relinkArray(arrayNode: LocationNode, array: readonly unknown[], from: number, removed?: readonly unknown[], inserted?: readonly unknown[], insertedFresh?: boolean): void;
|
|
274
|
+
/**
|
|
275
|
+
* After `sort`, `reverse`, `fill` or `copyWithin`: like `relinkArray` from
|
|
276
|
+
* index 0, and an object without a node that now sits at two indexes (an
|
|
277
|
+
* alias the change made) gets a node with both places.
|
|
278
|
+
*/
|
|
279
|
+
export declare function relinkReorder(arrayNode: LocationNode, array: readonly unknown[], removed: readonly unknown[], inserted?: readonly unknown[]): void;
|
|
280
|
+
/**
|
|
281
|
+
* Drop the proxy cache entries of an object that left the tree, and of its
|
|
282
|
+
* children that left with it, so GC can collect them. An object that is
|
|
283
|
+
* still placed under a root (it moved) keeps its proxy.
|
|
284
|
+
*/
|
|
285
|
+
export declare function evictDeep(value: any, parent?: LocationNode): void;
|
|
286
|
+
/** The proxy an evicted object had, if it is still alive; it goes back in the caches. */
|
|
287
|
+
export declare function restoreEvicted(node: LocationNode): object | undefined;
|
|
288
|
+
export {};
|
package/dist/reactive.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ import { EmitFunction, Path, ReactiveOptions } from "./types";
|
|
|
4
4
|
*/
|
|
5
5
|
export declare function isReactive(value: any): boolean;
|
|
6
6
|
/**
|
|
7
|
-
* Create a reactive proxy for an object
|
|
7
|
+
* Create a reactive proxy for an object.
|
|
8
|
+
*
|
|
9
|
+
* Called by users, this makes a root: events from anywhere below it go to
|
|
10
|
+
* `emit`, with paths that start with `path`. Nested objects are wrapped on
|
|
11
|
+
* read by `wrapChild`.
|
|
8
12
|
*/
|
|
9
13
|
export declare function reactive<T extends object>(obj: T, emit?: EmitFunction, path?: Path, options?: ReactiveOptions): T;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { StateEvent } from "./types";
|
|
1
2
|
/**
|
|
2
3
|
* Returns the raw, original object underlying a reactive proxy.
|
|
3
4
|
* If the input is not a proxy, returns the input itself.
|
|
@@ -6,10 +7,12 @@ export declare function toRaw<T>(observed: T): T;
|
|
|
6
7
|
/**
|
|
7
8
|
* Strip proxy refs from spread results before storing in raw state.
|
|
8
9
|
* Prevents unbounded proxy nesting from `{ ...reactiveProxy }` patterns.
|
|
10
|
+
* The value and its direct children only: the place walk of the store puts
|
|
11
|
+
* the raw object in place of a proxy deeper down (see `storeRaw` in
|
|
12
|
+
* location.ts), and a fresh value (see `cloneStored`) holds no proxy.
|
|
9
13
|
*/
|
|
10
14
|
export declare function unwrapForStore(value: any): any;
|
|
11
15
|
export declare const pathCache: WeakMap<object, Map<string, any>>;
|
|
12
|
-
export declare const pathConcatCache: Map<string, any[]>;
|
|
13
16
|
export declare const globalSeen: WeakMap<any, any>;
|
|
14
17
|
export declare const wrapperCache: WeakMap<object, object>;
|
|
15
18
|
export declare const proxyStats: {
|
|
@@ -20,6 +23,11 @@ export declare const proxyStats: {
|
|
|
20
23
|
objects: number;
|
|
21
24
|
/** Number of old proxied values evicted when replaced via set trap */
|
|
22
25
|
staleEvicted: number;
|
|
26
|
+
/**
|
|
27
|
+
* Writes through a proxy whose object is in no tree (it was removed, or
|
|
28
|
+
* never placed). They change the object and emit nothing.
|
|
29
|
+
*/
|
|
30
|
+
detachedWrites: number;
|
|
23
31
|
};
|
|
24
32
|
export declare function getProxyStats(): {
|
|
25
33
|
pathConcatCacheSize: number;
|
|
@@ -30,14 +38,13 @@ export declare function getProxyStats(): {
|
|
|
30
38
|
objects: number;
|
|
31
39
|
/** Number of old proxied values evicted when replaced via set trap */
|
|
32
40
|
staleEvicted: number;
|
|
41
|
+
/**
|
|
42
|
+
* Writes through a proxy whose object is in no tree (it was removed, or
|
|
43
|
+
* never placed). They change the object and emit nothing.
|
|
44
|
+
*/
|
|
45
|
+
detachedWrites: number;
|
|
33
46
|
};
|
|
34
47
|
export declare function resetProxyStats(): void;
|
|
35
|
-
/**
|
|
36
|
-
* Recursively evict an object and all its nested children from proxy caches.
|
|
37
|
-
* This allows GC to collect the entire old object tree when a property is
|
|
38
|
-
* replaced, not just the top-level value.
|
|
39
|
-
*/
|
|
40
|
-
export declare function evictDeep(value: any): void;
|
|
41
48
|
export declare function deepEqual(a: any, b: any, seen?: WeakMap<any, any>): boolean;
|
|
42
49
|
export declare function getFromPathCache(root: object, pathKey: string): any | undefined;
|
|
43
50
|
export declare function setInPathCache(root: object, pathKey: string, value: any): void;
|
|
@@ -47,14 +54,148 @@ export declare function setInPathCache(root: object, pathKey: string, value: any
|
|
|
47
54
|
* (and any deeper ones) are not reused on subsequent mutations.
|
|
48
55
|
*/
|
|
49
56
|
export declare function evictDescendantsFromPathCache(root: object, pathKey: string): void;
|
|
50
|
-
export declare function getPathConcat(path: string): any[] | undefined;
|
|
51
|
-
export declare function setPathConcat(path: string, value: any[]): void;
|
|
52
57
|
/**
|
|
53
58
|
* recursively traverses an object or array, accessing each property/element.
|
|
54
59
|
* used by `watch` with `deep: true` to establish dependencies on all nested properties.
|
|
55
60
|
* the actual tracking is done by the proxy `get` handlers triggered during traversal.
|
|
56
61
|
*/
|
|
57
62
|
export declare function traverse(value: any, seen?: Set<any>): any;
|
|
63
|
+
/**
|
|
64
|
+
* The most copies one snapshot may make beyond the first copy of each
|
|
65
|
+
* object. A snapshot copies a shared object once per place, so a graph
|
|
66
|
+
* that shares objects at many places (each level holding the one below
|
|
67
|
+
* twice) grows exponentially: 22 objects become 4,194,303 copies. Such a
|
|
68
|
+
* snapshot throws a `RangeError` instead. A tree, however large, makes no
|
|
69
|
+
* extra copies and is never refused.
|
|
70
|
+
*/
|
|
71
|
+
export declare const SNAPSHOT_SHARED_COPY_LIMIT = 100000;
|
|
72
|
+
/** A snapshot over `SNAPSHOT_SHARED_COPY_LIMIT`. */
|
|
73
|
+
export declare class SnapshotLimitError extends RangeError {
|
|
74
|
+
constructor(extraCopies: number);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A write the library cannot synchronize, refused before anything changed.
|
|
78
|
+
* See "Supported inputs" under "Synchronization Limits" in the README.
|
|
79
|
+
*/
|
|
80
|
+
export declare class UnsupportedStateError extends TypeError {
|
|
81
|
+
constructor(problem: string);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Which arrays of a payload copy keep their named (non-index) properties.
|
|
85
|
+
* Finding them costs a key list per array, so only the payloads 1.0.44 sent
|
|
86
|
+
* as the value itself keep them: the initial replace, inserted values and
|
|
87
|
+
* what a write removes. Reorders also keep properties below the reordered
|
|
88
|
+
* array. Assignment `newValue` copies keep array items only, as in 1.0.44.
|
|
89
|
+
*/
|
|
90
|
+
export declare const enum Named {
|
|
91
|
+
/** No array: its items only. */
|
|
92
|
+
None = 0,
|
|
93
|
+
/** Arrays below `items`, `oldValues`, or the reordered array. */
|
|
94
|
+
Below = 1,
|
|
95
|
+
/** Every array. */
|
|
96
|
+
All = 2
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Deep clone for event payloads. Unlike `deepClone`, an object that appears
|
|
100
|
+
* at several places in `value` is copied once per place, so the result is a
|
|
101
|
+
* tree: a replica holds one copy per place, and a write through a shared
|
|
102
|
+
* object emits one event per place. Copies may not share objects, because a
|
|
103
|
+
* wire that keeps identity (structuredClone, an in-process listener) would
|
|
104
|
+
* then hold one object where the source has several places, and apply each
|
|
105
|
+
* per-place event to it again. Cycles are kept. Every own enumerable data
|
|
106
|
+
* property is copied as an own data property (also `__proto__`), and an
|
|
107
|
+
* array's holes stay holes; `named` says which arrays keep their named
|
|
108
|
+
* properties. Levels deeper than `FILL_DEPTH` take no stack frame, so any
|
|
109
|
+
* depth fits.
|
|
110
|
+
*
|
|
111
|
+
* Throws a `SnapshotLimitError` (a `RangeError`) when the copy would make more than
|
|
112
|
+
* `SNAPSHOT_SHARED_COPY_LIMIT` extra copies of shared objects.
|
|
113
|
+
*/
|
|
114
|
+
export declare function cloneTree<T>(value: T, named: Named): T;
|
|
115
|
+
/** What `cloneTreeUnless` returns for a value that reaches the object it names. */
|
|
116
|
+
export declare const REACHES: unique symbol;
|
|
117
|
+
/**
|
|
118
|
+
* `cloneTree(value, named)`, or `REACHES` as soon as the copy (or its
|
|
119
|
+
* measure) meets `container`. A `SnapshotLimitError` thrown first is
|
|
120
|
+
* measured on objects other than `container`.
|
|
121
|
+
*/
|
|
122
|
+
export declare function cloneTreeUnless<T>(value: T, container: object, named: Named): T | typeof REACHES;
|
|
123
|
+
/**
|
|
124
|
+
* `cloneTreeUnless(value, container, named)` for a value about to be stored
|
|
125
|
+
* (the new value of a write, inserted items, a new root; `container` may be
|
|
126
|
+
* undefined). It also finds whether the value is fresh: no object in it has
|
|
127
|
+
* a location node, and no object sits at two places in it (an alias or a
|
|
128
|
+
* cycle). `copiedFresh` says so when the call returns. The place walk of a
|
|
129
|
+
* store finds nothing to do in a fresh value, so the store skips it (see
|
|
130
|
+
* `attachValue`). The check stops at the first object that is not fresh.
|
|
131
|
+
*/
|
|
132
|
+
export declare function cloneStored<T>(value: T, container: object | undefined, named: Named): T | typeof REACHES;
|
|
133
|
+
/** Whether the value the last `cloneStored` call copied is fresh; set when it returns. */
|
|
134
|
+
export declare let copiedFresh: boolean;
|
|
135
|
+
/**
|
|
136
|
+
* The copy `cloneTree(value, named)` makes once `container` holds what
|
|
137
|
+
* `contents` holds: wherever the copy (and its measure) meets `container`,
|
|
138
|
+
* it reads `contents` instead, a shallow copy of `container` of the same
|
|
139
|
+
* kind. So a payload is copied, or refused, as it will be after a write to
|
|
140
|
+
* `container`, before that write is made.
|
|
141
|
+
*/
|
|
142
|
+
export declare function cloneTreeAfter<T>(value: T, container: object, contents: object, named: Named): T;
|
|
143
|
+
/**
|
|
144
|
+
* The enumerable string and symbol keys of `array` other than indexes.
|
|
145
|
+
* Indexes come first among string keys. Undefined when no keys remain.
|
|
146
|
+
*/
|
|
147
|
+
export declare function namedKeys(array: object): (string | symbol)[] | undefined;
|
|
148
|
+
/** `object[key] = value` as an own enumerable data property: no setter runs, and `__proto__` stays a key. */
|
|
149
|
+
export declare function setData(object: object, key: PropertyKey, value: unknown): void;
|
|
150
|
+
/**
|
|
151
|
+
* Name `member`, a member of `collection` (raw), in a payload whose copy of
|
|
152
|
+
* it is `copy`, or `member` itself when the event sends the object.
|
|
153
|
+
* `entering`: the write puts `member` into `collection`. Returns what the
|
|
154
|
+
* payload carries: `copy`, or a copy that carries the token `member` has in
|
|
155
|
+
* `collection` when that is not its own token (see `overrides`). Inside a
|
|
156
|
+
* copy of a payload (see `copyingPayload`), `member` is itself a copy, and
|
|
157
|
+
* `copy` names the same member.
|
|
158
|
+
*/
|
|
159
|
+
export declare function nameMember(member: unknown, copy: unknown, collection: object, entering: boolean): unknown;
|
|
160
|
+
/**
|
|
161
|
+
* Name `key`, a key of `collection` (raw), in the map event `event`, which
|
|
162
|
+
* carries the key itself, or a copy when its token there is not its own
|
|
163
|
+
* (see `nameMember`). `entering`: the write adds `key`.
|
|
164
|
+
*/
|
|
165
|
+
export declare function nameKey(event: StateEvent, key: object, collection: object, entering: boolean): void;
|
|
166
|
+
/** `copy` is a copy of the payload copy `source`: it names the same member. */
|
|
167
|
+
export declare function nameCopyOfCopy(source: unknown, copy: unknown): void;
|
|
168
|
+
/** Copy payloads of payloads with `run` (see `copyingPayload`). */
|
|
169
|
+
export declare function copyingPayloads<T>(run: () => T): T;
|
|
170
|
+
/** What the proxy of a Set or Map reads to know whether its collection has an index (see `watchIndex`). */
|
|
171
|
+
export interface IndexWatch {
|
|
172
|
+
indexed: boolean;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The `IndexWatch` for a new proxy of `collection` (raw): `indexed` turns
|
|
176
|
+
* true when the collection gets an index, also one `updateState` made
|
|
177
|
+
* before the proxy, and the proxy then keeps that index as it changes the
|
|
178
|
+
* collection (see `indexAdded`).
|
|
179
|
+
*/
|
|
180
|
+
export declare function watchIndex(collection: object): IndexWatch;
|
|
181
|
+
/**
|
|
182
|
+
* The proxy of `collection` (raw), which has an index (see
|
|
183
|
+
* `watchIndex`), added `member` (a Set member or Map key): the
|
|
184
|
+
* index takes it, so a later event finds it without a rebuild.
|
|
185
|
+
*/
|
|
186
|
+
export declare function indexAdded(collection: Set<unknown> | Map<unknown, unknown>, member: unknown): void;
|
|
187
|
+
/** The proxy of `collection` (raw), which has an index, removed `member`: the index lets it go. */
|
|
188
|
+
export declare function indexRemoved(collection: Set<unknown> | Map<unknown, unknown>, member: unknown): void;
|
|
189
|
+
/** `set-add` on a replica set (raw or a proxy). */
|
|
190
|
+
export declare function replicaAdd(set: Set<unknown>, value: unknown): void;
|
|
191
|
+
/** `set-delete` on a replica set (raw or a proxy). */
|
|
192
|
+
export declare function replicaDelete(set: Set<unknown>, value: unknown): void;
|
|
193
|
+
/** `map-set` on a replica map (raw or a proxy). */
|
|
194
|
+
export declare function replicaMapSet(map: Map<unknown, unknown>, key: unknown, value: unknown): void;
|
|
195
|
+
/** `map-delete` on a replica map (raw or a proxy). */
|
|
196
|
+
export declare function replicaMapDelete(map: Map<unknown, unknown>, key: unknown): void;
|
|
197
|
+
/** A replica collection was cleared or refilled: its index is made again when needed. */
|
|
198
|
+
export declare function forgetReplicaIndex(collection: object): void;
|
|
58
199
|
/**
|
|
59
200
|
* creates a deep clone of a value.
|
|
60
201
|
* includes cycle detection using a weakmap.
|
package/dist/wrap-array.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function wrapArray<T extends any[]>(arr: T,
|
|
1
|
+
import { LocationNode } from "./location";
|
|
2
|
+
export declare function wrapArray<T extends any[]>(arr: T, node: LocationNode): T;
|
package/dist/wrap-map.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function wrapMap<K, V>(map: Map<K, V>,
|
|
1
|
+
import { LocationNode } from "./location";
|
|
2
|
+
export declare function wrapMap<K, V>(map: Map<K, V>, node: LocationNode): Map<K, V>;
|
package/dist/wrap-set.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function wrapSet<T>(set: Set<T>,
|
|
1
|
+
import { LocationNode } from "./location";
|
|
2
|
+
export declare function wrapSet<T>(set: Set<T>, node: LocationNode): Set<T>;
|