@solidjs/signals 2.0.0-rc.16 → 2.0.0-rc.17

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.
Files changed (39) hide show
  1. package/dist/dev-shared.js +1719 -1603
  2. package/dist/dev.attribution.js +13 -13
  3. package/dist/dev.js +182 -45
  4. package/dist/observe/boundaries.js +2 -2
  5. package/dist/observe/core/async.js +3 -1
  6. package/dist/observe/core/context.js +2 -0
  7. package/dist/observe/core/core.js +26 -10
  8. package/dist/observe/core/effect.js +2 -0
  9. package/dist/observe/core/graph.js +10 -8
  10. package/dist/observe/core/lanes.js +25 -14
  11. package/dist/observe/core/owner.js +73 -47
  12. package/dist/observe/core/scheduler.js +189 -173
  13. package/dist/observe/core/verdict.js +3 -0
  14. package/dist/observe/map.js +2 -2
  15. package/dist/observe/signals.js +6 -1
  16. package/dist/observe/store/affects.js +13 -13
  17. package/dist/observe/store/optimistic.js +112 -71
  18. package/dist/observe/store/store.js +25 -16
  19. package/dist/prod/boundaries.js +2 -2
  20. package/dist/prod/core/async.js +3 -1
  21. package/dist/prod/core/context.js +2 -0
  22. package/dist/prod/core/core.js +31 -15
  23. package/dist/prod/core/effect.js +2 -0
  24. package/dist/prod/core/graph.js +10 -8
  25. package/dist/prod/core/heap.js +1 -1
  26. package/dist/prod/core/lanes.js +25 -14
  27. package/dist/prod/core/owner.js +70 -44
  28. package/dist/prod/core/scheduler.js +43 -27
  29. package/dist/prod/core/verdict.js +4 -1
  30. package/dist/prod/map.js +2 -2
  31. package/dist/prod/signals.js +18 -13
  32. package/dist/prod/store/optimistic.js +112 -71
  33. package/dist/prod/store/store.js +18 -7
  34. package/dist/types/core/core.d.ts +10 -3
  35. package/dist/types/core/dev.d.ts +9 -1
  36. package/dist/types/core/error.d.ts +9 -1
  37. package/dist/types/core/owner.d.ts +4 -0
  38. package/dist/types/core/scheduler.d.ts +23 -4
  39. package/package.json +1 -1
@@ -10,7 +10,7 @@ import { getObserver } from "../core/owner.js";
10
10
 
11
11
  import { insertIntoHeap } from "../core/heap.js";
12
12
 
13
- import { txOf, flushTransaction, holdNode, joinFuture, insertSubs, schedule, passLane, globalQueue, queuePendingNode, GlobalQueue, installStoreHooks, joinPassTx, dirtyQueue } from "../core/scheduler.js";
13
+ import { txOf, flushTransaction, holdNode, joinFuture, insertSubs, schedule, passLane, globalQueue, queuePendingNode, resolveTx, GlobalQueue, installStoreHooks, joinPassTx, dirtyQueue } from "../core/scheduler.js";
14
14
 
15
15
  import { lookupTarget, setLookup, $OWNER, isOwned, markDescendants, devAssertNeverUserMutation } from "./target.js";
16
16
 
