Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
143c530
size(signals): L2 hold model, carve, lanes/verdicts/boundaries/reveal…
ryansolid Oct 2, 2026
8f304a3
size(signals): carve the lane layer (lanes.ts, verdict.ts) for the §2…
ryansolid Oct 2, 2026
41a75a4
size(signals): §28 S0 — the lane layer rebuilt on the slot (lanes.ts,…
ryansolid Oct 3, 2026
c1dadbc
size(signals): §28 S1 — holds and seams (A15 LANE, #3463, #3648, #354…
ryansolid Oct 3, 2026
23f2870
size(signals): §28 S2 — verdicts and consolidation (watchers → staged…
ryansolid Oct 3, 2026
9487c06
size(signals): affects() on L2 — transaction-inert, as ruled (A24 (4)…
ryansolid Oct 3, 2026
8f292e5
size: attribution on L2 — feed the observe engine from the lane/verdi…
ryansolid Oct 3, 2026
25200eb
docs(plan): §31 stores on L2 — T0 inventory, design candidate, perf c…
ryansolid Oct 3, 2026
6bd9f6e
docs(plan): §31.7 stores on L2 — rulings Q-A…Q-G, benchmark reference…
ryansolid Oct 3, 2026
9b75c1c
size(signals): §31 S1 — plain stores on L2 (container node, slot lite…
ryansolid Oct 3, 2026
7bd0630
size(signals): §31 S2 — plain stores under holds; read()'s held arm f…
ryansolid Oct 3, 2026
5eb10eb
size(signals): §31 S3a — projections, derived stores, reconcile on L2
ryansolid Oct 3, 2026
f53c670
size(signals): §31 S3b — holds on derived stores (#3706, #3688, #3612…
ryansolid Oct 3, 2026
32f640c
size(signals): §35 S4 — optimistic stores on lanes (createOptimisticS…
ryansolid Oct 3, 2026
69c946f
size(signals): §35.1 store size pass — attribution, seam trim (−29 br…
ryansolid Oct 3, 2026
ea7a9cc
size(signals): §36 S-U — utils.ts back (merge/omit, views); the carve…
ryansolid Oct 3, 2026
a0400de
size(signals): §37 S5 — affects() store half; StoreNode back; declara…
ryansolid Oct 3, 2026
02798df
docs(plan): §38 Q-D decision memo — overlapping actions on one array,…
ryansolid Oct 3, 2026
b9622e9
size(signals): §39 Q-D — provenance-gated landings on optimistic stor…
ryansolid Oct 3, 2026
95b8785
size(signals): §39.1 parity — signal/store twins for Q-D and the kanb…
ryansolid Oct 4, 2026
cb04977
size(signals): §40 S3c — projection verdict windows, family pending v…
ryansolid Oct 4, 2026
72bf0ac
docs(plan): §40.3 — the remaining web red diagnosed (frames rebind he…
ryansolid Oct 4, 2026
241c144
perf(signals): §41 — family settle walk only after a wake; value read…
ryansolid Oct 4, 2026
f029db6
perf(signals): §41.4 — the per-key staging question once per pass; no…
ryansolid Oct 4, 2026
d4c6c7f
test(signals): re-point next-smoke and owner-stamp at the rebuilt sto…
ryansolid Oct 4, 2026
4f85d80
perf(signals): §41.5 — Q-A escape hatch: container node only when a h…
ryansolid Oct 4, 2026
e133516
fix(web): frames — re-arm the switch gate and rebind in the pass, not…
ryansolid Oct 4, 2026
169e1f8
fix(html): exit raw text mode after a self-closing raw text element (…
drakeo338 Oct 2, 2026
ba7a686
fix(html): component props named on/only/once get getters like any dy…
ryansolid Oct 2, 2026
1bef2aa
fix(compilers,web): compiled SSR style objects no longer glue a compu…
dex157 Oct 2, 2026
19b674b
fix(compiler): load the WASI fallback where / is not accessible (Andr…
ryansolid Oct 2, 2026
827ba88
fix(web): spread applies attributes before children, matching ssrElem…
ryansolid Oct 2, 2026
b0eb0e5
fix(web): stylesheet-gated fragments reveal under a nonce CSP and whe…
everton-dgn Oct 2, 2026
817738d
fix!: lowercase on* names are attributes, not event handlers (#3753)
ryansolid Oct 2, 2026
2a015e7
fix(h): materialize elements without mutating the caller's props; cor…
ryansolid Oct 2, 2026
925e3d3
fix(web): a late hydration claim leaves server nodes in place (#3749)…
ryansolid Oct 3, 2026
7f31f5e
chore(size): keep the size comparison green on fork PRs (#3765)
everton-dgn Oct 4, 2026
87ce0fc
fix(signals): derived writes apply first, then derivations re-run (#3…
ryansolid Oct 1, 2026
e26bb58
fix(signals): a derive reading a held key through its draft joins the…
ryansolid Oct 4, 2026
7654e17
docs(signals): the spec pass — "The hold model — L2" in SPEC-ASYNC-SE…
ryansolid Oct 4, 2026
1aca890
docs(signals): every A-rule's Mechanism paragraph rewritten for L2; t…
ryansolid Oct 4, 2026
8af3415
merge: origin/next (#3772 createSSRResponse teardown) into size/carve…
ryansolid Oct 4, 2026
82dd0f7
docs(signals): regenerate RULES-INDEX after merging origin/next (cita…
ryansolid Oct 4, 2026
0699462
merge: origin/next (#3763 request failures before render) into size/c…
ryansolid Oct 4, 2026
b33e450
size: frames eager client 12.98 -> 13.00 KB for the switch-gate fix (…
ryansolid Oct 4, 2026
5001e7b
size: frames eager client ledger note — CI measurements (+20 B br, +7…
ryansolid Oct 4, 2026
22c3d3e
perf(signals): record a pre-batch backing only for adoptions — fresh …
ryansolid Oct 4, 2026
c57018c
size: lower every cap to the L2 measurements + 10 B (the ratchet)
ryansolid Oct 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/derive-reads-held-key-joins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): a derived store's derive reading a key (or container) a transaction holds through its draft — a user's write inside an action, held with it — joins that transaction, so the derive's whole result reveals with the action rather than key by key (core R31 / #3733: "under the transaction and revealed with it"; the `derived-write-then-derivation-3733` action-hold pin). A user setter reading its own draft is no pass and joins nothing.
5 changes: 5 additions & 0 deletions .changeset/frames-rebind-in-the-pass.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/web": patch
---

Frames client: an address switch re-arms the shell gate and rebinds the frame in the pass that sees the new address (the follow's compute), not in an effect's run. Under the hold model a switch delivered while the previous switch's gate still pends lands the binding in the frame that gate holds, and an effect's run is stashed with that frame — behind the very gate the rebind would release, so a second switch mid-flight never bound to the live call. The gate signal takes `ownedWrite` (the re-arm and a warm rebind's release are written from the pass). Both the call-driven mount and the document-adoption face.
5 changes: 5 additions & 0 deletions .changeset/size-affects-on-l2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): `affects()` rebuilt on the L2 hold model as ruled (A24 (4), the #2893 audit) — a declared in-flight change that lights up `isPending` on the marked accessor and its derivations for the surrounding transaction's lifetime; never a hold, never an entanglement, never a suspension. A count on the node, listed with its scope; coverage pull-derived at probe time; verdict readers re-derived at registration and release. The store targets return with the stores. Also: `GlobalQueue`'s hook statics are `declare static` (type-only) — they emitted as `static X;` on every bundle.
5 changes: 5 additions & 0 deletions .changeset/size-attribution-on-l2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Attribution on the L2 hold model: the observe-tier engine is fed from the rebuilt lane and verdict layers again (hold census — blockers, optimistic/affects/isPending/latest acknowledgements; optimistic reverts labelled superseded vs reverted; loading-boundary fallback show/hide records; run posture). A lane derivation's first landing no longer trips the dev `SETTLE_WALK_UNINITIALIZED_SOURCE` tripwire.
5 changes: 5 additions & 0 deletions .changeset/size-audit-l2-hold-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): the reactive engine rebuilt on the L2 hold model — transactions as the one hold relationship (membership, `blocked`, frame reads, born-held), with lanes (`createOptimistic`), verdicts (`isPending`/`latest`), boundaries (`createLoadingBoundary`/`createErrorBoundary`), `createRevealOrder` and `action` rebuilt on it as modules behind `GlobalQueue` hooks; stores, `affects()` and the attribution engine carved out pending their own steps. Every step is measured on the whole size suite and recorded in `documentation/plans/size-reduction-carve-step1.md` (§1–§28), with the maintainer's rulings that decided each behavior. Checkpoint before the §28 replay of the lane layer.
5 changes: 5 additions & 0 deletions .changeset/size-carve-lane-layer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): carve the lane layer — `createOptimistic`'s write, `isPending`, `latest` — ahead of its rebuild from the §28 principles (`documentation/plans/size-reduction-carve-step1.md`). The layer measured 1775 B br on `+ isPending/latest` and 1809 B br on the live page as built.
5 changes: 5 additions & 0 deletions .changeset/size-lane-layer-s0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): the lane layer rebuilt from the §28 principles (S0 skeleton). A node's value lives in one of three places — `_value` the committed truth, `_pendingValue` a transaction's staging, `_x._lane` the lane's value — and the lane transaction carries the shown/held state (`_shown`, `_held`); the seat of a pass is its node's; leaves read the screen; the body-end correction runs at the seam with one more pure round so its re-derivations are the parent's; a dissolving lane retires the void world's flights. Removes `CONFIG_LANE_HELD`, `CONFIG_HELD_TRUTH`, `REACTIVE_VERDICT_RERUN` and the seam-time value swap. Fixes #3409 (indicators of a body-end correction clear together) and the #3698 held-lane children case. Design and results in `documentation/plans/size-reduction-carve-step1.md` §28.
5 changes: 5 additions & 0 deletions .changeset/size-lane-layer-s1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): §28 S1 — holds and seams on the rebuilt lane layer. A render effect reading a lane flight that has never shown waits on it in its own frame and reads the landed answer at the landing (A15 LANE, #3334); a zombie's say is moot only for the transaction that disposes it (#3463); a lane-derived value committed at a dissolve publishes its inputs (#3648); a boundary re-armed through a display-ahead read swaps as the lane's from the head (#3540); any stale reader of a flight holds it, lane work included (V5/A17).
5 changes: 5 additions & 0 deletions .changeset/size-lane-layer-s2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): §28 S2 — verdicts and consolidation on the rebuilt lane layer. The verdict watchers merge into the lane layer's staged-readers list (one seam, one rule: a pass that read this flush's staging as the screen re-derives if the frame parks); one `staleReader` registration shared by frame reads, lane reads and verdict routes; `dissolveLane` restructured by outcome, every guess of a dissolving lane re-homed with its truth. No behavior change; 0 pins moved.
5 changes: 5 additions & 0 deletions .changeset/size-spec-l2-hold-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): the spec pass. `SPEC-ASYNC-SEMANTICS.md` gains "The hold model — L2 (2026-10-04)" — the carve's rulings in the spec's voice, the 2026-10-03 re-pins, and a mechanism note (the per-rule "Mechanism (index, 2026-09-14/15)" paragraphs describe the pre-L2 implementation; the L2 module map is the cross-reference) — with dated amendments on A18, A19, A22, A29 and A34. `INTERNALS-ASYNC-STATE.md` gains "0. L2 — the hold model: what replaced §1–§4". `RULES-INDEX.md` regenerated; plan-section citations in `src/` comments are written `plan sec. N`. Comment-only in source.
5 changes: 5 additions & 0 deletions .changeset/size-store-bench-fixes-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): §41.4 benchmark fixes. A plain pass already marked as having read this flush's staging reads an unheld container staging directly — the per-key "did this key change" question is asked once per pass, not once per key (a `mapArray` over 1k shifted rows asked it 1k times; store array ops `splice`/`shift`/`unshift`/`reverse`/`push` on 1k proxied rows now at parity with `next`). At the fold, a child whose parent was adopted whole no longer re-resolves its slot by an O(rows) `indexOf` that cannot hit (the slot already holds the child's new backing).
5 changes: 5 additions & 0 deletions .changeset/size-store-bench-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): §41 benchmark fixes. A derived store's family settle walk runs only after a wake (`fam.woke`), not on every sync commit — a 1k-row derived store's no-op re-derive was walking every leaf (14× the fork). A value read under a staging asks only whether the key's value or presence changed (`readSource(target, key, shape)`); descriptor readers and hold decisions keep the full enumerability/accessor test, as does any container with accessors seen. Keyed reconcile of 1k rows read by `mapArray` in the staging flush: 2.5× faster.
5 changes: 5 additions & 0 deletions .changeset/size-store-container-node-escape-hatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): §41.5 — the container node's escape hatch (Q-A). A store staging gets its container node only when something can read the frame through it: a structural subscriber, lane work, a creation-time pass, or a derive a transaction holds. Otherwise the backing swap and the fold queue are the whole staging — nothing is allocated, queued or swept per container — and when a flush parks, the seam materializes and holds the node for every node-less staging (`_storePark`), so a never-read key of a held container still reads committed until the landing (pinned). The fold queue itself no longer allocates per batch: a reusable list plus a weak map of pre-batch backings written in place (a dbmon tick's ~7000 containers cost ~540 KB of map table per tick before). dbmon-deep tick 1.17–1.19× → 1.08–1.13× by the harness's own method; node parity.
5 changes: 5 additions & 0 deletions .changeset/size-store-prebatch-backing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): the fold queue records a pre-batch backing only for adoptions (whose backing swaps eagerly), in a weak map written in place batch after batch; a draft's pre-batch backing is its own committed backing, so nothing is recorded for it — 2000 fresh one-key stores per flush had cost 2000 weak-map insertions and ran at 2× `next` (CodSpeed's `fresh stores` bench). The two rare moves of a draft's backing mid-batch (a privatization, a draft over an adopted raw) are kept in small per-batch maps.
5 changes: 5 additions & 0 deletions .changeset/size-stores-on-l2-s3c.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Size audit (measurement branch): §40 S3c — projection verdict windows and family pending on L2; the promise-delivery readers by posture. A probe answered before the flush had a transaction re-runs at the seam even when a later read routed its pass into the verdict lane (`REACTIVE_PROBE_UNANSWERED`); a render effect already observing a derive's flight keeps pulling it on re-run (the frame's hold is not dropped with its flight still up); the post-pass family wake fires only for a flight this pass registered (#3181); a derive's rejection reaches its leaves' readers (`handleAsync` gains an `onError(error, pending)` seam; `errorFamily`). `wakeFamily` stamps leaves with the derive as a pending source and propagates through core's own `propagateStatus` (split out of `notifyStatus`): branch recovery stays pending through another path, pending render effects are held by the frame. A `refresh()` during a non-quiet flight does not launder the new question; a quiet flight's landing writes are quiet through their reveal on stores. `resolve`/`until`/`refresh`'s waiter deliver their own transaction's frame and, over a foreign hold, the committed view at its commit (#3482/#3490). The descriptor trap reads the backing the container's frame serves (#3706). Four pins re-ruled onto L2 / signal parity (plan §40.2): A22-3, #3662 step 1, #3585 never-resolving case, #3038 companion walk.
5 changes: 5 additions & 0 deletions .changeset/size-stores-qd-parity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

One provenance test for a derivation's landing and a written landing alike (`stale`); signal/store twin pins for the overlapping-actions and kanban shapes.
5 changes: 5 additions & 0 deletions .changeset/size-stores-qd-provenance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Optimistic stores: a landing is judged against the guess of the question it answers. Another action's landing beneath a guess is held beneath it (the truth for the commit), the guess keeps showing, and the guess's own landing judges it; an arrangement guess on a keyed list is re-based over the held truth by key (order from the guess, rows from the truth, new rows appended, rows the setter removed stay removed). Two overlapping list edits confirming out of order no longer snap back. A corrected lane that had shown keeps the runs it queued this round; a chained view's guess reverts against the inner store's live value.
5 changes: 5 additions & 0 deletions .changeset/size-stores-s1-plain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Stores on L2, S1: plain `createStore` returns (`snapshot`, `deep`, `storePath`, `isWrappable`, `markRaw`, `$TRACK`/`$TARGET`/`$PROXY`/`$RECORD`, `storeIsShallow`). A store is a tree of L2 nodes: one-literal slot nodes (`slotSignal`) for leaves, presence, deep witness and the container node — the `$TRACK` node given a value, whose staging is the pending backing, so the scheduler owns the backing's lifetime. Core: the slot-node sweep dispatch and the store commit hook; `_devWindows` becomes an observe-literal slot; `mapArray` reads `$TRACK` again. Derived stores, projections, reconcile and optimistic stores return on later steps.
5 changes: 5 additions & 0 deletions .changeset/size-stores-s2-holds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Stores on L2, S2: plain stores under holds. Every leaf read is core's `read()` (the hold rules — frame reads, joins, A28 — come from core, tracked or not); nodes are born from the two frames and held by the container's transaction only for keys the batch changed (#3706); structural reads take the container's frame; a setter's returned replacement is staged, not eager. Core: `read()`'s held arm now applies to untracked reads by a pass (a derivation of a held write is never published mainline — A29/A15).
5 changes: 5 additions & 0 deletions .changeset/size-stores-s3a-projections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Stores on L2, S3a: `createProjection`, `createStore(fn, seed)` and `reconcile` return. The firewall is projection-only and lives in the store: every read through a projection pulls the derive first (core `read()` of it — untracked when settled, so nothing subscribes to the derive; tracked while a flight is up, so readers observe it as a memo's would); pending propagates to leaf readers by core's own dependent rule and settles at the landing; a derive's continuation writes join its hold; the creation run commits directly; adoption is eager with the container node keeping the committed frame. Core: the self-registered-flight probe in `recompute` is restored (projection-only, carved by mistake); an untracked verdict read of an uninitialized pending node links its reader as `read()` does. Derived-store manual writes follow A34 rule B (re-pinned).
5 changes: 5 additions & 0 deletions .changeset/size-stores-s3b-held-derived.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Stores on L2, S3b: holds on derived stores. A pass reading a key a held batch left unchanged reads committed and holds no one (#3706); a mainline setter above a held adoption publishes mainline for the keys the hold did not change (#3688); a user write to a key whose staging is a held derivation becomes the draft's prior state and the hold re-derives over it (A34 (3), #3612 — `CONFIG_MANUAL_WRITE` discriminates a user's proposal from the derive's derivation).
5 changes: 5 additions & 0 deletions .changeset/size-stores-s4-optimistic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Stores on L2, S4: optimistic stores on lanes. A user write to an optimistic store is a guess on the written key's node (presence and container arrangement guesses alongside), shown under the action's hold, confirmed or corrected by a landing beneath it, dissolved at settle — no store-side layer or backup snapshots. The committed backing is never touched by a guess. Reads compose per key through the nodes; a guess over an in-flight derive stands in for the flight (A17). Chained views (`createOptimisticStore(base)`) keep their links on the inner store's truth. A user's `reconcile` on an optimistic family writes the draft. The optimistic machinery is late-bound: a plain store does not carry the lane layer. Core: a slot node's flight is its family's derive (`_slotFlight`); an untracked read inside lane work derives from the lane; a pass that joined a hold before its first lane read is re-derived on the screen; linked lanes are judged by `blocked`; a supersession resolves the lane's merged parent.
5 changes: 5 additions & 0 deletions .changeset/size-stores-s4-seam-trim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Store size pass after S4: the write override is a live binding (no accessor call on the `get` hot path); the optimistic draft and its set-aside staging live in the optimistic module; one predicate for the lane-view composition sites. Behavior unchanged.
5 changes: 5 additions & 0 deletions .changeset/size-stores-s5-affects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Stores on L2, S5: the store half of `affects()` — `affects(store)` marks the record's carrier and every live node under it, `affects(record, key)` the slot's leaf; coverage by raw identity (captured proxies, chained views, cross-family raws), nodes born in the window inherit the mark, untracked probes are witnessed. Ambient marks whose flush parks join its transaction; one over a node whose own flight is up (a declared reload) lives to the landing. `StoreNode` is exported again (the L2 target's shape).
5 changes: 5 additions & 0 deletions .changeset/size-stores-su-utils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/signals": patch
---

Stores on L2, S-U: `merge`/`omit` and the merge/omit view machinery (`utils.ts`) are back unchanged; the carve has no stubs left.
Loading
Loading