@solidjs/signals 2.0.0-rc.4 → 2.0.0-rc.6
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/dist/dev.js +1618 -232
- package/dist/node.cjs +2262 -1199
- package/dist/prod/boundaries.js +4 -1
- package/dist/prod/core/async.js +152 -101
- package/dist/prod/core/constants.js +55 -1
- package/dist/prod/core/core.js +305 -234
- package/dist/prod/core/effect.js +28 -28
- package/dist/prod/core/error.js +13 -1
- package/dist/prod/core/external.js +2 -2
- package/dist/prod/core/graph.js +27 -27
- package/dist/prod/core/heap.js +30 -30
- package/dist/prod/core/lanes.js +32 -32
- package/dist/prod/core/optimistic.js +57 -57
- package/dist/prod/core/owner.js +34 -34
- package/dist/prod/core/scheduler.js +346 -152
- package/dist/prod/core/verdict.js +122 -65
- package/dist/prod/index.js +3 -3
- package/dist/prod/map.js +106 -106
- package/dist/prod/signals.js +321 -26
- package/dist/prod/store/next/optimistic.js +363 -151
- package/dist/prod/store/next/patch.js +6 -6
- package/dist/prod/store/next/projection.js +25 -21
- package/dist/prod/store/next/store.js +223 -113
- package/dist/prod/store/store.js +2 -2
- package/dist/types/core/async.d.ts +2 -0
- package/dist/types/core/attribution-hooks.d.ts +11 -0
- package/dist/types/core/attribution.d.ts +57 -4
- package/dist/types/core/constants.d.ts +54 -0
- package/dist/types/core/core.d.ts +19 -20
- package/dist/types/core/dev.d.ts +8 -2
- package/dist/types/core/error.d.ts +9 -0
- package/dist/types/core/index.d.ts +2 -2
- package/dist/types/core/scheduler.d.ts +39 -0
- package/dist/types/core/types.d.ts +12 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/signals.d.ts +108 -11
- package/dist/types/store/next/optimistic.d.ts +13 -10
- package/dist/types/store/next/projection.d.ts +1 -1
- package/dist/types/store/next/store.d.ts +22 -0
- package/dist/types/store/next/target.d.ts +25 -0
- package/dist/types-cjs/core/async.d.cts +2 -0
- package/dist/types-cjs/core/attribution-hooks.d.cts +11 -0
- package/dist/types-cjs/core/attribution.d.cts +57 -4
- package/dist/types-cjs/core/constants.d.cts +54 -0
- package/dist/types-cjs/core/core.d.cts +19 -20
- package/dist/types-cjs/core/dev.d.cts +8 -2
- package/dist/types-cjs/core/error.d.cts +9 -0
- package/dist/types-cjs/core/index.d.cts +2 -2
- package/dist/types-cjs/core/scheduler.d.cts +39 -0
- package/dist/types-cjs/core/types.d.cts +12 -0
- package/dist/types-cjs/index.d.cts +3 -3
- package/dist/types-cjs/signals.d.cts +108 -11
- package/dist/types-cjs/store/next/optimistic.d.cts +13 -10
- package/dist/types-cjs/store/next/projection.d.cts +1 -1
- package/dist/types-cjs/store/next/store.d.cts +22 -0
- package/dist/types-cjs/store/next/target.d.cts +25 -0
- package/package.json +1 -1
package/dist/prod/store/store.js
CHANGED
|
@@ -252,7 +252,7 @@ s) {
|
|
|
252
252
|
// Callers guard on `pendingCheckActive`, which only flips inside
|
|
253
253
|
// isPending() — the verdict layer is loaded and its hook installed.
|
|
254
254
|
const o = e[STORE_NODE]?.[$AFFECTS];
|
|
255
|
-
if (o?.o?.t) GlobalQueue.
|
|
255
|
+
if (o?.o?.t) GlobalQueue.Wt(o);
|
|
256
256
|
if (affectsScopes.size) {
|
|
257
257
|
// Chained backings (§7b): a wrapper's STORE_VALUE can be another store's
|
|
258
258
|
// proxy — marks cover by identity of the BASE raw, so resolve the chain
|
|
@@ -263,7 +263,7 @@ s) {
|
|
|
263
263
|
let t = r;
|
|
264
264
|
for (;;) {
|
|
265
265
|
if (s.scope.has(t)) {
|
|
266
|
-
GlobalQueue.
|
|
266
|
+
GlobalQueue.Wt(e);
|
|
267
267
|
break;
|
|
268
268
|
}
|
|
269
269
|
const o = t?.[$TARGET];
|
|
@@ -16,6 +16,8 @@ export declare function releaseSettledDependents(el: Computed<any>): void;
|
|
|
16
16
|
export declare function settleErroredDependents(el: Computed<any>, error: any): void;
|
|
17
17
|
export declare function settlePendingSource(el: Computed<any>): void;
|
|
18
18
|
export declare function isThenable<T>(value: T | PromiseLike<T>): value is PromiseLike<T>;
|
|
19
|
+
/** Fire and clear a node's iterator-flight cancellation hook (#3122). */
|
|
20
|
+
export declare function releaseFlightTeardown(el: Computed<any>): void;
|
|
19
21
|
export declare function handleAsync<T>(el: Computed<T>, result: T | PromiseLike<T> | AsyncIterable<T>, setter?: (value: T) => void): T;
|
|
20
22
|
export declare function clearStatus(el: Computed<any>, clearUninitialized?: boolean): void;
|
|
21
23
|
export declare function notifyStatus(el: Computed<any>, status: number, error: any, blockStatus?: boolean, lane?: OptimisticLane): void;
|
|
@@ -36,6 +36,17 @@ export interface AttributionHooks {
|
|
|
36
36
|
write(el: Signal<any> | Computed<any>, prev: unknown, value: unknown): void;
|
|
37
37
|
/** refresh() invalidated this node (self-invalidation, no dep changed). */
|
|
38
38
|
refreshed(el: Computed<any>): void;
|
|
39
|
+
/**
|
|
40
|
+
* A new async flight entered the system (`_inFlight` was just assigned
|
|
41
|
+
* during a recompute of `el`). Always fired inside the owning recompute —
|
|
42
|
+
* both call paths (core's recompute and the projection self-registration)
|
|
43
|
+
* run within one — so the engine can read the current frame stack to link
|
|
44
|
+
* the flight to the change that caused it (waterfall chaining). `flight`
|
|
45
|
+
* is the registered thenable/iterable itself: the engine keys a first-seen
|
|
46
|
+
* origin registry on its identity, so shared and preloader-marked promises
|
|
47
|
+
* carry their true start time instead of the moment the graph saw them.
|
|
48
|
+
*/
|
|
49
|
+
flightStart(el: Computed<any>, flight: object): void;
|
|
39
50
|
/** An async landing is about to apply its value (before any branch). */
|
|
40
51
|
asyncStart(el: Computed<any>): void;
|
|
41
52
|
/**
|
|
@@ -60,11 +60,16 @@ export interface RerunEvent {
|
|
|
60
60
|
/** Wall time of this run including nested recomputes (ms). */
|
|
61
61
|
totalMs: number;
|
|
62
62
|
/**
|
|
63
|
-
* Whether the run
|
|
63
|
+
* Whether the run produced a changed value. A PLAIN memo run with
|
|
64
64
|
* `changed: false` was pure waste — the equality cutoff stopped it from
|
|
65
|
-
* notifying anyone
|
|
66
|
-
*
|
|
67
|
-
*
|
|
65
|
+
* notifying anyone. Effects run with `_equals: false` in core (their
|
|
66
|
+
* effect phase re-fires on every recompute), so the engine derives this
|
|
67
|
+
* fact itself: an effect run whose compute output is identical to the
|
|
68
|
+
* previous run's reports `changed: false` — the phase re-fired with the
|
|
69
|
+
* same input, pure waste. Side-effect-only computes (`undefined` output)
|
|
70
|
+
* are exempt: identity of `undefined` proves nothing about their work.
|
|
71
|
+
* Summed as `wastedMs` in costs() (plain, non-held runs only — see
|
|
72
|
+
* `phase`).
|
|
68
73
|
*/
|
|
69
74
|
changed: boolean;
|
|
70
75
|
/**
|
|
@@ -138,6 +143,24 @@ export interface AttributionOptions {
|
|
|
138
143
|
* disables.
|
|
139
144
|
*/
|
|
140
145
|
wideWrites?: number | false;
|
|
146
|
+
/**
|
|
147
|
+
* Async-waterfall warning: emit a diagnostic when an async flight that
|
|
148
|
+
* could only start after an upstream flight resolved (its recompute's
|
|
149
|
+
* cause chain reaches the upstream's async landing, and its origin
|
|
150
|
+
* post-dates that landing) forms a sequential chain of 2+ flights, each
|
|
151
|
+
* of which took at least `minFlightMs` (default 50ms). The duration gate
|
|
152
|
+
* is one safety valve for what the graph cannot see: a settled
|
|
153
|
+
* preload/cache hit resolves fast and never warns. In-flight preloads are
|
|
154
|
+
* absolved by origin: `markFlight()` stamps (and first-seen identity)
|
|
155
|
+
* prove work predated the upstream landing — parallel, not sequential.
|
|
156
|
+
* Chains of 2 emit at `info` severity, structured channel only (a
|
|
157
|
+
* dependent fetch is sometimes intrinsic, and unmarked external preloads
|
|
158
|
+
* are invisible); 3+ escalate to `warn` with console output. `false`
|
|
159
|
+
* disables.
|
|
160
|
+
*/
|
|
161
|
+
waterfalls?: {
|
|
162
|
+
minFlightMs: number;
|
|
163
|
+
} | false;
|
|
141
164
|
}
|
|
142
165
|
export interface ScopeCost {
|
|
143
166
|
name: string;
|
|
@@ -181,6 +204,36 @@ export interface Attribution {
|
|
|
181
204
|
scopes: ScopeCost[];
|
|
182
205
|
writes: WriteCost[];
|
|
183
206
|
};
|
|
207
|
+
/**
|
|
208
|
+
* Every graph-provable sequential flight chain observed since enable()
|
|
209
|
+
* (ring-buffered like history()). Facts, not verdicts: chains are recorded
|
|
210
|
+
* regardless of the duration gate — the ASYNC_WATERFALL diagnostic is the
|
|
211
|
+
* thresholded view of the same data.
|
|
212
|
+
*/
|
|
213
|
+
waterfalls(): readonly WaterfallRecord[];
|
|
214
|
+
/**
|
|
215
|
+
* Cooperative preload declaration: stamp a flight object (promise or async
|
|
216
|
+
* iterable) with its true kickoff time BEFORE the reactive graph sees it.
|
|
217
|
+
* A route preloader or query cache calls this on the promise it hands out
|
|
218
|
+
* (on the WRAPPER it mints, with the original kickoff time — wrapping
|
|
219
|
+
* defeats identity tracking otherwise); any dependent that later awaits it
|
|
220
|
+
* is then judged against the real start — work already in the air when its
|
|
221
|
+
* upstream landed is parallel, never a waterfall link. Callable while
|
|
222
|
+
* attribution is disabled (marks made at navigation time must survive a
|
|
223
|
+
* later enable()). Dev-only, like the whole DEV surface.
|
|
224
|
+
*/
|
|
225
|
+
markFlight(flight: object, startedAt?: number): void;
|
|
184
226
|
format: typeof formatRerun;
|
|
185
227
|
}
|
|
228
|
+
/** One landed flight: its node name, wall duration, and upstream chain. */
|
|
229
|
+
export interface FlightLink {
|
|
230
|
+
name: string;
|
|
231
|
+
ms: number;
|
|
232
|
+
}
|
|
233
|
+
export interface WaterfallRecord {
|
|
234
|
+
/** Sequential flights, oldest first, ending at the flight that landed. */
|
|
235
|
+
chain: FlightLink[];
|
|
236
|
+
/** Summed wall time of the chain — the serialized cost. */
|
|
237
|
+
sequentialMs: number;
|
|
238
|
+
}
|
|
186
239
|
export declare const attribution: Attribution;
|
|
@@ -51,6 +51,60 @@ export declare const CONFIG_CHILD_COMPANIONS: number;
|
|
|
51
51
|
* moved into the cold extension (§12), and an unconditional `_x` deref per
|
|
52
52
|
* marked node measurably taxed the propagation hot path (diamond -22%). */
|
|
53
53
|
export declare const CONFIG_FW_CHILDREN: number;
|
|
54
|
+
/** Authoritative-view reader (`until()`): while this node computes, reads
|
|
55
|
+
* dodge active optimistic OVERRIDES only — the predicate must observe
|
|
56
|
+
* arriving truth, never the caller's own tentative writes (which would
|
|
57
|
+
* trivially satisfy it). Everything else reads normally, INCLUDING
|
|
58
|
+
* transition-staged `_pendingValue`: staged data is authoritative (optimism
|
|
59
|
+
* lives only in override slots), and a hold that refused staged reads would
|
|
60
|
+
* deadlock on data the open transaction itself is holding (a refresh the
|
|
61
|
+
* action issued lands staged and cannot commit until the hold releases).
|
|
62
|
+
* read() checks the bit on the reading computation (`context`) directly — no
|
|
63
|
+
* ambient flag — so a shared computed the predicate pulls recomputes as
|
|
64
|
+
* itself (no bit) under the normal view, and its cache never forks. */
|
|
65
|
+
export declare const CONFIG_AUTHORITATIVE_READ: number;
|
|
66
|
+
/** Sticky mark: an authoritative-view reader read this node PAST an active
|
|
67
|
+
* override. The ack shape — an authoritative arrival EQUAL to the override —
|
|
68
|
+
* rides paths that are deliberately silent under A17 (every ordinary reader
|
|
69
|
+
* sees the override, so an equal landing changes nothing for them). A marked
|
|
70
|
+
* node notifies those readers on such paths anyway, so the landed truth is
|
|
71
|
+
* seen without re-firing ordinary subscribers. Never cleared — only nodes an
|
|
72
|
+
* until() predicate observed mid-override pay. */
|
|
73
|
+
export declare const CONFIG_AUTHORITATIVE_OBSERVED: number;
|
|
74
|
+
/** Promise-delivery effect (resolve()/until()): commits its computed value
|
|
75
|
+
* directly even when recomputing under its own held transition. These
|
|
76
|
+
* effects deliver applies on a microtask (#2930) instead of the stashed
|
|
77
|
+
* effect queues, so the value must ride the same immediate schedule — a
|
|
78
|
+
* staged value with an immediate apply delivers stale state (resolve) or
|
|
79
|
+
* deadlocks the hold (until). Safe because the node is a private leaf: no
|
|
80
|
+
* subscriber reads an effect's value, only its own apply does. */
|
|
81
|
+
export declare const CONFIG_DIRECT_COMMIT: number;
|
|
82
|
+
/** Fresh-pull reader (awaitable `refresh()`'s waiter effect): a read of a
|
|
83
|
+
* dirty source recomputes it inline even when the height gate defers to the
|
|
84
|
+
* flush. Closes the same-flush ordering race where a waiter created
|
|
85
|
+
* alongside a refresh() mark read the PRE-re-ask value as settled and
|
|
86
|
+
* delivered stale; with the pull, the waiter either parks on the re-ask's
|
|
87
|
+
* pending window (async — woken by the settle walk, which runs on every
|
|
88
|
+
* landing including equal-value ones) or serves its sync answer. resolve()
|
|
89
|
+
* deliberately keeps that race — its contract is "first settled value"
|
|
90
|
+
* (#2930), not "next quiescent state". */
|
|
91
|
+
export declare const CONFIG_FRESH_READ: number;
|
|
92
|
+
/** HELD truth (#3164): this node's staged `_pendingValue` is confirming
|
|
93
|
+
* truth riding a transaction that retains optimism, revealed only at that
|
|
94
|
+
* transaction's settle. Two arming sites, one meaning: the store fold
|
|
95
|
+
* (a landing staged into the retaining transaction) and until()'s
|
|
96
|
+
* flip-entanglement (a foreign carrier's staged write, stolen when it
|
|
97
|
+
* flipped the awaited predicate truthy). Until the reveal, ordinary
|
|
98
|
+
* readers — lane and speculative recomputes included — keep committed:
|
|
99
|
+
* the staging notified subscribers as a plain write, so without the mask
|
|
100
|
+
* a mid-hold recompute composes live optimism with the confirming truth,
|
|
101
|
+
* a frame no timeline contains (GabbeV's union tear). Authoritative
|
|
102
|
+
* readers (until()'s predicate) and latest() tunnel through — the
|
|
103
|
+
* exemption that keeps holds deadlock-free. Override-covered nodes never
|
|
104
|
+
* arm: the override is their display and its revert their notification
|
|
105
|
+
* (A17). Cleared at commit (the commit IS the reveal); subscribers masked
|
|
106
|
+
* during the hold are woken by finalizePureQueue's post-revert pass. */
|
|
107
|
+
export declare const CONFIG_HELD_TRUTH: number;
|
|
54
108
|
export declare const STATUS_NONE = 0;
|
|
55
109
|
export declare const STATUS_PENDING: number;
|
|
56
110
|
export declare const STATUS_ERROR: number;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type Refreshable } from "./constants.js";
|
|
2
1
|
import { type OptimisticLane } from "./lanes.js";
|
|
3
2
|
import type { Computed, FirewallSignal, NodeExtension, NodeOptions, Owner, Signal } from "./types.js";
|
|
4
3
|
export declare const PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE = "[PRIMITIVE_IN_FORBIDDEN_SCOPE] Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled";
|
|
@@ -107,6 +106,19 @@ export declare const READ_SLOW: unique symbol;
|
|
|
107
106
|
* snapshot / transition / lane / dev-strictRead state all take the full
|
|
108
107
|
* resolution. Anything slow returns READ_SLOW; the caller then calls read().
|
|
109
108
|
*/
|
|
109
|
+
/**
|
|
110
|
+
* Wake only authoritative-view readers (until() predicates) subscribed to `el`.
|
|
111
|
+
* The A17-silent ack paths — an authoritative arrival equal to the active
|
|
112
|
+
* override — use this so the predicate re-evaluates without re-firing
|
|
113
|
+
* ordinary subscribers whose visible (override) value did not change.
|
|
114
|
+
* Pay-for-use: reached through GlobalQueue._notifyAuthoritativeObservers,
|
|
115
|
+
* installed at first until() call — apps that never use until() shake it.
|
|
116
|
+
*/
|
|
117
|
+
export declare function notifyAuthoritativeObservers(el: Signal<any> | Computed<any>): void;
|
|
118
|
+
/** Installs the until() machinery hook. Idempotent; called by until() before
|
|
119
|
+
* any authoritative-view read happens (same late-binding contract as the
|
|
120
|
+
* optimistic engine). */
|
|
121
|
+
export declare function installAuthoritativeRead(): void;
|
|
110
122
|
export declare function readNodeFast<T>(el: Signal<T>): T | typeof READ_SLOW;
|
|
111
123
|
export declare function read<T>(el: Signal<T> | Computed<T>): T;
|
|
112
124
|
/**
|
|
@@ -155,23 +167,10 @@ export declare function setMemo<T>(el: Computed<T>, v: T | ((prev: T) => T)): T;
|
|
|
155
167
|
export declare function runWithOwner<T>(owner: Owner | null, fn: () => T): T;
|
|
156
168
|
export declare function staleValues<T>(fn: () => T, set?: boolean): T;
|
|
157
169
|
/**
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* write-like invalidation operation: it does not read the target's value, and
|
|
164
|
-
* refreshing a plain signal accessor is a no-op.
|
|
165
|
-
*
|
|
166
|
-
* Use it to invalidate cached async values (e.g. force a re-fetch) without
|
|
167
|
-
* tearing the consumer down.
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* ```ts
|
|
171
|
-
* const user = createMemo(async () => fetch(`/users/${id()}`).then(r => r.json()));
|
|
172
|
-
*
|
|
173
|
-
* // Re-fetch on demand
|
|
174
|
-
* <button onClick={() => refresh(user)}>Reload</button>
|
|
175
|
-
* ```
|
|
170
|
+
* Core marking half of `refresh()` (the public wrapper lives in signals.ts —
|
|
171
|
+
* it validates the target, marks through here, then builds the quiescence
|
|
172
|
+
* promise on the resolve()/until() effect machinery). Flags the node's next
|
|
173
|
+
* recompute as a quiet re-ask and schedules it; no-ops for non-derived or
|
|
174
|
+
* disposed targets and for same-tick manual writes.
|
|
176
175
|
*/
|
|
177
|
-
export declare function
|
|
176
|
+
export declare function markRefresh(node: Computed<any>): void;
|
package/dist/types/core/dev.d.ts
CHANGED
|
@@ -6,8 +6,14 @@ export interface DevHooks {
|
|
|
6
6
|
onUpdate?: () => void;
|
|
7
7
|
onStoreNodeUpdate?: (state: any, property: PropertyKey, value: any, prev: any) => void;
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* `info` is the advisory tier: a structural fact worth surfacing that is not
|
|
11
|
+
* presumptively a bug (e.g. a 2-deep sequential fetch chain, which may be an
|
|
12
|
+
* intrinsic data dependency). Budget/assertion consumers should treat only
|
|
13
|
+
* `warn`/`error` as failures unless they opt in to `info`.
|
|
14
|
+
*/
|
|
15
|
+
export type DiagnosticSeverity = "info" | "warn" | "error";
|
|
16
|
+
export type DiagnosticCode = "STRICT_READ_UNTRACKED" | "PENDING_ASYNC_UNTRACKED_READ" | "PENDING_ASYNC_FORBIDDEN_SCOPE" | "REACTIVE_WRITE_IN_OWNED_SCOPE" | "ACTION_CALLED_IN_OWNED_SCOPE" | "RUN_WITH_DISPOSED_OWNER" | "NO_OWNER_CLEANUP" | "CLEANUP_IN_FORBIDDEN_SCOPE" | "SETTLED_CLEANUP_UNOWNED" | "SETTLE_WALK_UNINITIALIZED_SOURCE" | "FLUSH_IN_EFFECT_CALLBACK" | "PRIMITIVE_IN_FORBIDDEN_SCOPE" | "NO_OWNER_EFFECT" | "NO_OWNER_BOUNDARY" | "ASYNC_OUTSIDE_LOADING_BOUNDARY" | "INVALID_REFRESH_TARGET" | "INVALID_AFFECTS_TARGET" | "MISSING_EFFECT_FN" | "SYNC_NODE_RECEIVED_ASYNC" | "REACTIVITY_HALTED" | "INVARIANT_VIOLATION" | "HUGE_FAN_OUT" | "HUGE_FAN_IN" | "HOT_SCOPE_RERUNS" | "HOT_SCOPE_TIME" | "WIDE_SCOPE_DEPS" | "UNSTABLE_MEMO_OUTPUT" | "WIDE_WRITE" | "ASYNC_WATERFALL" | "HOT_SCOPE_FANOUT";
|
|
11
17
|
export type DiagnosticKind = "strict-read" | "async" | "write" | "lifecycle" | "owner" | "error" | "perf" | "graph";
|
|
12
18
|
/** First warning when a node's live edge count reaches this size. */
|
|
13
19
|
export declare const GRAPH_SIZE_WARN_AT = 2000;
|
|
@@ -39,6 +39,15 @@ export declare class StatusError extends Error {
|
|
|
39
39
|
}
|
|
40
40
|
/** Return the user's error from an internal status wrapper. */
|
|
41
41
|
export declare function unwrapStatusError(error: unknown): unknown;
|
|
42
|
+
/**
|
|
43
|
+
* Rejection value of `until(fn, { timeout })` when the predicate does not turn
|
|
44
|
+
* truthy within the window. Inside an `action()`, the rejection is thrown back
|
|
45
|
+
* in at the `yield` point — catchable there, or the action fails and its
|
|
46
|
+
* optimistic state reverts.
|
|
47
|
+
*/
|
|
48
|
+
export declare class TimeoutError extends Error {
|
|
49
|
+
constructor(message?: string);
|
|
50
|
+
}
|
|
42
51
|
export declare class NoOwnerError extends Error {
|
|
43
52
|
constructor();
|
|
44
53
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { ContextNotFoundError, NoOwnerError, NotReadyError } from "./error.js";
|
|
2
|
-
export { isEqual, untrack, runWithOwner, computed, signal, read, setSignal, setMemo, suppressComputedRecompute, optimisticSignal, optimisticComputed,
|
|
1
|
+
export { ContextNotFoundError, NoOwnerError, NotReadyError, TimeoutError } from "./error.js";
|
|
2
|
+
export { isEqual, untrack, runWithOwner, computed, signal, read, setSignal, setMemo, suppressComputedRecompute, optimisticSignal, optimisticComputed, installAuthoritativeRead, markRefresh, staleValues, setSnapshotCapture, markSnapshotScope, releaseSnapshotScope, clearSnapshots } from "./core.js";
|
|
3
3
|
export { enableExternalSource, _resetExternalSourceConfig, type ExternalSourceFactory, type ExternalSource, type ExternalSourceConfig } from "./external.js";
|
|
4
4
|
export { createOwner, createRoot, dispose, getNextChildId, getObserver, getOwner, isDisposed, cleanup, peekNextChildId } from "./owner.js";
|
|
5
5
|
export { createContext, getContext, setContext, type Context, type ContextRecord } from "./context.js";
|
|
@@ -40,6 +40,24 @@ export interface Transition {
|
|
|
40
40
|
_done: boolean | Transition;
|
|
41
41
|
_gatedSubs: Set<Computed<any>>;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Flip-entanglement (#3164 follow-up): `until()` is a declaration of
|
|
45
|
+
* relatedness — the predicate names the condition that confirms the awaiting
|
|
46
|
+
* transaction. When the predicate settles truthy, every live foreign
|
|
47
|
+
* transition whose staged write it read IS the confirming event by the
|
|
48
|
+
* user's own definition, so it merges into the awaiting transaction and
|
|
49
|
+
* reveals at the joint settle — the cross-primitive twin of the family fold
|
|
50
|
+
* (a landing on an optimism-carrying family joins the retaining
|
|
51
|
+
* transaction). Non-flipping updates never pass through here: falsy
|
|
52
|
+
* evaluations don't entangle, so unrelated traffic on the watched sources
|
|
53
|
+
* reveals freely on its own schedule.
|
|
54
|
+
*
|
|
55
|
+
* Runs inside the predicate's compute (pure phase) — the confirming
|
|
56
|
+
* transition's stamps are still live and its commit decision hasn't run, so
|
|
57
|
+
* the merge lands before any reveal. Only the tree-shaken graphs that call
|
|
58
|
+
* `until()` retain this.
|
|
59
|
+
*/
|
|
60
|
+
export declare function entangleConfirmingTransitions(obs: Computed<any>, target: Transition): void;
|
|
43
61
|
export declare function schedule(): void;
|
|
44
62
|
/**
|
|
45
63
|
* Permanently halts the reactive system. Called when a user error escapes
|
|
@@ -112,6 +130,10 @@ export declare class GlobalQueue extends Queue {
|
|
|
112
130
|
static _laneReadsCommitted: ((el: OptimisticNode, owner: OptimisticNode, c: Computed<any>) => boolean) | null;
|
|
113
131
|
static _recomputeLane: ((el: Computed<any>, own: boolean) => OptimisticLane | null | false) | null;
|
|
114
132
|
static _laneAsyncPending: ((el: Computed<any>) => void) | null;
|
|
133
|
+
/** Authoritative-view reader wakeup (until()): installed at first until() call.
|
|
134
|
+
* Call sites are gated by CONFIG_AUTHORITATIVE_OBSERVED, which only until()'s
|
|
135
|
+
* carve-out read can set, so `!` invocations are safe once the gate holds. */
|
|
136
|
+
static _notifyAuthoritativeObservers: ((el: Signal<any> | Computed<any>) => void) | null;
|
|
115
137
|
static _laneAsyncSettled: ((el: Computed<any>) => void) | null;
|
|
116
138
|
static _trackOptimisticStore: ((store: any) => void) | null;
|
|
117
139
|
flush(): void;
|
|
@@ -187,6 +209,23 @@ export declare const globalQueue: GlobalQueue;
|
|
|
187
209
|
*/
|
|
188
210
|
export declare function flush(): void;
|
|
189
211
|
export declare function flush<T>(fn: () => T): T;
|
|
212
|
+
/** A fresh, unentered transaction (#3146): the optimistic store's truth
|
|
213
|
+
* flight DECLARES an owned transaction instead of relying on whatever the
|
|
214
|
+
* ambient adoption machinery stamped on its firewall. Activate it with
|
|
215
|
+
* initTransition; it is a plain batch until then. */
|
|
216
|
+
export declare function createTransition(): Transition;
|
|
190
217
|
export declare function currentTransition(transition: Transition): Transition;
|
|
191
218
|
export declare function setActiveTransition(transition: Transition | null): void;
|
|
192
219
|
export declare function runInTransition<T>(transition: Transition, fn: () => T): T;
|
|
220
|
+
/** Run `fn` with `transition` as BOTH the ambient transaction and the
|
|
221
|
+
* registration batch, restoring both after. runInTransition alone is not
|
|
222
|
+
* enough for code that WRITES on behalf of a transaction from inside someone
|
|
223
|
+
* else's window (optimistic replay re-arming a still-open action's edits
|
|
224
|
+
* during a landing commit, #3123): registrations route through the queue's
|
|
225
|
+
* batch pointer, and a bare activeTransition swap leaves them in the ambient
|
|
226
|
+
* batch — a plain batch "completes" at the next flush and reverts optimistic
|
|
227
|
+
* registrations that were supposed to live with the transaction.
|
|
228
|
+
* initTransition is the wrong tool here: it MERGES the currently ambient
|
|
229
|
+
* transaction into the target, entangling whatever the interrupted window
|
|
230
|
+
* belonged to. */
|
|
231
|
+
export declare function runAsTransitionBatch<T>(transition: Transition, fn: () => T): T;
|
|
@@ -27,6 +27,11 @@ export interface NodeOptions<T> {
|
|
|
27
27
|
ownedWrite?: boolean;
|
|
28
28
|
/** Exclude this signal from snapshot capture (internal — not part of public API) */
|
|
29
29
|
_noSnapshot?: boolean;
|
|
30
|
+
/** Extra CONFIG_* bits OR'd into the node's config at creation (internal —
|
|
31
|
+
* not part of public API). Used by resolve()/until() for
|
|
32
|
+
* CONFIG_DIRECT_COMMIT / CONFIG_AUTHORITATIVE_READ, keeping the per-flag
|
|
33
|
+
* option arms out of the core creation path. */
|
|
34
|
+
_extraConfig?: number;
|
|
30
35
|
unobserved?: () => void;
|
|
31
36
|
lazy?: boolean;
|
|
32
37
|
sync?: boolean;
|
|
@@ -73,6 +78,13 @@ export interface NodeExtension {
|
|
|
73
78
|
*/
|
|
74
79
|
_affectsCount: number;
|
|
75
80
|
_inFlight: PromiseLike<any> | AsyncIterable<any> | null;
|
|
81
|
+
/** Cancellation for the CURRENT iterator flight (#3122): closes the
|
|
82
|
+
* iterator (`it.return()`), idempotent. Fired at the sites that release
|
|
83
|
+
* `_inFlight` so a superseded stream stops at supersede time — its owner
|
|
84
|
+
* cleanup registration may ride the zombie-disposal channel, which a held
|
|
85
|
+
* transition defers until the SUPERSEDING flight settles. Null for plain
|
|
86
|
+
* promise flights (no cancellation hook exists). */
|
|
87
|
+
_flightTeardown: (() => void) | null;
|
|
76
88
|
_error: unknown;
|
|
77
89
|
_blocked: boolean | undefined;
|
|
78
90
|
_pendingSources: Set<Computed<any>> | undefined;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { $REFRESH, ContextNotFoundError, NoOwnerError, NotReadyError, action, createContext, createOwner, createRoot, runWithOwner, flush, getNextChildId, peekNextChildId, getContext, setContext, getOwner, isDisposed, getObserver, isEqual, untrack, isPending, latest,
|
|
1
|
+
export { $REFRESH, ContextNotFoundError, NoOwnerError, NotReadyError, TimeoutError, action, createContext, createOwner, createRoot, runWithOwner, flush, getNextChildId, peekNextChildId, getContext, setContext, getOwner, isDisposed, getObserver, isEqual, untrack, isPending, latest, SUPPORTS_PROXY, setSnapshotCapture, markSnapshotScope, releaseSnapshotScope, clearSnapshots, enforceLoadingBoundary, enableExternalSource, resetErrorHalt } from "./core/index.js";
|
|
2
2
|
import { type Dev } from "./core/index.js";
|
|
3
3
|
export declare const DEV: Dev | undefined;
|
|
4
4
|
export type { Owner, Context, ContextRecord, IQueue, ExternalSourceFactory, ExternalSource, ExternalSourceConfig, Refreshable, Dev, DevHooks, DiagnosticCapture, DiagnosticCode, DiagnosticEvent, DiagnosticKind, Diagnostics, DiagnosticSeverity } from "./core/index.js";
|
|
5
|
-
export { createSignal, createMemo, createEffect, createRenderEffect, createTrackedEffect, createReaction, createOptimistic, resolve, onSettled, onCleanup } from "./signals.js";
|
|
6
|
-
export type { Accessor, SourceAccessor, Setter, Signal, ComputeFunction, EffectFunction, EffectBundle, EffectOptions, SignalOptions, MemoOptions, NoInfer } from "./signals.js";
|
|
5
|
+
export { createSignal, createMemo, createEffect, createRenderEffect, createTrackedEffect, createReaction, createOptimistic, refresh, resolve, until, onSettled, onCleanup } from "./signals.js";
|
|
6
|
+
export type { Truthy, UntilOptions, Accessor, SourceAccessor, Setter, Signal, ComputeFunction, EffectFunction, EffectBundle, EffectOptions, SignalOptions, MemoOptions, NoInfer } from "./signals.js";
|
|
7
7
|
export { affects } from "./affects.js";
|
|
8
8
|
export { mapArray, repeat, type Maybe } from "./map.js";
|
|
9
9
|
export * from "./store/index.js";
|
package/dist/types/signals.d.ts
CHANGED
|
@@ -365,17 +365,6 @@ export declare function createMemo<T>(compute: ComputeFunction<undefined | NoInf
|
|
|
365
365
|
* @description https://docs.solidjs.com/reference/basic-reactivity/create-effect
|
|
366
366
|
*/
|
|
367
367
|
export declare function createEffect<T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T> | EffectBundle<NoInfer<T>, T>, options?: EffectOptions): void;
|
|
368
|
-
/**
|
|
369
|
-
* @deprecated `createEffect(compute)` (single argument) is no longer supported.
|
|
370
|
-
* Pass a separate effect function as the second argument:
|
|
371
|
-
* `createEffect(compute, effect)`. See [MISSING_EFFECT_FN].
|
|
372
|
-
*
|
|
373
|
-
* - For a side effect that reacts to changes, split the work:
|
|
374
|
-
* `createEffect(() => signal(), value => doWork(value))`.
|
|
375
|
-
* - For a derived value, use `createMemo(() => signal())`.
|
|
376
|
-
* - For a one-shot side effect at construction time, just call the function.
|
|
377
|
-
*/
|
|
378
|
-
export declare function createEffect<T>(compute: ComputeFunction<undefined | NoInfer<T>, T>): never;
|
|
379
368
|
/**
|
|
380
369
|
* Creates a reactive computation that runs during the render phase as DOM elements
|
|
381
370
|
* are created and updated but not necessarily connected.
|
|
@@ -491,6 +480,114 @@ export declare function createReaction(effectFn: EffectFunction<undefined> | Eff
|
|
|
491
480
|
* @param fn a reactive expression to resolve
|
|
492
481
|
*/
|
|
493
482
|
export declare function resolve<T>(fn: () => T): Promise<T>;
|
|
483
|
+
/**
|
|
484
|
+
* Invalidates one reactive source, forcing it to re-execute even if its inputs
|
|
485
|
+
* haven't changed, and returns a promise for the target's NEXT QUIESCENT
|
|
486
|
+
* STATE — the re-ask (and anything that supersedes it) has settled.
|
|
487
|
+
*
|
|
488
|
+
* Pass either a Solid-created accessor or a projected store created from
|
|
489
|
+
* `createStore(fn, ...)` / `createProjection(...)`. `refresh()` is a
|
|
490
|
+
* write-like invalidation operation: it does not read the target's value, and
|
|
491
|
+
* refreshing a plain signal accessor is a no-op that resolves immediately.
|
|
492
|
+
*
|
|
493
|
+
* The returned promise is safe to ignore (fire-and-forget refresh is
|
|
494
|
+
* unchanged, and a failed refetch will not surface an unhandled rejection).
|
|
495
|
+
* Awaiting it gives imperative flows the settle point without a reactive
|
|
496
|
+
* read:
|
|
497
|
+
* - Accessor targets resolve with the settled value; store targets resolve
|
|
498
|
+
* with the store node passed (reads through it are fresh after the await).
|
|
499
|
+
* - A failed re-ask rejects with the error (inside an action's generator,
|
|
500
|
+
* `yield refresh(x)` throws back at the yield point and the action reverts
|
|
501
|
+
* like any other failure).
|
|
502
|
+
* - Semantics are quiescence, not flight identity: if another refresh (or
|
|
503
|
+
* any invalidation) supersedes this one mid-flight, the promise waits for
|
|
504
|
+
* — and delivers — whatever finally lands.
|
|
505
|
+
* - Inside an action, truth landing into the held transaction is STAGED;
|
|
506
|
+
* the promise still settles then (matching `resolve()`/`until()`, #2930)
|
|
507
|
+
* and delivers the staged value — the caller's own optimistic override is
|
|
508
|
+
* never the delivered value.
|
|
509
|
+
* - The re-ask itself stays verdict-quiet exactly as before: `isPending`
|
|
510
|
+
* does not flip for a bare refresh (pair with `affects()` for a visible
|
|
511
|
+
* pending window).
|
|
512
|
+
*
|
|
513
|
+
* @example
|
|
514
|
+
* ```ts
|
|
515
|
+
* const user = createMemo(async () => fetch(`/users/${id()}`).then(r => r.json()));
|
|
516
|
+
*
|
|
517
|
+
* // Fire-and-forget re-fetch
|
|
518
|
+
* <button onClick={() => refresh(user)}>Reload</button>;
|
|
519
|
+
*
|
|
520
|
+
* // Imperative settle point
|
|
521
|
+
* const fresh = await refresh(user);
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
export declare function refresh<T>(target: Refreshable<T>): Promise<T extends (...args: any) => infer V ? V : T>;
|
|
525
|
+
/** Falsy values a truthy predicate result is narrowed against. */
|
|
526
|
+
export type Truthy<T> = Exclude<T, false | 0 | 0n | "" | null | undefined>;
|
|
527
|
+
export interface UntilOptions {
|
|
528
|
+
/** Reject with `TimeoutError` if the predicate has not turned truthy within
|
|
529
|
+
* this many milliseconds. Strongly recommended when the confirming truth
|
|
530
|
+
* arrives over a transport that can drop (sockets, subscriptions). */
|
|
531
|
+
timeout?: number;
|
|
532
|
+
/** Reject with `signal.reason` on abort. */
|
|
533
|
+
signal?: AbortSignal;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Awaits a reactive predicate and resolves the first time it settles *truthy*,
|
|
537
|
+
* with that (narrowed) value. Falsy results and pending async reads both mean
|
|
538
|
+
* "not yet": the subscription stays live and re-evaluates as sources change.
|
|
539
|
+
* If the predicate settles with an error — a throw, or an async source that
|
|
540
|
+
* rejects — the promise rejects with it, as do timeout and abort.
|
|
541
|
+
*
|
|
542
|
+
* Where {@link resolve} answers "what is this value" (first settled value,
|
|
543
|
+
* whatever it is), `until` answers "when does the world confirm this
|
|
544
|
+
* condition". The difference matters inside an `action()`: `yield until(...)`
|
|
545
|
+
* holds the action's transaction — and any optimistic state riding it — open
|
|
546
|
+
* until the condition is independently true.
|
|
547
|
+
*
|
|
548
|
+
* To make that sound, `until`'s predicate reads the AUTHORITATIVE view — and
|
|
549
|
+
* this is the one read-semantics difference from `resolve`, which reads the
|
|
550
|
+
* normal (transaction's own) view where overrides are visible:
|
|
551
|
+
*
|
|
552
|
+
* - **Optimistic overrides are invisible** to the predicate. Your own
|
|
553
|
+
* tentative write can never satisfy your own ack, even on the
|
|
554
|
+
* single-primitive shape where the optimistic store IS the live-fed store.
|
|
555
|
+
* (Derived computeds serve their normal cached values — express the
|
|
556
|
+
* condition over sources of truth, not derived views of the overlay.)
|
|
557
|
+
* - **Everything else reads normally, including uncommitted transition-staged
|
|
558
|
+
* data.** Real data is real wherever it currently lives. This is
|
|
559
|
+
* load-bearing, not a loophole: truth that arrives *into* the open
|
|
560
|
+
* transaction (a `refresh()` this action issued, an entangled landing)
|
|
561
|
+
* stages and cannot commit until the hold releases — a predicate that
|
|
562
|
+
* refused staged reads would deadlock on the very data it is waiting for.
|
|
563
|
+
*
|
|
564
|
+
* This is the acknowledgment mechanism for mutations confirmed on a live data
|
|
565
|
+
* channel (sockets, subscriptions, live queries) rather than by the mutation's
|
|
566
|
+
* own response: correlate by a client-generated id or version in the predicate,
|
|
567
|
+
* and let truth arrive however it arrives — push, refetch, or another tab.
|
|
568
|
+
*
|
|
569
|
+
* Failure composes with action semantics: a rejection is thrown back into the
|
|
570
|
+
* generator at the `yield` point — catchable there, or the action fails and
|
|
571
|
+
* its optimistic state reverts.
|
|
572
|
+
*
|
|
573
|
+
* Must be called *outside* a tracking scope.
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* ```ts
|
|
577
|
+
* const send = action(async function* (text: string) {
|
|
578
|
+
* const clientId = crypto.randomUUID();
|
|
579
|
+
* setMessages(m => { m.push({ clientId, text, pending: true }); }); // optimistic
|
|
580
|
+
* await socket.send({ clientId, text }); // fire-and-forget transport
|
|
581
|
+
* // Hold until the live source echoes the write (authoritative view —
|
|
582
|
+
* // the optimistic row above cannot satisfy this):
|
|
583
|
+
* yield until(() => messages.some(m => m.clientId === clientId), { timeout: 10_000 });
|
|
584
|
+
* });
|
|
585
|
+
* ```
|
|
586
|
+
*
|
|
587
|
+
* @param fn a reactive predicate over authoritative state
|
|
588
|
+
* @param options optional `timeout` (ms) and abort `signal`
|
|
589
|
+
*/
|
|
590
|
+
export declare function until<T>(fn: () => T, options?: UntilOptions): Promise<Truthy<T>>;
|
|
494
591
|
/**
|
|
495
592
|
* Creates an optimistic signal that can be used to optimistically update a value
|
|
496
593
|
* and then revert it back to the previous value at end of transition.
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
+
import { type Transition } from "../../core/scheduler.js";
|
|
1
2
|
import { type NoFn, type ProjectionOptions, type Store, type StoreSetter } from "../store.js";
|
|
2
|
-
import type {
|
|
3
|
+
import type { StoreNextTarget } from "./target.js";
|
|
4
|
+
/** #3164 fold: a stamped truth is HELD (masked from ordinary readers until
|
|
5
|
+
* the reveal) only while its transition is live AND retaining optimism —
|
|
6
|
+
* overrides are what make partial-coverage composition a tear. A plain
|
|
7
|
+
* async transition carries no overrides, so downstream computes must see
|
|
8
|
+
* staged values to converge (normal speculation). Resolves merges first:
|
|
9
|
+
* merge unions optimistic nodes/stores into the target. */
|
|
10
|
+
export declare function transitionHoldsOptimism(transition: Transition): boolean;
|
|
3
11
|
export declare function createOptimisticStoreNext<T extends object = {}>(first: T | ((store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>), second?: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
|
|
4
12
|
/** Diff the draft against the current OPTIMISTIC VIEW (committed + active
|
|
5
13
|
* overrides — the same view the draft was seeded from) and emit engine writes
|
|
6
14
|
* for exactly the changed keys. Visible-view diffing keeps no-op writes from
|
|
7
15
|
* entangling lanes (RUL-10 / opt R38). */
|
|
8
16
|
export declare function notifyOptimisticWrites(t: StoreNextTarget, pb: Record<PropertyKey, any>): void;
|
|
9
|
-
/**
|
|
10
|
-
* Landing consumption (RUL-2): fresh authoritative data supersedes every
|
|
11
|
-
* tentative override in the family. Mirrors legacy clearProjectionOverride —
|
|
12
|
-
* drop the override, clear lane/ownership, notify subscribers whose visible
|
|
13
|
-
* value changes (reversion effects go to regular queues via the projection
|
|
14
|
-
* write posture the caller holds).
|
|
15
|
-
*/
|
|
16
|
-
export declare function consumeOverridesNext(fam: StoreNextFamily): void;
|
|
17
17
|
/** Optimistic-view composition for snapshot/deep (O1: snapshot is the CURRENT
|
|
18
18
|
* view, lane values included; a fresh copy per call during pending windows —
|
|
19
|
-
* RUL-12). Returns `src` untouched when no override is active on `t`.
|
|
19
|
+
* RUL-12). Returns `src` untouched when no override is active on `t`.
|
|
20
|
+
* Authoritative-view reads (until()'s predicate) skip composition entirely:
|
|
21
|
+
* the predicate observes authoritative truth, never the caller's tentative
|
|
22
|
+
* overlay. (Write-side emission callers never run under such a compute.) */
|
|
20
23
|
export declare function optimisticView(t: StoreNextTarget, src: Record<PropertyKey, any>): Record<PropertyKey, any>;
|
|
@@ -5,4 +5,4 @@ export declare function createProjectionNext<T extends object = {}>(fn: (draft:
|
|
|
5
5
|
* masks the recompute for the tick (core R31 — the manual write wins over a
|
|
6
6
|
* same-flush dependency change). */
|
|
7
7
|
export declare function createStoreDerivedNext<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [Refreshable<Store<T>>, (f: (draft: T) => T | void) => void];
|
|
8
|
-
export declare function runProjectionComputedNext<T extends object>(wrappedStore: Store<T>, fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, key: string | ((item: NonNullable<any>) => any) | null, wrapCommit?: (write: () => void) => void,
|
|
8
|
+
export declare function runProjectionComputedNext<T extends object>(wrappedStore: Store<T>, fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, key: string | ((item: NonNullable<any>) => any) | null, wrapCommit?: (write: () => void, value: T) => void, aroundDraftWrite?: (op: () => void) => void): Computed<void | T>;
|
|
@@ -30,9 +30,16 @@ export declare function materializePB(target: StoreNextTarget): void;
|
|
|
30
30
|
* authoritative base (R21/R32).
|
|
31
31
|
*/
|
|
32
32
|
export declare function adoptPB(target: StoreNextTarget, incoming: Record<PropertyKey, any>, eager?: boolean): void;
|
|
33
|
+
/** Parked truth-staged pending backings (#3164 fold): a tentative draft that
|
|
34
|
+
* opens while a folded landing's backing is live moves the staged container
|
|
35
|
+
* here (see ensurePB); the tentative discard in notifyOptimisticWrites
|
|
36
|
+
* restores it in place of the usual null. */
|
|
37
|
+
export declare const stagedTruthPB: WeakMap<StoreNextTarget, Record<PropertyKey, any>>;
|
|
33
38
|
/** Same logical slot: both values resolve to one (re-pointed) child target —
|
|
34
39
|
* adoption preserved identity, so the slot did not change (R9). */
|
|
35
40
|
export declare function targetsEqual(ov: any, nv: any): boolean;
|
|
41
|
+
export declare function arrayStructureChanged(old: any[], neu: any[]): boolean;
|
|
42
|
+
export declare function membershipChanged(old: Record<PropertyKey, any>, neu: Record<PropertyKey, any>): boolean;
|
|
36
43
|
/**
|
|
37
44
|
* The fold diff walks SUBSCRIPTION KEYS ONLY (legacy parity: `for key in
|
|
38
45
|
* nodes`): nodes exist exactly where something tracked, so unobserved data
|
|
@@ -62,6 +69,21 @@ export declare function runAuthoritative<T>(fn: () => T): T;
|
|
|
62
69
|
/** Active optimistic override on an armed node (armed slot idles at
|
|
63
70
|
* NOT_PENDING; undefined = unarmed plain node). */
|
|
64
71
|
export declare function hasActiveOverride(node: Signal<any>): boolean;
|
|
72
|
+
/** The reading computation is until()'s authoritative-view predicate — same
|
|
73
|
+
* source of truth as core read()'s A17 carve-out (`context`, which persists
|
|
74
|
+
* under untrack). optimisticView()'s composition gate consults exactly this:
|
|
75
|
+
* write-side machinery (patch emission, tentative re-application) must keep
|
|
76
|
+
* composing even when it runs inside an authoritative-write bracket. */
|
|
77
|
+
export declare function authoritativeRead(): boolean;
|
|
78
|
+
/** Serve-side authoritative gate: until()'s predicate PLUS truth authors —
|
|
79
|
+
* the projection derive's draft (wrapDraft trap brackets, runAuthoritative;
|
|
80
|
+
* the same posture pair ensurePB classifies drafts by). A source computing
|
|
81
|
+
* the next truth must never read its callers' tentative overlays: a derive
|
|
82
|
+
* continuation's `store.push` computing its index from an action's
|
|
83
|
+
* optimistic row landed truth in the wrong slot and corrupted committed
|
|
84
|
+
* state (#3108). Trap-level overlay serves gate on this so values, length,
|
|
85
|
+
* membership, and keys leave the authoritative view together. */
|
|
86
|
+
export declare function authoritativeServe(): boolean;
|
|
65
87
|
export type SetStoreNextFunction<T> = (fn: (draft: T) => T | void) => void;
|
|
66
88
|
/** Low-level setter primitive: opens write mode on a next proxy, runs `fn`,
|
|
67
89
|
* emits write-time notifications at outermost exit, applies returned
|