@@ -266,8 +266,13 @@ setSlotUnobserved(e => {
266
266
  // a node-less staging holds nothing (`stageOn`)
267
267
  // Held by the container's transaction only for a key the HELD staging
268
268
  // changed — a mainline layer's change above it stages mainline. (A
269
- // container carrying a guess is a lane's: the flush's park decides.)
270
- if ((i.l & (CONFIG_HELD | CONFIG_OVERRIDE)) === CONFIG_HELD && heldKeyChanged(e, r)) holdNode(n, txOf(i));
269
+ // container carrying a guess is a lane's: the flush's park decides —
270
+ // unless a correction folded under the guess, D-34: the key is that
271
+ // correction's hold's.)
272
+ if (i.l & CONFIG_HELD && heldKeyChanged(e, r)) {
273
+ const e = txOf(i);
274
+ if (!(i.l & CONFIG_OVERRIDE) || e.folded) holdNode(n, resolveTx(e._parent ?? e));
275
+ }
271
276
  // A28 (4): a batch written inside a creation-time pass is promoted — its
272
277
  // late-materialized leaf with it.
273
278
  if (i.l & CONFIG_PROMOTED) notePromotedWrite(n);
@@ -1111,7 +1116,7 @@ function inDraft(e) {
1111
1116
  * committed frame. */ function stagingReader() {
1112
1117
  let e = context;
1113
1118
  if (e === null) return null;
1114
- if (e.je) e = e.Ye ?? null;
1119
+ if (e.Qe) e = e.Ye ?? null;
1115
1120
  return e === null || e.l & CONFIG_CHILDREN_FORBIDDEN ? null : e;
1116
1121
  }
1117
1122
 
@@ -1645,7 +1650,9 @@ const traps = {
1645
1650
  set(e, n, t) {
1646
1651
  const r = inDraft(e);
1647
1652
  const i = !r && writeOverride;
1648
- if (!r && !i) return true;
1653
+ if (!r && !i) {
1654
+ return true;
1655
+ }
1649
1656
  if (n === "__proto__") return true;
1650
1657
  // pollution guard (core R30)
1651
1658
  const o = e.s ? t : unwrapValue(t);
@@ -1694,7 +1701,9 @@ const traps = {
1694
1701
  defineProperty(e, n, t) {
1695
1702
  const r = inDraft(e);
1696
1703
  const i = !r && writeOverride;
1697
- if (!r && !i) return true;
1704
+ if (!r && !i) {
1705
+ return true;
1706
+ }
1698
1707
  if (n === "__proto__") return true;
1699
1708
  if (t.get || t.set) e.a = true;
1700
1709
  if ("value" in t) t = {
@@ -1712,7 +1721,9 @@ const traps = {
1712
1721
  deleteProperty(e, n) {
1713
1722
  const t = inDraft(e);
1714
1723
  const r = !t && writeOverride;
1715
- if (!t && !r) return true;
1724
+ if (!t && !r) {
1725
+ return true;
1726
+ }
1716
1727
  const i = ensurePB(e);
1717
1728
  touch(e, n);
1718
1729
  // The key count (`kc`, the overlay gate and the rebuild cap) follows a
@@ -45,6 +45,9 @@ export declare function ext(el: {
45
45
  * the boundary collects it and shows its fallback, and the pass is the
46
46
  * boundary's, not the tick's (A29's boundary exemption, #3540). */
47
47
  export declare function joinPass(c: Computed<any>, el: Signal<any> | Computed<any>): void;
48
+ /** `joinPass` into the hold `t` (a folded guess's: store/optimistic.ts
49
+ * `foldedRead`, D-34) — a reader is never a render effect there. */
50
+ export declare function joinPassAt(c: Computed<any>, t: Transaction): void;
48
51
  /** A node born into transaction `t`: held by it and never committed (A29,
49
52
  * ruling A) — uninitialized (born held), or a member of the frame one of its
50
53
  * held passes built (CONFIG_HELD_FRAME). Its branch exists only in `t`: it
@@ -117,8 +120,9 @@ export declare function exitCallback(): void;
117
120
  * its owner (a list pass removing a row, a branch switching away), so its
118
121
  * writes are imperative like an effect callback's (#4165). Kept apart from
119
122
  * `callbackDepth` because its sites cannot use try/finally (the frame would
120
- * survive into prod): a throwing cleanup leaves it raised, and dev.ts resets
121
- * it on the next microtask, which teardown — synchronous — never spans.
123
+ * survive into prod). A throwing cleanup is caught (owner.ts `runCleanup`);
124
+ * anything else escaping a teardown leaves it raised, and dev.ts resets it on
125
+ * the next microtask, which teardown — synchronous — never spans.
122
126
  */
123
127
  export declare let disposalDepth: number;
124
128
  export declare function enterDisposal(): void;
@@ -239,7 +243,10 @@ export declare function read<T>(el: Signal<T> | Computed<T>): T;
239
243
  export declare function serve(el: Signal<any> | Computed<any>, c: Computed<any> | null): unknown;
240
244
  /** A pass read a staging of this flush: it derives from what the flush may
241
245
  * yet hold (REACTIVE_STAGED_READ — the seam decides). Lane work too (plan sec. 28, a
242
- * lane sees the screen plus its own guesses): the staging is the screen if
246
+ * lane sees the screen plus its own guesses) — a folded lane's only before
247
+ * the frame has a transaction (after, it reads the screen like a verdict
248
+ * reader, `stagedScreen` — a list pass never pairs a held length with the
249
+ * guess's rows, D-34): the staging is the screen if
243
250
  * the frame commits — one pass, the common case — and a held write if it
244
251
  * parks, which the seam repairs (`stagedReaders`): the pass re-derives on
245
252
  * the committed world and its lane's runs wait that round, so the held
@@ -16,7 +16,7 @@ export interface DevHooks {
16
16
  * `warn`/`error` as failures unless they opt in to `info`.
17
17
  */
18
18
  export type DiagnosticSeverity = "info" | "warn" | "error";
19
- export type DiagnosticCode = "STRICT_READ_UNTRACKED" | "PENDING_ASYNC_UNTRACKED_READ" | "PENDING_ASYNC_FORBIDDEN_SCOPE" | "REACTIVE_WRITE_IN_OWNED_SCOPE" | "ASYNC_STORE_SETTER" | "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" | "PRIMITIVE_IN_EFFECT_CALLBACK" | "NO_OWNER_EFFECT" | "NO_OWNER_BOUNDARY" | "ASYNC_OUTSIDE_LOADING_BOUNDARY" | "LOADING_ON_OUTSIDE_HOLD" | "INVALID_REFRESH_TARGET" | "INVALID_AFFECTS_TARGET" | "MISSING_EFFECT_FN" | "SYNC_NODE_RECEIVED_ASYNC" | "UNTRACKED_READ_AFTER_AWAIT" | "REACTIVITY_HALTED" | "INVARIANT_VIOLATION" | "HUGE_FAN_OUT" | "HUGE_FAN_IN" | "GRAPH_GROWTH" | "HOT_SCOPE_RERUNS" | "HOT_SCOPE_TIME" | "WIDE_SCOPE_DEPS" | "UNSTABLE_MEMO_OUTPUT" | "WASTED_RECOMPUTE" | "ASYNC_WATERFALL" | "HOT_SCOPE_FANOUT" | "SILENT_HOLD" | "LONG_HOLD" | "UNTRACKED_ASYNC_HANDLER" | "ABANDONED_FLIGHTS" | "FALLBACK_FLASH" | "STACKED_HOLDS" | "OPTIMISTIC_REVERTED" | "EFFECT_WRITES_OWN_SOURCE" | "EFFECT_RELAY_TEAR" | "IMMUTABLE_UPDATE_IN_STORE" | "UNSTABLE_LIST_IDENTITY" | "SSR_RENDER_ERROR_CONTAINED" | "SSR_SUBTREE_ABANDONED" | "SSR_STREAM_ABANDONED" | "SSR_CLIENT_CONTENT_MASKED" | "LATE_HEADER_WRITE" | "SERVER_ERROR_SANITIZED" | "SSR_BOUNDARY_WATERFALL" | "SSR_UNDECLARED_LIVE_SOURCE" | "SSR_LIVE_HOLE_LATCHED" | "SERVER_WRITE" | "REVEAL_IN_RENDER_TO_STRING" | "LAZY_ASSET_UNMAPPED" | "PRELOAD_DESCRIPTOR_INVALID" | "HEAD_TAG_INVALID" | "UNRECOGNIZED_INSERT_VALUE" | "UNSCOPED_HOLE_ALLOCATED_IDS" | "LOWERCASE_EVENT_ATTRIBUTE" | "FRAME_MARKER_CORRUPTED" | "DYNAMIC_ASYNC_COMPONENT";
19
+ export type DiagnosticCode = "STRICT_READ_UNTRACKED" | "PENDING_ASYNC_UNTRACKED_READ" | "PENDING_ASYNC_FORBIDDEN_SCOPE" | "REACTIVE_WRITE_IN_OWNED_SCOPE" | "ASYNC_STORE_SETTER" | "STORE_WRITE_OUTSIDE_SETTER" | "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" | "PRIMITIVE_IN_EFFECT_CALLBACK" | "NO_OWNER_EFFECT" | "NO_OWNER_BOUNDARY" | "ASYNC_OUTSIDE_LOADING_BOUNDARY" | "LOADING_ON_OUTSIDE_HOLD" | "INVALID_REFRESH_TARGET" | "INVALID_AFFECTS_TARGET" | "MISSING_EFFECT_FN" | "SYNC_NODE_RECEIVED_ASYNC" | "UNTRACKED_READ_AFTER_AWAIT" | "REACTIVITY_HALTED" | "INVARIANT_VIOLATION" | "HUGE_FAN_OUT" | "HUGE_FAN_IN" | "GRAPH_GROWTH" | "HOT_SCOPE_RERUNS" | "HOT_SCOPE_TIME" | "WIDE_SCOPE_DEPS" | "UNSTABLE_MEMO_OUTPUT" | "WASTED_RECOMPUTE" | "ASYNC_WATERFALL" | "HOT_SCOPE_FANOUT" | "SILENT_HOLD" | "LONG_HOLD" | "UNTRACKED_ASYNC_HANDLER" | "ABANDONED_FLIGHTS" | "FALLBACK_FLASH" | "STACKED_HOLDS" | "OPTIMISTIC_REVERTED" | "EFFECT_WRITES_OWN_SOURCE" | "EFFECT_RELAY_TEAR" | "IMMUTABLE_UPDATE_IN_STORE" | "UNSTABLE_LIST_IDENTITY" | "SSR_RENDER_ERROR_CONTAINED" | "SSR_SUBTREE_ABANDONED" | "SSR_STREAM_ABANDONED" | "SSR_CLIENT_CONTENT_MASKED" | "LATE_HEADER_WRITE" | "SERVER_ERROR_SANITIZED" | "SSR_BOUNDARY_WATERFALL" | "SSR_UNDECLARED_LIVE_SOURCE" | "SSR_LIVE_HOLE_LATCHED" | "SERVER_WRITE" | "REVEAL_IN_RENDER_TO_STRING" | "LAZY_ASSET_UNMAPPED" | "PRELOAD_DESCRIPTOR_INVALID" | "HEAD_TAG_INVALID" | "UNRECOGNIZED_INSERT_VALUE" | "UNSCOPED_HOLE_ALLOCATED_IDS" | "LOWERCASE_EVENT_ATTRIBUTE" | "UNCOMMITTED_INPUT_OVERWRITTEN" | "FRAME_MARKER_CORRUPTED" | "DYNAMIC_ASYNC_COMPONENT";
20
20
  export type DiagnosticKind = "strict-read" | "async" | "write" | "lifecycle" | "owner" | "error" | "perf" | "graph"
21
21
  /** Perceived responsiveness: the runtime behaved correctly but the user saw no feedback. */
22
22
  | "responsiveness"
@@ -472,6 +472,14 @@ export declare function ownerPath(subject: DiagnosticSubject | null | undefined)
472
472
  * own). Console output is a separate, dev-tier step — see `reportDiagnostic`.
473
473
  */
474
474
  export declare function emitDiagnostic(event: Omit<DiagnosticEvent, "sequence">, subject?: DiagnosticSubject | null | undefined): DiagnosticEvent;
475
+ /**
476
+ * The locating lines of a console report: `\n in <App> › <TodoRow> › effect`
477
+ * (the owner path) and `\n at src/App.tsx:18:3` (see `locationLine`), each
478
+ * when the entry carries it; `""` when it carries neither. Shared by
479
+ * `reportDiagnostic` and the sites that print their own console entry (the
480
+ * halt, which logs its cause beside the message).
481
+ */
482
+ export declare function locationLines(entry: DiagnosticEvent): string;
475
483
  /**
476
484
  * The console face of a diagnostic — ONE entry per finding: the message, the
477
485
  * owner path (`in <App> › <TodoRow> › effect`) so a human can locate it, the
@@ -52,5 +52,13 @@ export declare class NoOwnerError extends Error {
52
52
  constructor();
53
53
  }
54
54
  export declare class ContextNotFoundError extends Error {
55
- constructor();
55
+ /**
56
+ * In dev, a read site passes the context (and whether a provider above set
57
+ * it to `undefined`) so the message can name it and say why it has no
58
+ * value (#4181). Read through `arguments` so production — where the message
59
+ * is empty — keeps the zero-parameter constructor byte for byte.
60
+ */
61
+ constructor(context?: {
62
+ id: symbol;
63
+ }, providedUndefined?: boolean);
56
64
  }
@@ -1,6 +1,10 @@
1
1
  import type { Computed, Disposable, Owner, Root } from "./types.js";
2
2
  export declare function markDisposal(el: Owner): void;
3
3
  export declare function dispose(node: Computed<unknown>): void;
4
+ /** Runs a cleanup or `unobserved` hook; a throw is collected, not raised. @internal */
5
+ export declare function runCleanup(fn: () => void): void;
6
+ /** Rethrows the error `runCleanup` collected, once; `drop` discards it. @internal */
7
+ export declare function rethrowCleanupError(drop?: boolean): void;
4
8
  export declare function disposeChildren(node: Owner, self?: boolean, zombie?: boolean): void;
5
9
  export declare function linkChild(parent: Owner, node: Owner): void;
6
10
  /**
@@ -1,3 +1,4 @@
1
+ import { type DiagnosticSubject } from "./dev.js";
1
2
  import { type Heap } from "./heap.js";
2
3
  import type { Computed, Owner, Signal } from "./types.js";
3
4
  export declare let laneReadHook: ((c: Computed<any> | null, el: Signal<any> | Computed<any>) => unknown) | null;
@@ -79,6 +80,15 @@ export interface Transaction {
79
80
  * leaf reading a held lane that has not shown is a stale reader of it
80
81
  * (#3460); one reading a lane the seam has not judged yet is its work. */
81
82
  _held: boolean;
83
+ /** Lane: a current truth that differs folded beneath one of its keyed
84
+ * guesses (lanes.ts `laneWrite`, D-34) — the store's reader of it: a
85
+ * deriving pass outside the lane, or `latest()` (`c` null), is served
86
+ * the hold's world from its guesses; NOT_PENDING otherwise
87
+ * (store/optimistic.ts `foldedRead`). Unset until then; not
88
+ * `_`-prefixed: a new mangled name shifts every later one
89
+ * (scripts/mangle-props.mjs), which costs the floors bytes for a path
90
+ * only optimistic stores reach. */
91
+ folded?: (c: Computed<any> | null, el: Signal<any> | Computed<any>) => unknown;
82
92
  /** `affects()` marks declared in it (affects.ts): released at the landing.
83
93
  * Not nodes — a mark holds nothing (`blocked` never sees one). */
84
94
  _marks: Signal<any>[] | null;
@@ -219,6 +229,13 @@ export declare function schedule(): void;
219
229
  */
220
230
  export declare const ROOT_ERROR_HOOK: unique symbol;
221
231
  export declare function haltReactivity(cause?: unknown): void;
232
+ /**
233
+ * Dev: `haltReactivity`, located at `subject` — the computation the uncaught
234
+ * error escaped from — for the REACTIVITY_HALTED message's owner path. Call
235
+ * sites pick it in dev builds only (`haltReactivity(e)` in production), so
236
+ * production keeps the one-argument halt and its bytes unchanged.
237
+ */
238
+ export declare function haltReactivityAt(cause: unknown, subject: DiagnosticSubject): void;
222
239
  /** @internal Test/dev-reload hook. Revives scheduling after a halt. */
223
240
  export declare function resetErrorHalt(): void;
224
241
  export interface IQueue {
@@ -252,10 +269,12 @@ export declare class GlobalQueue implements IQueue {
252
269
  static _storeWrappable: ((v: unknown) => boolean) | undefined;
253
270
  static _mark: ((node: Signal<any> | Computed<any>) => void) | undefined;
254
271
  static _witnessMark: (() => void) | undefined;
255
- /** An older question's truth was held beneath a guess (lanes.ts
256
- * `laneWrite`): the store re-bases an arrangement guess over it
257
- * (store/optimistic.ts). */
258
- static _laneRebase: ((el: Signal<any>, truth: unknown) => void) | undefined;
272
+ /** A truth landing on a guess (lanes.ts `laneWrite`), `older` when it
273
+ * answers an older question: the store re-bases an arrangement guess over
274
+ * it; a current one differing from a shown keyed arrangement guess folds
275
+ * beneath it instead of voiding it (D-34) — true: the lane stages it
276
+ * beneath (store/optimistic.ts). */
277
+ static _laneRebase: ((el: Signal<any>, truth: unknown, older: boolean) => boolean | void) | undefined;
259
278
  static _verdictLane: ((t: Transaction) => Transaction) | undefined;
260
279
  static _laneGuesses: ((t: Transaction) => Signal<any>[]) | undefined;
261
280
  /** `createDeferred` (deferred.ts): a deferred node with a flight up that
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidjs/signals",
3
- "version": "2.0.0-rc.16",
3
+ "version": "2.0.0-rc.17",
4
4
  "description": "Solid's reactive primitives: signals, memos, effects, stores, and async-aware computations.",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",