Repository navigation
@solidjs/signals@2.0.0-rc.21
Pre-releasePatch Changes
-
f509fe3: Avoid evaluating property getters when attribution compares memo outputs and list items for unstable identity diagnostics.
-
46ab2dd: Dev diagnostic
CAUGHT_REACTIVE_READ(D-42 / S-47): warns once per computation when a reactive read's throw —NotReadyErroror the source's error — was caught inside the computation's body and the pass completed with a value. Anasynccomputation is judged when its flight settles (a rejection is the throw continuing; a landed value is the catch). The runtime's own catches (boundaries,isPending,watch, comparator/cleanup/effect-callback routing, solid-js's hydration trace) never warn. Dev-only; no production bytes. -
9379257:
deep()tracks and snapshots a plain store record in one walk instead of two. Records in a projection or optimistic family, chained stores and overlays keep the two walks. -
f17cd09:
deep()andsnapshot()read inside a computation now serve the frame the store's container node serves that computation. Before, a container held by a transaction (an action that wrote the store on both sides of a yield) always served its committed backing todeep()/snapshot(), even in the transaction's own landing flush, where the same computation's property reads already saw the landed values: a render effect readings.xanddeep(s)logged3:{"x":1}and was never re-run. The same applied to a derivedcreateStore(fn, seed)whose user setter wrote across a yield. Reads outside a computation still see the committed backing of a held container. -
65da5de: fix(signals):
defer: trueskips an effect's first run when a held update mounts it (#4543) -
689347f: fix(signals): a deferred effect mounted by a held update keeps its first value as the next pass's
prev(#4556) -
20c115c:
createStore(fn): a derive that went pending on a source and was settled without re-running (a staged rejection, or a re-ask that returned to the committed question) settles its readers with it, as a memo's would:isPendingends and a refetch's rejection reaches them. -
5315127: A derived store (
createStore(fn),createProjection,createOptimisticStore(fn)) hands an upstream error to its readers once: a re-run of the derive that meets the same error no longer re-runs a reader already showing it, so an effect's error arm runs once per error. -
ecf3011: A derived store's held rejection is staged like a memo's (D-41, #4489). While a hold is open — an action holding a filter change behind a pending guess, or any transition — an untracked read of the store (a click handler on a row the screen still shows) reads the screen instead of throwing the new error; the effect's error arm,
<Errored>and the read all see the error together at the reveal. Closes D-41's derived-store deviation (theit.failspin inerror-is-an-answer.test.tsnow passes asit). -
bb7f9b5:
createStore(fn)over alatest()-reading memo shows an action's value as the memo does: a derive pass that is a lane's work writes its leaves as that lane's derivation instead of staging them with the action. -
64fedc7: A reader of a derived store that mounts while the derive's input is in flight is held until it answers, as a reader of the async memo is, instead of showing the previous answer first:
createStore(d => { d.v = m1() })over a memo that readslatest(), read mid-flight, no longer shows the old question's value before the new one (#4491). -
e49b0c7: A sync derived store over a failing sync memo hands each new error to its readers once per flush, not twice: the error a source propagates to the derive now reaches the family's dedupe.
-
6af149e: A write that a custom
equalscalls equal to the committed value now nets to it (D-8) while another write to the signal is staged, so it pends nothing (#4483). -
19e0951: An error boundary no longer hands its reader an error that was superseded inside the same transition (#4527). Here is the case: an action keeps its transition open, the store's re-ask is rejected (that rejection is staged, D-41), and a second re-ask answers before the commit. An effect whose compute created
createErrorBoundary(() => store, …)used to get the fallback at the commit and never ran again. Now it gets the answer, as the screen does.Two changes make that work. First, a pass that a derived store's pull throws a staged error into is now linked to the store's derive, including the untracked shape probe of a returned proxy. That way the re-ask and the answer that supersede the error reach the memo. Second, an error boundary no longer waits for first content: one that has not shown content reveals a recovery that lands in the hold it caught the error in together with that hold's commit, instead of keeping its fallback past it.
-
dd5f9d1: An
<Errored>heals once no reader it caught still reads the failed source, instead of staying on its fallback after navigating to another branch (#4644). This covers an error read only by memos (a<Show>/<Match>condition), and a source something outside the boundary still reads: a hoisted memo, a derived store or projection, a reader under another<Errored>. -
ecf3011: An error boundary that a held pass mounts over a source whose error is staged in that hold (D-41) no longer loops the flush for good (#4480). The seam's fold-back of a fallback staged into the hold its readers landed in (D-16, U-9) is a loading boundary's: it also cleared an error boundary's readers, so the output re-derived into the staged error every round and the effect owning the boundary re-ran on each new output. The error now waits with the hold and its fallback reveals with the frame (D-41, F-12). Seen with a derived optimistic store whose re-ask failed while a guess was pending, read by an effect through
createErrorBoundary. -
39f951b: A rejection under a
<Loading>that has not shown its content reaches<Errored>at once when alatest()reader under the same boundary reads a derivation whose upstream still has a flight out for an older question (#4568). The boundary judged its readers settled while thatlatest()reader was queued to re-derive, revealed into a hold the reader then went pending in, and the later rejection was staged in that hold until the obsolete flight landed. A verdict reader queued to re-derive is now waited on until its pass answers (A19, D-41). -
3a73a36: An
<Errored>boundary over a list no longer reveals the list from before the error when the error's replacement lands held with an action (a guess on the errored store re-asked it): the error stays until that action's frame reveals, instead of showing the previous question's rows. -
ceb7896: A memo over an error boundary's output no longer halts when the boundary's source rejects during a held change: the boundary shows its fallback, as it does when a render effect reads the output directly (#4640).
-
4235019: An
<Errored>recovery re-arms its subtree: every<Loading>under an error fallback counts as not shown, so on recovery it catches what is still pending in the replacement frame and shows its fallback beside the recovered content, instead of the error staying up until the nested content is ready (#4627). -
a56b10b:
<Errored>no longer recovers beside a memo that is still answering an older input (#4592). While the error fallback shows, a reader behind it that goes pending — which passes the error boundary by (A6) and, hidden, holds nothing — is now also waited on by the boundary, as a pending under a hidden loading fallback already was. When the source that threw answers but another reader in the content is still asking for the new input, the error stays the display until that reader answers too, so the content reveals as one whole frame instead of showing the pending memo's stale value beside the new input (D-39, F-1). -
b773146: A
Loading/Erroredfallback is born held only when the boundary's output pass that builds it read the hold (D-27), no longer by the flag of the enclosing pass it is parented under (#4428). -
343f007: A memo whose verdict posture is only inherited (it reads a memo that calls
isPending/latest, and probes nothing itself) is the hold's work where it reads the hold's own write: it reads that staging instead of the pre-hold value, so a branch the hold opens no longer reads the pre-hold world and the hold lands, whether the writes go through oneflush()or several. A memo that probes in its own body still reads the screen, and what a branch born into the hold then asks for no longer keeps the hold from landing (#4544). -
ab3e844: A derived store heals with its Errored like the memo it derives from (#4451). A leaf born from a lane container's staging — a derive's lane-pass write to a key nobody had read yet — takes the staging as the lane's derivation, as the write would have left a leaf that existed then; before, the leaf was born a plain staging the park held with the frame, and an Errored the memo's lane value healed stayed on its fallback over the store.
-
87f3446: Clear the settled source at
propagateStatus's verdict re-derive shortcut: a verdict reader (isPending/latest) whose probed source errored kept that source in its pending set, so when its re-run parked on a second source, that source's landing left the reader pending forever (and aLoadingboundary over it never released). -
62745f6: Shrink the compiled and hand-written floors: the dependent walks, dependency clearing, status writes, effect-run queueing, flatten's thunk walk and the delegated-event parent hop share their code (no behavior change).
-
4a4803c: A derived store (or memo) reading a keyed optimistic store through
latest()now picks up a confirmed row after a correction folded the truth beneath the guess: a confirming truth landing re-derives thelatest()readers too. -
6ec1613: fix(signals): a guess over a question in flight keeps the frame whole when a memo, or a chain of derivations, sits between the list and its binding — the guess shows (#4561)
-
d9aa8f7: A keyed optimistic store's arrangement guess written while its derive asks a new question (an input changed, not a
refresh()) is re-based over that question's answer, like an older truth (#4525). Before, the answer folded beneath the guess, so the rows the guess had only carried over from the old answer stayed on screen; under<Loading on={filter()}>the region left its fallback showing the new input beside the old list minus the guess until the action's refresh landed. -
60d6307: A render effect in a branch an action holds (
<Show when={y() > 0}>opened by the action's write) no longer runs ahead of that branch's landing when it readslatest(y)inline, while the same read through a memo waited: a member of the frame a held pass built is the hold's own work, so neither form seats it as the hold's verdict reader, and memo wrapping no longer changes what it shows. -
7135a77: A verdict memo (
createMemo(() => isPending(x)), the router'suseIsRouting) whose probe ran before its flush joined a transaction now showstruewhile that transaction is held, instead offalseuntil it lands (#4439). -
592a43b: A keyed child under a display-ahead branch no longer mounts a third time when a flush parks: a re-derive that gives back the staging it superseded keeps its held readers and their children (#4417). A display-ahead branch no longer attaches with an empty text hole while a child born into the open hold is still pending (#4574).
-
2ba429b: A lane member disposed before its lane dissolves no longer runs again (#4613). When an action's commit disposed a region whose list was still the action's lane work (e.g. a keyed
<For each={[filter()]}>region swapped by a filter change held with the action), dissolving the lane re-queued the dead list memo; its pass dropped the disposed flag, so it mapped rows in the torn-down region, stayed subscribed, and dev loggedRUN_WITH_DISPOSED_OWNER. A disposed reader is no reader (F-3, D-11): dissolution now skips it. -
c8d6fd2: A landing that settles a reader held by an optimistic lane no longer makes the flush join that lane as its transaction: rows a list guess mounted over a pending refresh render instead of staying empty.
-
64625bc: fix(signals): effects an optimistic guess mounts honor
deferand run once per write (#4557) -
2ba10bd: An async memo over two verdict memos asks each question once, and a lane's readers show its answer together (#4408, #4399; F-6, F-9, D-25, D-26).
- An async memo with no verdict window of its own that waits on a source's flight as the hold's work (
holdWork) drops its verdict posture at the wait, so the source's verdict-lane re-derive does not move it into that lane early, and the pass the landing runs reads plainly. Before,latest(m2)showedc1101whilem1:1122of the same lane was still in flight. - A held memo's pass that re-entered its hold at its head stays that hold's work when it reads another hold's verdict lane, in either read order. Before, moved into the other lane, it read its own hold's landing as the screen and asked
m1:15a second time. - A memo with a committed value and no pass staged keeps the verdict posture it reads when a pass of it reads that verdict memo while it is pending (#4408 after #4504; D-25). #4504's rule — a pending read hands on no posture — stays for the hold's own work: a pass born in the hold's world, or one over a staged pass of its own. Before,
m2 = m0b() + 1lost its posture at such a read, re-ran plainly into the framem0b's answer landed in, andlatest(m2)showedc1101beforev1122.
- An async memo with no verdict window of its own that waits on a source's flight as the hold's work (
-
8cac5f0: fix(signals): lane work re-based over a held change's answer reads that change's world in every flush and is not re-derived on the committed world while it is parked, so a refresh or a second entangled change no longer commits a derivation over the old inputs beside the new ones, and the held change lands once its last async answers (#4576, #4577)
-
42924f4: A pass that reads
latest(m)and thenisPending(m)of an unheld refetch outside anyLoadingno longer loops ("Potential Infinite Loop Detected"): thelatestread opened the flush's transaction for nothing held, the probe asked to re-run at that transaction's landing, and every re-run opened another. The probe now joins the verdict lane without asking for that re-run; the reader shows the committed value besidetrue, then the refetch's answer. -
9c4e4a8: The transaction a
latest()read of an unheld refetch opens is no longer kept alive after it lands: the mark that it was opened bylatestlives on the transaction itself instead of in a module-level reference. -
edd3c44: A memo pulled inside
latest()now computes as its own pass (A31): anisPending()it calls answers for what it reads, so a held write still in flight reads as pending there as it does when a plain read pulls the memo (D-23). -
77be406: fix(signals):
latest()andisPending()in a hydration claim read the server's snapshot, as a plain read does, so a client write during the hydration window no longer puts a nested<Loading on>into a fallback the server never rendered (a "Hydration key miss") (#4570) -
061b013: A memo whose last run read
latest(x)no longer holds a<Loading on>switch whilex's new flight is up: its read of the switch's own write is the screen's, and a flight it reads only insidelatest()is one it reads ahead of (F-6). The fallback shows at once; the memo keeps its committed value until the flight lands (#4661). -
d9a97d0: The
UNSTABLE_LIST_IDENTITYdiagnostic reads a row'sid/key/_idonly from an own data property, so it never invokes a getter (a class instance's prototypeidor an own accessor) while pairing rows. -
6e569c7: A
<Loading on>re-arm whose content reads its async through an error boundary built outside the<Loading>shows its fallback with the change's frame again, beside a sibling re-armed boundary (#4638). A pending error-boundary output read only behind fallbacks no longer holds the frame. -
f53d927: An error boundary output read only behind fallbacks now holds nothing when it reaches them through a memo or another error boundary built outside the
<Loading>, or is not read at all;LOADING_ON_OUTSIDE_HOLDno longer fires while the re-armed fallback is on screen. -
97e1826: A
<Loading>that has not shown content no longer reveals content derived from a write still held outside it (F-7, F-1). Two reveals did not consult the hold: a first load the held write re-asked (kept out of every hold, #2937) landed mainline and revealed its answer beside a screen still showing the frame before the write (#4593); and a reader settled by an answer staged in the hold — a rejection, which marks no frame reader (D-41) — revealed the content's stale committed value under a re-armedonboundary and let the held write commit early (#4591). The boundary now waits on the held node and reveals with that hold's commit; the rejection shows when a value for the same question would. A first load re-asked under an open action still reveals at its landing (#2937). -
eed4469:
mapArrayand<For>with akeyedfunction orkeyed: falseno longer callsetSignalfor a row whose signal already holds the new item and has no staged write. Before, every retained row in the common prefix and suffix was written on every list update. -
71a6a75: A memo between a render effect and an async memo in flight is born held with the mount that first reads it (#4504, D-2, D-22, D-27). With an input that reads
latest()/isPending(), the memo carried that verdict posture by what it read (D-25), and its pass in a plain mount mid-flight stamped the posture from the read of the pending async memo even though the read threw: at the landing the memo re-ran as a verdict reader and was served the async memo's committed value, so the held reader showed the old answer at the landing and the new one only at the commit (r:2, thenr:4). A read of a pending node now hands on no posture to a pass that is not a verdict reader already: the reader waits for the re-ask's answer and shows it once (r:4), as when it reads the async memo directly. A memo that was already a verdict reader on screen keeps its posture. -
2abf27d: A signal written and written back to its committed value in one tick (D-8, #4452) is no longer read as a staged value by a labelled
untrackread in dev, which took the slow read path and held what prod did not. The reader-seat shadow's table gains theD1''/L1''/V3''rows for that read (test-only), clearing theINV-seat-3"world after the read" classes onnext(8 in the signals suite, 7 in web, 60 in the generator). -
b5077ea: Writes that net to a signal's committed value in the tick an action opens a hold no longer pend the signal: a render effect reading
isPending(s)showsfalseduring the hold and is not re-run when the action lands (D-8). -
5315127:
createOptimisticStore(fn)delivers the error of an upstream memo its derive reads, ascreateStore(fn)does: the optimistic store now builds its family through the projection's own constructor. -
4f9768f: Fix an infinite flush loop when a memo over an optimistic store list (an "N left" count, a filter) read through a lane re-based over a parked refresh (#4643). Lane work re-based over a hold's answer no longer joins the flush into that hold, so a plain write beside it (a filter change) shows once instead of showing, retracting and showing again, and a guess beside the held answer no longer reveals it early. A push after a removal guess no longer leaves an
undefinedrow in the list. -
227a01d: Optimistic keyed lists: a push after a filter (with earlier saves still out) no longer hands
<For>anundefinedrow; a guess written while an earlier action'srefresh()is out shows at once instead of waiting for that refresh; a refresh landing older than a guess no longer brings back a row another pending guess removed; and an unkeyed list's guess written after a correction composes on what the screen shows, not on the truth beneath it (no duplicated, empty or missing rows).New DEV diagnostic
OPTIMISTIC_WRITE_BEFORE_LOAD: an optimistic write to a source whose first answer has not landed (createOptimistic(async fn),createOptimisticStore(fn, seed)) throws in development and makes no guess — before its first answer the source is loading, not a value to be optimistic over. Keep pending items in a separate list until the source loads, or disable the action until then. Production behaviour is unchanged. -
5f07d04:
createOptimisticStore: a row removed by an accepted action no longer comes back when its refresh lands while another removal is pending; each re-base of an arrangement guess composes from the rows the setter wrote. -
ecf3011: A keyed optimistic store's removal guess re-based over a new question's answer no longer shows the old list's rows beside the new ones (#4482). The re-base (D-35) kept every guessed row the new truth lacked, including the rows the guess had only carried over from the truth it was written on; it now composes the guess's own edit — the rows it added or carried from another action's guess, minus the rows it removed — over the new truth, and takes the rest from that truth (F-1).
-
885b99b: A second action's guess into an optimistic slot now shows at once while the first action's
refresh()of a list the overlay also reads is still in flight, whatever order the overlay reads the two in, and whether it reads the guess directly or through a memo derived from it (#4629). -
ab5b5cb: An optimistic guess into a second
createOptimisticlog shows at once while another action'srefresh()is in flight over the list both read (#4666). A reader held by that action's hold is seated in the new guess's lane when every flight it waits on is a re-ask (D-34 ¶3, F-11); one pending on a new question stays held (#4577). The same holds when that log already carries another action's guess whose lane has shown: a render effect reading the overlay now re-runs at that lane's reveal instead of waiting with the refresh's hold. -
9034647: In the production build,
getContext(and souseContext) with no owner now reads as if under an empty root: it returns the context's default, and throwsContextNotFoundErrorwhen there is none. Before, it threwNoOwnerErroreven when the context had a default, so a component created outside any owner (JSX at module scope, in a timer or event handler, or after anawait) crashed in production while dev and observe, whosecreateComponentruns each component in a root, returned the default. Dev still throwsNoOwnerErrorfor a bare read with no owner. Reads under an owner are unchanged. -
efd7f7d: A projection's adopted leaves (
lengthamong them) written by a lane's pass are the lane's derivation, as its container is: a row closed through an optimistic filter while a truth landing was held beneath another guess no longer stays on screen (or reads asundefined) (#4631). A second guess made while an earlier action's re-ask is in flight now shows through a keyed projection when that re-ask lands, as it does through the memo (#4629). -
25b94f0: A reader of a derived store whose derive carries a staged error (D-41) now links to the derive, as a reader of a pending or errored one does, so it re-runs when the derive's source answers. An
<Errored>mounted in the change that errored its content over a keyedcreateProjectionshowed its fallback for good; it now shows the answer. -
e704cfc: A store whose own
__proto__data is removed — byreconcile, a setter'sdelete, or a projection — now readsundefined, as a store that never had it does, for tracked and untracked readers alike (#4672, core R30). The key's node used to be told the backing's inherited value, so the read servedObject.prototypewrapped as a store. Tracked readers are notified of the change;__proto__assignment stays inert. -
e56a4a0: Reader seat S1 M1 (test-only): the shadow seat and slot table (
core/seat.ts,__TEST__) re-baselined against currentnext— the verdict seat (vhold), the branch world (creatorsWorld) and the owed table rows (V1'' staged error, Vl4', D8, lane rows for a boundary's structure,fallback's bracketed read) modelled,INV-seat-1amended per D-27, and ashadowKnownallow-list naming the filednextbugs (#4426, #4427, #4428, #4429). No change to any build output. -
e56a4a0: Reader seat shadow (test-only): a new
core/seat.tscomputes the reader seat and slot table beside the existing deciders under__TEST__, with theINV-seatfamily recording disagreements for the differential. No change to any build output. -
8a8e950: fix(signals): a guess re-based over a question's answer stays off the screen while that question's transaction is parked on another read, so the old question never shows beside the new answer's rows (#4559)
-
74126b1: A memo on the observation lifecycle (unowned, or
lazy: true) that blocked on an async source is no longer released before the retry its source's landing queued (#4474). The settle walk re-enqueues the blocked reader and, finding it unobserved, released it on the spot: the release pulled the retry back out of the heap, so the memo never computed the landing and woke later with no value —latest()of it returnedundefinedbesideisPending() === true. The release now waits for that pass (REACTIVE_RELEASE_AFTER): the retry runs once, as the owned twin's does, and the node is released at the pass's tail if it is still unobserved and settled. #2934's contract is kept (no perpetual recompute — one pass, then the release), #3078's untouched (reads revive; a dormant memo dirtied in the same tick is still reclaimed before the heap). Laziness is never observable (D-22). -
2c9a1e3: fix(signals): a re-parked node drops pending sources its pass no longer reaches, so a
<Loading>whose first answer was superseded while a sibling refetched reveals once both settle (#4541) -
718ec9c: Keep observing a pending store query when a later optimistic guess re-runs an existing reader, so bindings (shared or separate) do not show the new query's inputs beside rows from the previous answer, and the new answer's rows never show beside the old query for a frame when it lands.
-
643a7a7: An async memo's first answer that resolves in the same tick as a plain write re-asking it is answered, then re-asked (D-22, F-9):
isPendingof it istruewhile the new question flies, and an identity memo or derived store over it reads the answer throughlatestlike the memo itself. -
fda83a3: A chain's verdict no longer flips to
falsemid-hold where a diamond's staystrue(#4562). When a superseded flight's error is staged in a hold (D-41), the settle walk now marks every derivation it fully settles with the staging, not only a join it reaches a second time, soisPendingstaystrueuntil the commit whatever the graph shape (F-9, F-2). The mark moved behind the verdict engine's hooks (installVerdictHooks), so builds withoutisPending/latestcarry none of it. -
84353de: A non-keyed
<Show>'s or<Match>'s narrowed accessor read inside anisPending()thunk no longer throws the stale-value error for a branch that mounted in the flush its condition landed in, so the thunk's later reads link and the verdict flips (#4648). The exemption holds only inside a verdict window (isPending/latest): a plain read of the accessor while its branch's opening is held still throws, rather than hand out the committed falsy. -
f0471e8: Internal: the snapshot walk drops a redundant overlay guard before materializing a pending backing (
materializePBalready returns the backing unchanged without an overlay). No behavior change. -
66c6f56: Writes that net to a signal's committed value in one tick no longer hold an errored memo's re-run with an action, so
isPendingof it staysfalse(D-8). -
749b0d7: A memo's error staged with a hold now reaches the memos and derived stores that derive from it:
latest()of them throws the proposed error andisPending()of them istrueuntil the hold commits, as for the memo itself (D-41). -
404d06a: fix(signals): a re-pass equal to a first value already staged this flush is not a change, so a non-keyed
Showover an async condition no longer remounts its child when the child writes the source on mount (#4540) -
50dec1b: Preserve signed zero and pending-state atomicity when a derivation reads a staged signal write accepted by a custom comparator.
-
456e6d5: Store proxies wrap an empty object (an empty array for array stores) and use the store's internal target as their handler. V8 checks every trap result against the proxy target's own keys, so key listing,
for...inand spread on stores get faster.Object.freeze,Object.preventExtensionsandObject.setPrototypeOfon a store now throw a TypeError instead of breaking it. -
e44f824: Smaller store bundles: the store family field (
_fam) and its_overlaid,_asked,_wokeand_shallowfields are now_-prefixed internals, so the prod and observe builds mangle them (no behavior change). -
d5cf231: A store proxy over an array subclass or a class instance keeps the source's prototype:
instanceof,Object.getPrototypeOfand.constructoranswer as they do on the source, also after a write and in a projection's derive (#4670). Reading an inheritedconstructoron a draft still returnsundefined(the prototype pollution guard). -
ecf3011: A derived store's writes after an
awaitno longer leak into the next user setter (#4484). A write-override write (the derive's continuation) notifies its target at once but left it listed for notification, so the next outermost store setter — on any store — notified the derive's staged landing as its own write; on an optimistic family that made the landing a guess over a pending one, and a pending removal guess showed its row again when another action guessed on a different store. An outermost setter now starts with no stale targets (F-11, D-33). -
7ea8706: A
createTrackedEffectnow re-runs for a same-pass write it reads through a memo (#4606), and for an action's landing when it re-ran during the transition for another dependency (#4607). A memo the run's own read pulls stages its value while the run recomputes, so its subscriber walk woke nobody; the run now re-queues for any memo dependency staged with a different value, as it does for a signal written before the run (#4598). A run during a hold is served the committed value of the held dependency and had consumed the run the landing replays; it now queues one run with that hold's stashed runs, so it re-runs at the landing as a stale reader would (A15), without holding the transaction open (D-29). A tracked effect that writes a signal and then reads a memo of it re-runs once the write commits, as one that reads the memo first already did. -
aeca8da: A
createTrackedEffectwhose first run reads a signal written earlier in the same effect phase (another effect's first run, a parent'sonSettledwriting a prop) now re-runs once the write commits, ascreateEffect(compute, fn)does (#4598). A tracked effect reads the committed value and links its dependencies in the effect phase, after the write had already walked the signal's subscribers, so the commit at the next seam notified nobody. After a tracked effect's run, a dependency staged this flush whose subscriber walk predates the run queues the effect again for the round that commits it; writes that net to the committed value stage no change and queue nothing. The pass's own write-then-read is still never observed and never re-runs (#3006), andonSettledstays one-shot. -
ef0aadd: Two or more async memos whose answers resolve in the same tick as a plain write re-asking them are all answered, then re-asked (D-22, #4495): a memo over them reads every answer through
latestand is pending on the re-ask. An earlier landing's flush no longer re-asks the others before their answers arrive, dropping them. -
d0fc285:
createStore(fn)that nothing reads no longer holds a plain write with its derive's flight: a derive over alatest()-reading memo observed the flight as a frame reader although its store had no reader. -
62bf4c4: fix(signals): a pending memo nothing reads no longer holds a fresh
<Loading>when its subtree mounts under a held update (#4542) -
f8080f3: Dev: in a component body, a plain
untrack(fn)that reads a pending async memo created in that same body now throwsPENDING_ASYNC_UNTRACKED_READ, as a direct read does. Before,untrackcleared the check: the read threwNotReadyErrorto<Loading>, which re-ran the body onto a fresh pending memo forever, and the page froze. An untracked read of a memo created outside the body still reaches the boundary (D-23), sync untracked reads stay quiet, anduntrack(fn, false)opts out. Production is unchanged. -
663ecb0: A memo born into a hold that reads
latest()in its pass (for example by calling a function aLoadingfallback returned) no longer mounts thatLoadingagain and again once the content lands. The memo's re-run is still the hold's own work, so it joins the hold whatever it asked before (D-25), and the boundary it mounts belongs to the hold and appears at its commit (D-13): the screen goes straight to the content. -
2e05808: A verdict reader born into a hold reads that hold's value of a node it holds in every flush, not only the hold's own: one run by another transaction's flush was served the committed value (#4426).
-
1445197:
isPending()read untracked inside a pass reads what the pass's plain read does in a normal flush — the flush's staging — so a pass never settles on the old value beside the new one. Inside a hold it still reads the committed value, but it is final in the hold's frame (nevertruebeside the fresh value), and the pass re-derives on the landed world before the hold's held runs show, so the hold ends with one frame — whether the pass was re-run while the hold was up, first read the held node in a later flush, or probed only in the flush that staged the write. A probe of a first value staged in the current flush (a narrowed<Show>/<Match>accessor in its landing flush) reads that value instead ofundefined(#4648). -
ab3d2ad: A memo pulled inside
isPending()now computes as its own pass (A31): the probe's state no longer leaks into it, so alatest()it calls doesn't join the hold through the probe, and its reads don't answer the outerisPending(#4429). -
131ceb8: A render effect seated as a hold's verdict reader no longer leaves the seat when it reads a verdict lane of a transaction merged into that hold: the merged transaction's lane is the same hold's, read as the lane's value and shown with it (#4427).