Repository navigation
Release RC packages (rc) - #4252
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 27, 2026 07:19
18aa4ba to
6c1f51e
Compare
github-actions
Bot
force-pushed
the
changeset-release/next
branch
3 times, most recently
from
October 27, 2026 16:06
64e668c to
ef1baad
Compare
github-actions
Bot
force-pushed
the
changeset-release/next
branch
from
October 27, 2026 16:12
ef1baad to
bd058e8
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.19
Patch Changes
c={-1},d={NaN}) are static again. Since Babel 8 support,evaluateAndInlinebuilt them witht.valueToNode, which gives-1/0 / 0expressions rather than numeric literals, so they stopped being inlined into templates (SSR emittedssrAttribute("c", -1)instead ofc="-1") and diverged from@solidjs/compiler(the parity probes' "exotic literal holes"). They are now NumericLiteral nodes again, built directly where @babel/types 8's builder would reject the value; both Babel majors print them as before.@babel/core8 alongside 7: the peer range is now^7.20.12 || ^8.0.0. SSR no longer readsScope#uids(removed in Babel 8), evaluated negative or non-finite numbers are built withvalueToNode,import()parsed asImportExpressionstays dynamic, and TSRX emits the AST shape of the running Babel major (type arguments, type parameter names,import(), enums, heritage). TSRX also keepsimport()options and class method type parameters, which it dropped before.<label {...props()} />) now defers behind a thunk like a spread beside other attributes, so it runs after the element's hydration key. A spread that created a memo shifted the element's key on the server only, and hydration missed the element ([2.0 rc.17] A lone spread runs before the element's hydration key on the server, after it on the client #4240).@solidjs/compiler@2.0.0-rc.19
Patch Changes
compile_program, an entry point that compiles an OxcProgramthe caller has already built instead of source text. It iscompilewith the parse step split off: the program goes through the samedom/ssr/universal/dynamicback ends, with the samerequireImportSourcegate and coverage-pragma handling, so a frontend that produces an AST (rather than projecting to JSX text) gets the shared lowering and source maps on its own authored positions.sourcemust be the program'ssource_text. Additive and Rust-only:compileand the Nodetransform()are unchanged (the shared back half is factored out ofcompile_inner; the TSRX route reaches it with its extracted stylesheet as before).solidjs_compiler::style, moved fromsrc/tsrx/style/tosrc/style/so it is available without thetsrxfeature:compile_style,compile_style_with_class_map_selectors, and their input and output types (StyleInput,StyleLocation,StyleKind,Element,ElementKind,ElementChild,Attribute,AttributeValue,StyleOutput,ClassMapEntry,StyleError). The engine already had no dependency on the TSRX frontend; exporting it lets another frontend (one that does not use TSRX at all) scope a<style>block over its own elements and get the same stylesheet and hash a.tsrxfile gets. Additive and Rust-only: the TSRX route and the Nodetransform()are unchanged.transformDirectives, the lazy and refresh passes, source names) accept a filename with any extension. They run on code that is already lowered to JavaScript, so the filename is metadata rather than a parser choice: a known extension still picks its dialect, and any other (App.rx, from another front end) is parsed as TSX instead of failing with "Unknown file extension". This matters for server functions, whose IDs hash the filename: a front end can now pass the module's real path, so the ID matches the onemoduleForFunctionIdcomputes for that module. The JSX transform itself is unchanged.<label {...props()} />) now defers behind a thunk like a spread beside other attributes, so it runs after the element's hydration key. A spread that created a memo shifted the element's key on the server only, and hydration missed the element ([2.0 rc.17] A lone spread runs before the element's hydration key on the server, after it on the client #4240).<image>or<g>under control flow, in a fragment, or as a component root) inside their<svg>/<math>owner, as DOM templates already are, so valid SVG partials no longer fail thevalidatecheck.@solidjs/diagnostics@2.0.0-rc.19
Patch Changes
@solidjs/element@2.0.0-rc.19
Patch Changes
@solidjs/h@2.0.0-rc.19
Patch Changes
@solidjs/html@2.0.0-rc.19
Patch Changes
placeholder="Search…"rendered the literal…, anhrefwith&kept it in the URL, and components received static props like"a & b"undecoded. Values are now decoded once with the HTML parser's quoted-attribute rules, as text children already were.@solidjs/signals@2.0.0-rc.19
Patch Changes
2a0da2f: fix(web): refuse an async memo that resolves to an element ([2.0.0-rc.18] renderToStream: one value seroval cannot serialize leaves every value in its hydration batch unresolved #4242)
On the server, an async memo (or async iterable source) whose value is rendered output — JSX, a component's result, a
<Loading>/<Errored>boundary — can no longer reach the hydration serializer. A boundary's output failed in seroval, so its record never resolved and the hydrating client waited on the memo forever (streamed, the boundary reverted to its fallback); a template object crossed as data, duplicating the markup, and streamed the client could not insert it (UNRECOGNIZED_INSERT_VALUE). The memo now rejects where its value lands, with the new diagnosticASYNC_MEMO_ELEMENT(recorded on the observe channel; the dev message says what to do instead, other tiers carry the code), and its boundary contains the error like any render error: the nearest<Errored>renders its fallback and the client hydrates it; with none, the<Loading>fragment rejects and the client renders the subtree. Return data from the async memo and render the JSX from it. Ordinary data is never refused (only plain objects in the SSR template shape, boundary outputs and fragment arrays holding them count as rendered output), and content that never hydrates (<NoHydration>) is untouched.Also, a fragment failing while a boundary registered under an undefined key (one created inside an async memo's continuation) is pending no longer fails the whole request in
renderToStream.0847122: Two mounts under one boundary, made in separate flushes, keep their holds independent (S-5 rows 1′–3′, D-4, [2.0 / next] Two mounts under one error boundary merge their holds though they were made in separate flushes (S-5, D-4) #4283). A boundary's tree and output are structure, not a user derivation of its content: like the render effect that flattens the same children without a boundary, they read a hold they are not part of as committed and are re-derived at its landing, and a re-pass of one outside its hold's flush publishes mainline instead of re-joining that hold and merging it with the next flush's.
<Errored>and<Loading>(with or withouton) around two<Show>s, each over its own hold, now reveal each branch at its own hold's landing. A re-arm's swap is still the change's work: while it is, the output joins the change (D-13).0090fe3: Fix: a streamed
<Loading>claimed after a client write changed a shell memo it reads now shows the client's value. A hydrated memo adopted while its server answer was still streaming had no snapshot, so once a client write took its compute over, the boundary's claim read the client's value while adopting the server's markup — and kept the server's text (or attribute) for good, since nothing re-ran the binding. The memo's server answer is now its snapshot when it lands, even when the write already superseded it: the claim reads what the markup shows and replays the client's value at its release, as for a written signal. If the client's recompute is still in flight when the boundary resumes, the claim is served the snapshot instead of going pending, so the boundary keeps the server's content (no fallback over it, no detached nodes, no lost queued click) until the client's value lands.0dd40b2: Release deferred flight bookkeeping when iterator setup or the initial pull throws, so pending verdicts clear and truth readers receive the current error.
f811097: A derived store's per-key
isPendingnow readstruewhile the derive re-asks under aLoadingboundary that has shown content, when the verdict is read in the same computation as the value (${state.a} ${isPending(() => state.a)}). The derive's first flight left a commit-beneath-a-flight mark that its setter landing never cleared, so the next re-ask suspended the verdict reader to the boundary (which kept the stale screen withisPendingfalse) instead of serving it the committed value withisPendingtrue, as an async memo does. ([2.0 / next] A derived store's per-keyisPendingreads false under aLoadingthat has shown content (D-30, S-37) #4269)8b34f22: An error boundary that caught an error rethrown from an inner boundary's fallback now recovers when the inner content does: switching the inner boundary back to its content disposes the fallback that threw, and the outer boundary now drops that error and shows its content again in the same flush, instead of keeping its fallback until some later error re-rendered it ([2.0 / next] An outer error boundary that caught a rethrow from an inner fallback does not recover #4270).
2d9c9aa: Drain pending computations after disposal, releasing retired roots while idle.
c1009e5: A render effect that reads
latest(s)before an async value that has never shown now holds its mount the same way the reverse read order does: an earlierlatest()read no longer turns the later unready read into waiting lane work, so a newly mounted branch (for example under<Show>) stays unpublished until the value lands instead of appearing with an empty slot (S-39, D-28) ([2.0 / next] A reader whose first read islatest(s)publishes an empty slot instead of holding the mount (S-39, D-28) #4275).6ca7e8d:
latest()of an optimistic value now shows the guess beside the held screen however reads are grouped into render effects ([2.0 / next] A held optimistic lane holds per render effect:latest(x)in its own JSX hole shows the guess beside held content (D-25) #4284). When a guess's lane is held on a downstream async derivation, a render effect that reads the guess andlatest(guess)together no longer parks with the lane and freezes thelatest()read: like split effects, it shows1 x1 / 5(the committed value and its derivation beside the guess) and5 x5 / 5when the derivation lands. The lane still holds the guess until its derivation lands; an unblocked lane costs no extra pass.3b6f839: A re-armed
Loadingboundary (on) whose fallback reads pending data through a render effect — any compiled JSX fallback, such as<p>Meta {meta()}</p>— no longer holds the new content's reveal when the content lands first: a fallback the screen never showed is disposed as soon as the content replaces it, so the content shows as soon as it lands and the fallback is never seen, as it already did when the fallback read the data directly ([2.0 / next] A render effect in a re-armedLoadingfallback holds the content's reveal (S-22 row 3′) #4268).4ea2f49:
UNSTABLE_MEMO_OUTPUTno longer reports the memomerge()creates for a function source, such as a compiled conditional component spread (<Child {...(on() ? { tone } : {})} />). No one can pass that memoequals, so the warning had no fix (UNSTABLE_MEMO_OUTPUTfires on the memomerge()creates for a function source (<C {...cond() ? { a } : {}} />); its advice (equals) cannot be applied to that memo #4256). In observe builds the memo is now namedmerge. Production output is unchanged.1d6c40f: Add
onFlush(fn): runsfnonce right after the pending flush, before paint, without waiting on async work. A write made there is its own update, so it is not held by async work another write in the same frame started (a menu closing while the consumer'sonSelectnavigates). Meant for event handlers and effect callbacks; dev warns (ON_FLUSH_IN_OWNED_SCOPE) in a component body or computation. Tree-shakes when unused.1212b77: A derived store (
createProjectionorcreateStore(fn)) over a memo now follows the memo after it has shown a value: when the memo goes pending again,isPendingon the store's keys reports it, and when the memo later throws, the error reaches the error boundary instead of the store silently keeping its last value. ([2.0 / next] A keyedcreateProjectionover a memo stops reporting pending and swallows later errors #4271)e509ad1: A keyed derived store over an async memo follows every landing ([2.0 / next] Regression from #4280: a keyed projection's per-row memos miss every landing after the first #4305): when the source goes pending, the readers of the store's keys wait on the derive itself, so a reader whose value a landing leaves unchanged (a memo per row under
mapArray/<For>) is released by the landing instead of holding the first one forever. The same holds when the derive re-runs while its source is pending.253561e: A memo whose first read rejected stays uninitialized when it is re-asked: an
isPendingpass andlatest()throw NotReady until a value lands instead of readingundefined([2.0] A memo whose first read rejected readsundefined(not NotReady) in a verdict pass while it is re-asked #4244).e0e4224: A served answer's arrival during hydration no longer swallows a client write made in the same flush. Writes made before the arrival flush first, outside hydration's own pass, and a write made during it (an effect's, a later round of the flush) makes a node it reaches compute, so the node shows the written value instead of re-serving the server's answer.
@solidjs/signalsexports its internal flush-round counter (clock) for this.c225400:
IMMUTABLE_UPDATE_IN_STOREno longer reports an array index that now holds an item the array already had, such as the next item shifted down by an in-placesplice(the repair the diagnostic recommends). Before, if the removed item and its neighbour shared at least half of their leaves, the move was reported as a spread-copy replacement ([2.0] IMMUTABLE_UPDATE_IN_STORE false positive when an in-placespliceshifts the next item into the removed index #4262). A fresh copy assigned to an index is still reported. Production output is unchanged.87934c1: Smaller bundles: builds without the optimistic-store, reveal-order or lane hook modules drop their dead branches, and the [2.0 / next] Hydration: an error boundary hydrated in its error state never recovers #4273/[2.0 / next] A reader whose first read is
latest(s)publishes an empty slot instead of holding the mount (S-39, D-28) #4275 fixes share existing paths.solid-js@2.0.0-rc.19
Patch Changes
2a0da2f: fix(web): refuse an async memo that resolves to an element ([2.0.0-rc.18] renderToStream: one value seroval cannot serialize leaves every value in its hydration batch unresolved #4242)
On the server, an async memo (or async iterable source) whose value is rendered output — JSX, a component's result, a
<Loading>/<Errored>boundary — can no longer reach the hydration serializer. A boundary's output failed in seroval, so its record never resolved and the hydrating client waited on the memo forever (streamed, the boundary reverted to its fallback); a template object crossed as data, duplicating the markup, and streamed the client could not insert it (UNRECOGNIZED_INSERT_VALUE). The memo now rejects where its value lands, with the new diagnosticASYNC_MEMO_ELEMENT(recorded on the observe channel; the dev message says what to do instead, other tiers carry the code), and its boundary contains the error like any render error: the nearest<Errored>renders its fallback and the client hydrates it; with none, the<Loading>fragment rejects and the client renders the subtree. Return data from the async memo and render the JSX from it. Ordinary data is never refused (only plain objects in the SSR template shape, boundary outputs and fragment arrays holding them count as rendered output), and content that never hydrates (<NoHydration>) is untouched.Also, a fragment failing while a boundary registered under an undefined key (one created inside an async memo's continuation) is pending no longer fails the whole request in
renderToStream.0090fe3: Fix: a streamed
<Loading>claimed after a client write changed a shell memo it reads now shows the client's value. A hydrated memo adopted while its server answer was still streaming had no snapshot, so once a client write took its compute over, the boundary's claim read the client's value while adopting the server's markup — and kept the server's text (or attribute) for good, since nothing re-ran the binding. The memo's server answer is now its snapshot when it lands, even when the write already superseded it: the claim reads what the markup shows and replays the client's value at its release, as for a written signal. If the client's recompute is still in flight when the boundary resumes, the claim is served the snapshot instead of going pending, so the boundary keeps the server's content (no fallback over it, no detached nodes, no lost queued click) until the client's value lands.ee94440: Hydration keeps a client-only boundary's served fallback ([2.0 / next] Hydration: a client-only (
ssrSource: "client") memo's servedLoadingfallback is dropped and rebuilt #4286). A<Loading>whose content reads a baressrSource: "client"source is served as its fallback plus the"$$f"marker; the client hydrated that fallback, then resumed by re-running the boundary, and when the content suspended on the question it now asks, the new boundary built a second fallback and dropped the served one (losing focus, selection or a running animation in it). The"$$f"route now creates the loading boundary once, at hydration: its content waits on the resume and its fallback hydrates the served one (built at the boundary's id, as the server built it), so content that suspends after the resume keeps the hydrated fallback until it can show.f5cf675: An
<Errored>around a<Loading>whose async read fails during a streamed render now shows its fallback in the server HTML outside server components too, and the client adopts it. Before, the boundary's HTML was empty until hydration (neither the loading nor the error fallback), and the hydrating client rendered the failed boundary from scratch: it asked again and showed the loading fallback. Now, when the<Loading>is all of the<Errored>'s content, the server draws the error fallback in its place (in the shell, or in the streamed fragment after the shell) and serializes the error at the<Errored>, so a client that hydrates after the failure arrived claims that markup and adopts its data without asking again, and recovers when the content's inputs change, as for any hydrated failure ([2.0 / next] Hydration: an error boundary hydrated in its error state never recovers #4273). A client that hydrated before the failure arrived renders it once, with nothing of the server's swap left beside it. With markup between the two boundaries the server still leaves the position blank and the client renders the failure ([2.0 / next] SSR: a boundary that fails through an async read renders no error fallback outside server-component scope, and hydration asks again #4287).8f1d9d2: Server: when an
<Errored>renders its fallback for a<Loading>that failed after the shell, and a hole in that fallback rejects while the server waits for it, the rejection now goes to the next boundary up, as it does when a fallback throws synchronously. Inside a pending outer<Loading>, that outer fragment fails; under an outer<Errored>whose whole content is that position, the outer fallback is drawn there and the client adopts it. Before, the region streamed blank and the hydrating client halted (Errored fallback whose async hole rejects is dropped inside a pending outer Loading #4316). A synchronous throw in that fallback no longer writes an error record for an outer<Errored>without sending its fallback.The server's wait for that fallback now stops after the same pass budget as the
<Loading>resume loop and then streams what it has. It also stops as soon as the render is torn down, for example when the request is aborted (Server wait for an Errored fallback's async holes has no pass limit or abort check #4317).8f1d9d2: An
<Errored>whose fallback fails while rendering (a hole that rejects, or a synchronous throw) now passes that failure to the enclosing boundary on the server, in the shell as well as in a streamed fragment. An outer<Errored>draws its fallback in place of the region, and with none the request fails. Before, the region was sent blank, with the errors recorded and no markup for them.0856fee: An
<Errored>boundary hydrated in the error state the server rendered now recovers. Before, hydration threw the server's error without running the content, so the boundary tracked nothing and stayed on the fallback untilreset(), even after the failed content's inputs changed. Now the content runs during hydration, reading its server data without refetching but claiming no DOM, while the fallback claims the server's markup. If the content fails on the client, the boundary holds that client error and recovers when the content's inputs change. If the error only happened on the server, the server's fallback and error stay up untilreset()is called or the content re-runs ([2.0 / next] Hydration: an error boundary hydrated in its error state never recovers #4273).542ff6f: An
<Errored>whose fallback reads async data, around a<Loading>that fails after the shell, now streams its fallback once that data is ready, and a client hydrating after it arrived claims it. Before, the failure landed while the fallback's read was still pending, so the server had no markup for it. On its own, the boundary swapped to a blank and the client rendered the failure itself, asking for the failed read again. Inside an outer<Loading>still pending, the outer fragment arrived with the Errored region blank, and the client hydrated against the blank with warnings and showed nothing there. Now the failure waits for the fallback, as a swap to a fallback waits for the fallback to be ready: the loading placeholder stays until the finished fallback replaces it (carried by the outer fragment when that is still pending), and the error is serialized with it (Errored fallback with an async hole is dropped inside a pending outer Loading (SSR streaming) #4306).2c9fdd9: A boundary whose server render failed is rendered fresh on the client while adopting the server's records. Inside that render, a
<Dynamic>tag now creates its element instead of throwing a hydration mismatch, and a<Portal>mounts. Hydration also completes when the adopted error has no client boundary to catch it.e0e4224: A client hydrating mid-stream no longer asks again for an async read whose server answer was an error, nor flashes back to the
<Loading>fallback after the failure showed ([2.0 / next] SSR: a boundary that fails through an async read renders no error fallback outside server-component scope, and hydration asks again #4287, Errored fallback with an async hole is dropped inside a pending outer Loading (SSR streaming) #4306). The content of a hydrated failure (a hydrated<Errored>'s content run, or a rejected fragment's fresh render over the<Errored>fallback the server drew) reads a shell memo a cycle after its error landed, and a later tracked read retries an errored async node; the serialized-value latch took that rerun for a client write and computed. Inside such a content run the rerun now re-serves the server's answer and arms nothing. A rejected fragment with no outcome streams an empty template (it was a lone space), so the nodes its swap lists are the server's outcome alone.e0e4224: A memo that adopted its server answer no longer asks again when the server's answer for one of its sources arrives mid-stream. Hydrated mid-stream, an async shell memo
breading another,a, re-ran whena's server value landed, and the serialized-value latch took that rerun for a client write and computedb. The arrival of a served answer, with the flush that carries it, is now hydration's own pass (as a hydrated failure's content run is): a latched node re-running there re-serves its own answer and arms nothing. Only a client write makes it compute.1d6c40f: Add
onFlush(fn): runsfnonce right after the pending flush, before paint, without waiting on async work. A write made there is its own update, so it is not held by async work another write in the same frame started (a menu closing while the consumer'sonSelectnavigates). Meant for event handlers and effect callbacks; dev warns (ON_FLUSH_IN_OWNED_SCOPE) in a component body or computation. Tree-shakes when unused.8f1d9d2: Server: a
<Loading>that fails after the shell while its fragment waits inside an outer<Loading>that is still pending no longer arrives as a blank region reported as a success. The failure now goes to the nearest enclosing boundary, as it does when the same read fails inside the outer<Loading>'s own render. An<Errored>between them draws its fallback in the outer fragment, the client adopts it, and its error is serialized with it. With no<Errored>between them, the outer fragment fails, and an<Errored>whose whole content is that outer<Loading>draws its fallback there. This also covers an<Errored>fallback that fails in that position. Before, the client hydrated the blank region and either halted or rendered nothing there (Errored fallback whose async hole rejects is dropped inside a pending outer Loading #4316).6d6f03f:
<Repeat>with element (non-function) children no longer builds each row twice. It read thechildrengetter once to check for a function and again for the value, so every row's JSX ran twice and its refs fired twice ([2.0 / next] Repeat in non-callback form executes children twice #4296).e0e4224: A served answer's arrival during hydration no longer swallows a client write made in the same flush. Writes made before the arrival flush first, outside hydration's own pass, and a write made during it (an effect's, a later round of the flush) makes a node it reaches compute, so the node shows the written value instead of re-serving the server's answer.
@solidjs/signalsexports its internal flush-round counter (clock) for this.87934c1: Smaller bundles: builds without the optimistic-store, reveal-order or lane hook modules drop their dead branches, and the [2.0 / next] Hydration: an error boundary hydrated in its error state never recovers #4273/[2.0 / next] A reader whose first read is
latest(s)publishes an empty slot instead of holding the mount (S-39, D-28) #4275 fixes share existing paths.2c9fdd9: Hydration never asks again for what the server sent, even when a streamed boundary's fragment rejects with no outcome (no
<Errored>on the server could draw the failure). The client still renders that fragment fresh, so its graph is created, but every read in it now claims its serialized record: reads the server resolved take their values, and a read whose record is an error throws that error to the nearest client boundary, or is an uncaught error when there is none. Only reads with no record, such as those cut off by a truncated stream, compute. Recovery comes from a real input change or a boundary'sreset(), as for any hydrated failure.Updated dependencies [2a0da2f]
Updated dependencies [0847122]
Updated dependencies [0090fe3]
Updated dependencies [0dd40b2]
Updated dependencies [f811097]
Updated dependencies [8b34f22]
Updated dependencies [2d9c9aa]
Updated dependencies [c1009e5]
Updated dependencies [6ca7e8d]
Updated dependencies [3b6f839]
Updated dependencies [4ea2f49]
Updated dependencies [1d6c40f]
Updated dependencies [1212b77]
Updated dependencies [e509ad1]
Updated dependencies [253561e]
Updated dependencies [e0e4224]
Updated dependencies [c225400]
Updated dependencies [87934c1]
@solidjs/universal@2.0.0-rc.19
Patch Changes
<Show>withfallback={<></>}) no longer loses its place among its siblings: the region now keeps its sentinel while empty, so the content that later replaces it is inserted where the region sits instead of being appended after the following siblings ([universal] An empty fragment value loses its slot; the next value is appended after its siblings #4274).@solidjs/web@2.0.0-rc.19
Patch Changes
2c9fdd9: A streamed boundary that fails on the server can leave nested reads still pending. The server abandons those reads, and their records used to settle as
undefined, which the client's fresh render of the failed fragment would then adopt as the server's answer. The server now unregisters abandoned records, so those reads compute on the client. The fresh render also spends an id on each element's hydration key, as the server did, so its reads line up with the server's records by id.2a0da2f: fix(web): refuse an async memo that resolves to an element ([2.0.0-rc.18] renderToStream: one value seroval cannot serialize leaves every value in its hydration batch unresolved #4242)
On the server, an async memo (or async iterable source) whose value is rendered output — JSX, a component's result, a
<Loading>/<Errored>boundary — can no longer reach the hydration serializer. A boundary's output failed in seroval, so its record never resolved and the hydrating client waited on the memo forever (streamed, the boundary reverted to its fallback); a template object crossed as data, duplicating the markup, and streamed the client could not insert it (UNRECOGNIZED_INSERT_VALUE). The memo now rejects where its value lands, with the new diagnosticASYNC_MEMO_ELEMENT(recorded on the observe channel; the dev message says what to do instead, other tiers carry the code), and its boundary contains the error like any render error: the nearest<Errored>renders its fallback and the client hydrates it; with none, the<Loading>fragment rejects and the client renders the subtree. Return data from the async memo and render the JSX from it. Ordinary data is never refused (only plain objects in the SSR template shape, boundary outputs and fragment arrays holding them count as rendered output), and content that never hydrates (<NoHydration>) is untouched.Also, a fragment failing while a boundary registered under an undefined key (one created inside an async memo's continuation) is pending no longer fails the whole request in
renderToStream.f5cf675: An
<Errored>around a<Loading>whose async read fails during a streamed render now shows its fallback in the server HTML outside server components too, and the client adopts it. Before, the boundary's HTML was empty until hydration (neither the loading nor the error fallback), and the hydrating client rendered the failed boundary from scratch: it asked again and showed the loading fallback. Now, when the<Loading>is all of the<Errored>'s content, the server draws the error fallback in its place (in the shell, or in the streamed fragment after the shell) and serializes the error at the<Errored>, so a client that hydrates after the failure arrived claims that markup and adopts its data without asking again, and recovers when the content's inputs change, as for any hydrated failure ([2.0 / next] Hydration: an error boundary hydrated in its error state never recovers #4273). A client that hydrated before the failure arrived renders it once, with nothing of the server's swap left beside it. With markup between the two boundaries the server still leaves the position blank and the client renders the failure ([2.0 / next] SSR: a boundary that fails through an async read renders no error fallback outside server-component scope, and hydration asks again #4287).542ff6f: An
<Errored>whose fallback reads async data, around a<Loading>that fails after the shell, now streams its fallback once that data is ready, and a client hydrating after it arrived claims it. Before, the failure landed while the fallback's read was still pending, so the server had no markup for it. On its own, the boundary swapped to a blank and the client rendered the failure itself, asking for the failed read again. Inside an outer<Loading>still pending, the outer fragment arrived with the Errored region blank, and the client hydrated against the blank with warnings and showed nothing there. Now the failure waits for the fallback, as a swap to a fallback waits for the fallback to be ready: the loading placeholder stays until the finished fallback replaces it (carried by the outer fragment when that is still pending), and the error is serialized with it (Errored fallback with an async hole is dropped inside a pending outer Loading (SSR streaming) #4306).2f7dc84: First mounts of a multi-node insert skip
reconcileArrays' diff setup (spa-navigation mounts ~3%). The once-per-pass focus read from feat(web): keep focus on a moved node with moveBefore() (#3997) #4261 still applies, so a focused node arriving from another list keeps its focus.2c9fdd9: A boundary whose server render failed is rendered fresh on the client while adopting the server's records. Inside that render, a
<Dynamic>tag now creates its element instead of throwing a hydration mismatch, and a<Portal>mounts. Hydration also completes when the adopted error has no client boundary to catch it.e0e4224: A client hydrating mid-stream no longer asks again for an async read whose server answer was an error, nor flashes back to the
<Loading>fallback after the failure showed ([2.0 / next] SSR: a boundary that fails through an async read renders no error fallback outside server-component scope, and hydration asks again #4287, Errored fallback with an async hole is dropped inside a pending outer Loading (SSR streaming) #4306). The content of a hydrated failure (a hydrated<Errored>'s content run, or a rejected fragment's fresh render over the<Errored>fallback the server drew) reads a shell memo a cycle after its error landed, and a later tracked read retries an errored async node; the serialized-value latch took that rerun for a client write and computed. Inside such a content run the rerun now re-serves the server's answer and arms nothing. A rejected fragment with no outcome streams an empty template (it was a lone space), so the nodes its swap lists are the server's outcome alone.5601848: The focused node keeps focus when the runtime moves it, where the browser has
Element.moveBefore()(Keep element state when the runtime moves a node (moveBefore()and not detaching what is re-inserted) #3997). List reconciliation moves the node that holdsdocument.activeElementwithmoveBefore(), so a focused row survives a reorder, and a move into a list that updates before the one it leaves. While focus is in the list, the reconcile'sreplaceChildpath inserts instead, leaving the old row in place until the pass places it. Focus is read once per pass, and not at all withoutmoveBefore()or with focus on the body; every other node keeps plaininsertBefore(), so reorders cost the same as before. Browsers withoutmoveBefore()behave as before, with no focus restore. Array inserts into an empty slot now go through the same reconcile.88ea86c: Each event replayed after hydration is its own instant, as it would have been live ([2.0 / next] Hydration: events replayed by
runHydrationEventsshare one flush, so two clicks on a counter bump it once #4285).runHydrationEventsnow flushes after every replayed event, so a handler reads the writes of the events before it: two clicks on a counter queued before the client loaded bump it twice, not once.4eb570e: Avoid retaining the first value-bound select and its form through the shared option-insertion hook.
e8b0b15:
renderToStream: a value that fails to serialize no longer leaves the other pre-shell hydration values pending on the client ([2.0.0-rc.18] renderToStream: one value seroval cannot serialize leaves every value in its hydration batch unresolved #4242). Pending promises registered before the shell (async sources and Loading boundaries'<key>_frcompletion flags) were handed to seroval as one object write. Since seroval 1.7, a value that fails to serialize ends the write it belongs to, so one failure stopped every value in that write. An async memo that resolves to an element, such as a nested<Loading>, left both boundaries unresolved and hydration never finished. The stubs are still held until the shell and handed over at the same point, in the same order, but each is now its own keyed write, so a failure only affects its own key, as on rc.17.Updated dependencies [2a0da2f]
Updated dependencies [0090fe3]
Updated dependencies [ee94440]
Updated dependencies [f5cf675]
Updated dependencies [8f1d9d2]
Updated dependencies [8f1d9d2]
Updated dependencies [0856fee]
Updated dependencies [542ff6f]
Updated dependencies [2c9fdd9]
Updated dependencies [e0e4224]
Updated dependencies [e0e4224]
Updated dependencies [1d6c40f]
Updated dependencies [8f1d9d2]
Updated dependencies [6d6f03f]
Updated dependencies [e0e4224]
Updated dependencies [87934c1]
Updated dependencies [2c9fdd9]
board-example@0.0.1-rc.4
Patch Changes
canvas-example@0.0.1-rc.0
Patch Changes
server-dbmon-example@0.0.1-rc.3
Patch Changes
todos-server-example@0.0.1-rc.7
Patch Changes
test-integration@2.0.0-rc.19
Patch Changes