Repository navigation
Release RC packages (rc) - #4443
Open
github-actions[bot] wants to merge 1 commit into
Open
github-actions[bot] wants to merge 1 commit into
github-actions[bot] wants to merge 1 commit into
Conversation
github-actions
Bot
force-pushed
the
changeset-release/next
branch
30 times, most recently
from
October 30, 2026 17:51
2ba36f7 to
ad7fd1e
Compare
github-actions
Bot
force-pushed
the
changeset-release/next
branch
29 times, most recently
from
November 1, 2026 00:11
90f5a4c to
e45d44c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated.
nextis currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, runchangeset pre exitonnext.Releases
@solidjs/babel-plugin@2.0.0-rc.21
Patch Changes
if,elseor loop body.if (c) return <span>{x.join()}</span>;emitted the template clone andinsertbefore theif, so they ran (andx.join()threw) whencwas false, a loop body's setup read its loop variable out of scope, and a hydratinggetNextElementclaimed a node for a branch not taken. The setup is now inserted before thereturn, and Babel wraps the body in a block.@solidjs/diagnostics@2.0.0-rc.21
Patch Changes
@solidjs/element@2.0.0-rc.21
Patch Changes
@solidjs/h@2.0.0-rc.21
Patch Changes
classon a tag with static classes no longer throws "Invalid property descriptor". A component that forwards its props to a selector-class element (props => h("button.btn", props)) and is given a reactiveclassreceived it as a getter, and merging it with the static classes built a descriptor with bothgetandvalue. The getter is now read through the props object, so the merged class keeps the static classes and stays reactive.@solidjs/html@2.0.0-rc.21
Patch Changes
@solidjs/signals@2.0.0-rc.21
Patch 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 (2.0.0-rc.20: createEffect({ defer: true }) runs its first time when it was created under a held update #4543)689347f: fix(signals): a deferred effect mounted by a held update keeps its first value as the next pass's
prev(Deferred effect's compute sees prev=undefined on a held mount, prev=1 on a plain mount #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, [2.0 / next] createOptimisticStore: while an action holds the view, a handler reading a row the screen still shows throws the store's new error #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 ([2.0 / next] A reader that mounts while an unread derived store's flight is up shows the old question's answer (D-30, F-2) #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 (Writes that net under a customequalsstill pend (D-8) #4483).19e0951: An error boundary no longer hands its reader an error that was superseded inside the same transition ([2.0 / next] createErrorBoundary read in an effect hands the effect a superseded error when an action's transition commits #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.
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 ([2.0 / next] Infinite flush when a derived optimistic store's re-ask fails while a guess is pending and an effect reads the store through createErrorBoundary #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 ([2.0 / next] A rejection never reaches <Errored> while a latest() reader under the same unrevealed <Loading> waits on an obsolete flight #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.a56b10b:
<Errored>no longer recovers beside a memo that is still answering an older input ([2.0 / next] <Errored> recovery shows a pending memo's answer to an older input beside the new 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 ([2.0 / next] born-held asks the owner-context pass, the world asks the running passes — the two part under runWithOwner (fallback's b._fb) #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 (2.0.0-rc.20: a memo that calls isPending()/latest() on an unrelated signal makes a branch opened by a held update read the pre-hold world; <Loading> never settles #4544).ab3e844: A derived store heals with its Errored like the memo it derives from (Derived store (E3) stays on an error fallback the memo form heals — uncovered by the #4425 fix (async-gen 3289 #36981, 7 #46850) #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 (Optimistic guess tears when a memo sits between the keyed list and its binding #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 ([2.0 / next]<Loading on>shows the old answer under the new input when a guess is made while the input change is pending #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 ([2.0 rc.20] useIsRouting() stays false through a held navigation when an effect tracks it and a <Show when={latest(x)}> exists (regression from #4356) #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 ([2.0 / next] A keyed Show on latest() of a staged write mounts its child twice when the flush parks (regressed by #4393) #4417). A display-ahead branch no longer attaches with an empty text hole while a child born into the open hold is still pending ([2.0 / next] A display-ahead <Show> opened under a plain write's hold attaches its branch with an empty text hole until the landing (S-46, F-2) #4574).
2ba429b: A lane member disposed before its lane dissolves no longer runs again ([2.0 / next] dev warning RUN_WITH_DISPOSED_OWNER from inside
<For>when a keyed region is replaced after an action held its input change #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 (Effects mounted inside an optimistic lane ignore defer and run twice on a later write #4557)2ba10bd: An async memo over two verdict memos asks each question once, and a lane's readers show its answer together ([2.0 / next] latest(m2) reveals a lane's answer while m1 of the same lane is still in flight (F-6) #4408, 2.0: an async memo over two held verdict sources asks the same lane question twice #4399; F-6, F-9, D-25, D-26).
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.m1:15a second time.m2 = m0b() + 1lost its posture at such a read, re-ran plainly into the framem0b's answer landed in, andlatest(m2)showedc1101beforev1122.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 ([2.0] Filter change never commits when a shared async memo's other flight lands after an optimistic action's refresh #4576, [2.0] Filter change never commits when a second async memo reads the optimistically guessed list #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") ([2.0 / next] Hydration: a write during the hydration window re-arms a nested <Loading on>, whose fallback is claimed (Hydration key miss) #4570)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.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, 2.0.0-beta | The curious case of a deadlock #2937) landed mainline and revealed its answer beside a screen still showing the frame before the write ([2.0 / next] A first-load <Loading> reveals content for a write still held outside it (F-7) #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 ([2.0 / next] A rejection under an armed <Loading on> reveals a stale value and commits a write held outside it #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 (2.0.0-beta | The curious case of a deadlock #2937).71a6a75: A memo between a render effect and an async memo in flight is born held with the mount that first reads it (A memo over a re-asked async memo, first read mid-flight, shows the old answer when the input reads latest() #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, fix(signals): writes that net to the committed value hold no errored re-run #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.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 ([2.0 / next] createOptimisticStore: a removal guess re-based over a new question's answer shows the old list's rows next to 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).
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.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.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 ([2.0 / next] A verdict reader born into a hold T, run by another transaction's flush, is served the screen it was just ruled not to have (frameRead vs stagedScreen bornInto) #4426, [2.0 / next] laneRead's D-28 verdict-seat reset compares verdict lanes by identity; a merged transaction's lane reads as another hold's #4427, [2.0 / next] born-held asks the owner-context pass, the world asks the running passes — the two part under runWithOwner (fallback's b._fb) #4428, [2.0 / next]probingleaks into a memo's pass pulled insideisPending— a nestedlatest()joins the pass to the hold #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 (Optimistic guess tears when the question's transaction is parked on another async read #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 (latest() of an unread identity memo returns undefined when first read in the flush that re-asks its source #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. [signals 2.0 beta.25] Autodispose leak: derivatively-pending lazy memo is never released after losing its last subscriber (recomputes forever) #2934's contract is kept (no perpetual recompute — one pass, then the release), 2.0.0-rc.3 | didn't get the memo (isPendingmemo reads inconsistently in a transition) #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 (2.0.0-rc.20: <Loading> stays on its fallback forever when an async memo's first answer is superseded while a sibling under the same boundary refetches #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(signals: a chain's verdict flips to false mid-hold where a diamond's stays true (graph shape is observable) #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.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 (2.0.0-rc.20: a non-keyed <Show> remounts its children in a loop when the condition reads an async memo/projection and a 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.
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).ecf3011: A derived store's writes after an
awaitno longer leak into the next user setter ([2.0 / next] createOptimisticStore: a pending removal guess is dropped from the screen when another action guesses on a different store #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 ([2.0 / next] createTrackedEffect misses 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 ([2.0 / next] createTrackedEffect never re-runs for an action's landing when it re-ran during the transition #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 (2.0.0-rc.20: createTrackedEffect never re-runs when a dependency is written earlier in the same effect pass #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 (2.0.0-rc.20: createTrackedEffect never re-runs when a dependency is written earlier in the same effect pass #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 (2.0.0-rc.0 | royal flush - inconsistent read/write in onSettled #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, 2.0: two async sources answered and re-asked in one tick: the second answer is dropped, latest() of their memo throws #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 (2.0.0-rc.20: a pending async memo that nothing reads holds an outer <Loading> forever when the subtree is mounted under a held update #4542)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 ([2.0 / next] A verdict reader born into a hold T, run by another transaction's flush, is served the screen it was just ruled not to have (frameRead vs stagedScreen bornInto) #4426).
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([2.0 / next]probingleaks into a memo's pass pulled insideisPending— a nestedlatest()joins the pass to the hold #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 ([2.0 / next] laneRead's D-28 verdict-seat reset compares verdict lanes by identity; a merged transaction's lane reads as another hold's #4427).
solid-js@2.0.0-rc.21
Patch Changes
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.createOwnerleaves solid-js's public types: it is typed only throughsolid-js/internal, like the boundary primitives behindErrored,LoadingandReveal(solid-js types: index.d.ts re-exports createErrorBoundary, createLoadingBoundary and createRevealOrder, which hydration.d.ts strips as @internal #3709). It stays a runtime export for the renderers. Solid 1.x had nocreateOwner, and application code that used it in an RC should host a scope withcreateRoot()(itsdisposeargument can be passed around as a plain function) and re-enter one withrunWithOwner(). A detachedowner.disposekeeps throwing, since it is a method and not part of the public API ([2.0.0-rc.19] errors disposingcreateRenderEffectin a microtask after creation. #4444).<Errored>fallback (Hydrated Errored fallback ignores a content-input write made before the streamed chunks arrive #4588)_frresolution chunk is lost (host truncates stream) — plus_$HY.feis never implemented #2958). The truncation sweep only armed whenhydrate()ran whiledocument.readyStatewas still"loading". An entry that ran later, such as one waiting on a route module that arrives afterDOMContentLoaded, or a deferred module entry, left every unsettled_frdeclaration pending, so its<Loading>kept the fallback and hydration never ended. When the document carries the in-render bootstrap (<HydrationScript />, which declares_$HY.s), a runtime that boots after parsing now runs the same sweep at boot: the records that can no longer settle leave the registry, the cut fragments are rejected, and a macrotask later the refs a keyed consumer already took are rejected. Documents with a host-placed bootstrap (generateHydrationScript()) are unchanged.@solidjs/universal@2.0.0-rc.21
Patch Changes
@solidjs/web@2.0.0-rc.21
Patch Changes
useHeadstylesheet under<Loading>) warmed the same registry entry and waited on that element's load, and the removal took the element out before it loaded. A removed link fires neither load nor error, so the boundary stayed on its fallback. The removal now settles a pending load the way an error does, and the gate warms the sheet again on a new element and waits on that one.AssetManifestadmits a manifest that sets_base(2.0: AssetManifest type rejects a manifest that sets _base #4502). It wasRecord<string, Entry> & { _base?: string }, and since_basealso falls under the string index signature it had to be an entry too, so a manifest literal with_base: "/"did not type-check. The index signature now carries entries, metadata strings (_base, and any an integration stamps, such as the vite plugin's_entry) andundefined, so a read by key is an entry once narrowed (typeof entry === "object"). The server renderer narrows the same way: a metadata key enumerated while registering entry assets, or asked for byresolveAssets, is skipped instead of throwing.?room=a, no?args=) is now keyed by that query, so viewers of different queries no longer share one source.createOwnerleaves solid-js's public types: it is typed only throughsolid-js/internal, like the boundary primitives behindErrored,LoadingandReveal(solid-js types: index.d.ts re-exports createErrorBoundary, createLoadingBoundary and createRevealOrder, which hydration.d.ts strips as @internal #3709). It stays a runtime export for the renderers. Solid 1.x had nocreateOwner, and application code that used it in an RC should host a scope withcreateRoot()(itsdisposeargument can be passed around as a plain function) and re-enter one withrunWithOwner(). A detachedowner.disposekeeps throwing, since it is a method and not part of the public API ([2.0.0-rc.19] errors disposingcreateRenderEffectin a microtask after creation. #4444).renderToStream()that re-pulls root holes — as happens when alazy()component's first load is shared across concurrent renders — now restores the render'ssharedConfig.contextfirst, the same restore the streamed path already performs indoShell. Without it the resumed render body runs under whichever concurrent render set the global last, so an async memo created there records into (and adopts from) another render's slot store and concurrent requests can read each other's values ([2.0 rc.20] SSR: concurrent renders sharing a lazy() component's first load read another render's async memo value #4595).<link rel="modulepreload">hints for modules outside the entry's static import closure (lazy and route chunks, and modules registered later throughregisterAsset("module"), streamed hints included) now carryfetchpriority="low", so they yield bandwidth to the modules hydration waits on. The entry's static imports and modulepreload links written through the head API keep their default priority.renderToStringandrenderToStreamtakelowPriorityPreloads: falseto turn the hint off. In an rc.15 app (Tailwind, five entry imports, four route chunks) patched the same way, Chrome under Lighthouse's devtools throttling hydrated about 310 ms sooner with an unchanged first paint.respond(value, { headers }), returned or thrown, now keeps the envelope'sSet-Cookieheaders on the redirect.enableRichArguments(). A blob arrives as aBlobinstead of aFilenamedblob, an empty type stays empty instead ofapplication/octet-stream, and a file keeps its exact name and itslastModified. The server still reads uploads from clients that send only the part index.@solidjs/compiler@2.0.0-rc.21
board-example@0.0.1-rc.6
Patch Changes
canvas-example@0.0.1-rc.2
Patch Changes
server-dbmon-example@0.0.1-rc.5
Patch Changes
todos-server-example@0.0.1-rc.9
Patch Changes
test-integration@2.0.0-rc.21
Patch Changes