Skip to content

Release RC packages (rc) - #3255

Open
github-actions[bot] wants to merge 1 commit into
nextfrom
changeset-release/next
Open

Release RC packages (rc)#3255
github-actions[bot] wants to merge 1 commit into
nextfrom
changeset-release/next

Conversation

@github-actions

@github-actions github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

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.

⚠️⚠️⚠️⚠️⚠️⚠️

next is currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, run changeset pre exit on next.

⚠️⚠️⚠️⚠️⚠️⚠️

Releases

@solidjs/babel-plugin@2.0.0-rc.7

Patch Changes

  • ead7b1a: Keep hydration IDs aligned when an intrinsic element has a ref and one reactive spread.
  • b3586e8: Validate document-shell templates in the document context ([compiler] validate rejects document-shell templates (<html><head><body>) — fatal in client compiles since rc.5 made validate failures errors #3259). The validate pass round-trips templates through a body-context fragment parse, which strips <html>/<head>/<body> wrappers no matter how well-formed the markup — so once [compiler] validate warns but still emits the broken template walk #3099 made validate failures compile errors, a root component owning the document shell failed to compile in plain client mode, and merely importing it (the jsdom component-test configuration) was fatal. Shell-rooted templates now parse as a document and the shell element is compared back — the analogue of the synthetic <table> wrap for table partials, in both the Babel plugin and the native compiler. Genuine restructuring (an implied <head>, flow content in <head>, a <p> split in <body>) still errors. Since <template> parsing flattens shells, actually client-creating one now throws a descriptive dev-mode error from template() pointing at hydrate() — the failure moved from every import to the one broken act.
  • d601119: Remove the experimental patch channel and patch-mode list driver (always opt-in, never default). Graph-native regions own value delivery and the unified-For design owns list structure, so the channel's parallel delivery machinery is retired: patch.ts/patch-driver.ts deleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw, patchDriver/rowProof/driveList) removed, the patchDriver compiler option dropped from both compilers, the insert $ll seam stripped, and the write-side channel struct dieted to the single written-keys bound (t.wk) the core fold/notify paths actually use. Store-family app bundles reclaim up to ~900 B brotli; every measured tier shrinks.

@solidjs/compiler@2.0.0-rc.7

Patch Changes

  • ead7b1a: Keep hydration IDs aligned when an intrinsic element has a ref and one reactive spread.
  • b3586e8: Validate document-shell templates in the document context ([compiler] validate rejects document-shell templates (<html><head><body>) — fatal in client compiles since rc.5 made validate failures errors #3259). The validate pass round-trips templates through a body-context fragment parse, which strips <html>/<head>/<body> wrappers no matter how well-formed the markup — so once [compiler] validate warns but still emits the broken template walk #3099 made validate failures compile errors, a root component owning the document shell failed to compile in plain client mode, and merely importing it (the jsdom component-test configuration) was fatal. Shell-rooted templates now parse as a document and the shell element is compared back — the analogue of the synthetic <table> wrap for table partials, in both the Babel plugin and the native compiler. Genuine restructuring (an implied <head>, flow content in <head>, a <p> split in <body>) still errors. Since <template> parsing flattens shells, actually client-creating one now throws a descriptive dev-mode error from template() pointing at hydrate() — the failure moved from every import to the one broken act.
  • d601119: Remove the experimental patch channel and patch-mode list driver (always opt-in, never default). Graph-native regions own value delivery and the unified-For design owns list structure, so the channel's parallel delivery machinery is retired: patch.ts/patch-driver.ts deleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw, patchDriver/rowProof/driveList) removed, the patchDriver compiler option dropped from both compilers, the insert $ll seam stripped, and the write-side channel struct dieted to the single written-keys bound (t.wk) the core fold/notify paths actually use. Store-family app bundles reclaim up to ~900 B brotli; every measured tier shrinks.

@solidjs/diagnostics@2.0.0-rc.7

Patch Changes

@solidjs/element@2.0.0-rc.7

Patch Changes

@solidjs/h@2.0.0-rc.7

Patch Changes

@solidjs/html@2.0.0-rc.7

Patch Changes

@solidjs/signals@2.0.0-rc.7

Patch Changes

  • 215de3b: Align store overloads across the signals, client, and server entry points. Plain stores share StoreOptions, projection forms share ProjectionOptions, plain optimistic stores expose their existing options argument, and derived optimistic stores are typed as refreshable.

  • ae46c92: Comment-only: update doc paths in source comments after relocating the signals internals docs (INTERNALS-*, SPEC-ASYNC-SEMANTICS, rules-mining) from the package root into packages/signals/docs/. No behavior change.

  • fc7e626: Merge clone-path folds onto a container privatized mid-batch (Bug in solid 2.rc6 store #3271). Family and array drafts fold by swapping their pending backing in and re-slotting the parent with a CAS against the pre-batch old. When a descendant of the same node was written earlier in the draft, the descendant's fold path-copies THROUGH the ancestor first — privatizeCommitted clones the ancestor's committed backing and re-points the parent slot at the clone — so the ancestor's own fold swapped in a stale ensurePB-time clone, failed the parent CAS, and its writes were silently discarded (writable projections; plain object stores fold through the overlay path and were immune). Such folds now merge the batch's written keys onto the privatized container in place — the trap's written-keys bound is authoritative, with a value-diff fallback when an array length write poisoned it — composing both folds instead of losing one.

  • d50e855: rc.6 P1 store sweep — three fold-machinery gaps reported by @brenelz, all predating the Bug in solid 2.rc6 store #3271 fix:

    • [P1] 2.0.0-rc.6: Moving an array row and editing it in one setter overwrites another row #3282 — an array move (reverse/unshift/splice) plus an edit of a moved row corrupted sibling rows: the row target's parent-key is stamped at wrap time and never followed the move, so the fold's parent-slot re-point wrote the edited row's clone over whichever sibling now occupied the old index ([1,2] became [1,1]). Fold-time slot writes (privatization stitch, drainFolds path-copy, and the eager-fold twin) now resolve the slot by raw identity when the stamped key is stale — arrays only, fold-time only, no read-path cost.
    • [P1] 2.0.0-rc.6: deep() drops descendant subscriptions after a parent field edit #3283deep() silently unsubscribed from every untouched child after a parent-field edit: the walk bypasses the proxy traps, and a bare Reflect.ownKeys on a plain-object overlay pending backing (own keys = this batch's writes) hid inherited committed keys from the mid-flush re-walk, dropping those records from the effect's refreshed dependency set. The walk now merges committed keys minus deletes, mirroring the ownKeys trap's 2.0.0 | slow and steady wins the race #3044 overlay merge.
    • [P1] 2.0.0-rc.6: A nested derived-store write disconnects ancestor property observers #3284 — in derived stores, a descendant write disconnected ancestor observers and broke proxy identity: privatizeCommitted registered its clone only in the global lookup, but family targets resolve children through fam.map, so the next parent read wrapped a fresh target and orphaned the original's nodes. The clone now registers in the target's own map.
  • 8f9f369: Suspend uninitialized async values across optimistic lanes so latest()-conditioned branches wait for their first value instead of rendering undefined.

  • 0653673: Route errors thrown while applying asynchronous computed setters through the
    node's error state. This prevents user callbacks invoked during asynchronous
    projection reconciliation, such as key selectors, from escaping as unhandled
    promise rejections.

  • 067e3bc: Optimistic increments keep stacking after a sibling landing. With several
    optimistic-store actions in flight (optimistic votes++, server confirm,
    refresh(store)), the first vote's truth landing is staged into the
    transaction that still retains the second vote, and that vote's increment
    replays over it. A third click's draft then read the staged truth WITHOUT
    the replayed override: draft reads composed live overrides only while no
    pending backing existed, and votes++ reads before the first write triggers
    the view-reseed hand-off. It read base, wrote base + 1, and its override
    landed on the value already on screen — the click was invisible and the
    count stuck (or fell back) until truth caught up. Draft reads now compose
    overrides whenever the pending backing is not the draft's own view-seeded
    clone.

  • 8a65e5e: An optimistic store's first flight suspends into its Loading boundary again.
    The flight-owned transaction (Optimistic store truth-flight should own its transaction rather than rely on ambient adoption #3146) was declared for the uninitialized
    first ask too, so every transition-riding consumer — render()'s scheduled
    root insert included — was held until the initial fetch landed: the page
    stayed blank (content outside the boundary included) and the boundary's
    fallback never showed, while createStore(fn, seed) and
    createOptimistic(fn, seed) in the same spot showed it. Nothing has
    committed on a first flight, so there is no truth to keep on screen and no
    optimistic state to protect: it now declares nothing, like the loading
    window (2.0-betacreateOptimistic update is not visible while sibling <Loading> shows fallback #2933). Refetch flights declare exactly as before, so bare
    optimistic writes during an in-flight refetch still ride the flight's
    transaction (2.0.0-beta.26 | optimistic store unexpected pending state for store or dependency, while having an optimistic override #2951) and content stays put until the new truth lands.

  • f24e53d: refresh() after a held manual write stays a quiet re-ask. When an action
    wrote to a derived store and later called refresh(store), the lift of the
    manual-write mask (2.0.0-rc.1 | refresh(store) inside an action(), does not refresh the store #3026) dropped the re-ask classification, so the refetch
    was treated as a brand-new question and pended every leaf — every sibling
    row lit up isPending, and a row-scoped affects() could not narrow it.
    The lift now keeps the classification: same-question motion stays silent,
    and only the written slot and any declared affects() mark read pending
    until the truth lands. Same-tick precedence (Solid v2.0.0-beta.10 batched parent & derived signals manual update is neglected for derived signals #2692) is unchanged.

  • fa568d3: Relocate fix(signals): suspend uninitialized async across lanes #3277's uninitialized cross-lane suspension check from core read() into the optimistic module's laneSuspends. No behavior change — the check is only reachable under a lane, which implies the engine is installed — but the inline placement taxed every bundle including storeless floors (27-66 B across five size scenarios); in laneSuspends only bundles that retain the optimistic module pay.

  • d601119: Remove the experimental patch channel and patch-mode list driver (always opt-in, never default). Graph-native regions own value delivery and the unified-For design owns list structure, so the channel's parallel delivery machinery is retired: patch.ts/patch-driver.ts deleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw, patchDriver/rowProof/driveList) removed, the patchDriver compiler option dropped from both compilers, the insert $ll seam stripped, and the write-side channel struct dieted to the single written-keys bound (t.wk) the core fold/notify paths actually use. Store-family app bundles reclaim up to ~900 B brotli; every measured tier shrinks.

  • ac5159a: Preserve the supplied type in Store<T> instead of adding a shallow readonly mapping.

  • de1c8b5: Revert the complete-seed requirement on derived store forms (fix(signals): require complete store seeds #3258). Derived createStore, createProjection, and derived createOptimisticStore accept Partial<T> seeds again, on maintainer review: requiring a full T forces callers to fabricate a throwaway complete object in the common async case — any object store reconciling on a non-id key needs the options slot, hence the seed slot — while the seed is never observable there (reads pend until the first resolution). The type-honesty concern it addressed is real only for sync draft-reading callbacks and is better served by the seedless-callback direction discussed in Proposal: make derived store APIs type-safe and ergonomic #3194. Since fix(signals): require complete store seeds #3258 never shipped in a release, its pending changeset is dropped rather than superseded; the API is unchanged from 2.0.0-rc.6. The fix(signals): align store overloads #3260 overload alignment (slot order, shallow in options, Refreshable derived returns) is unaffected.

  • e346e61: Store leaf nodes ride slotSignal — one pre-shaped literal with _host/_key backrefs replacing the per-node options object, equals closure, unobserved closure, and the NodeExtension that held it; the unobserved sweep dispatches CONFIG_SLOT_NODE nodes to one shared hook. getNode self-time −23% on dbmon warm mounts.

  • e346e61: Store first-read diet: the get trap's accessor probe verdict threads through to node creation (one descriptor scan per first read, not two), the trap's duplicate node-map lookup is hoisted, and the first tracked read populates the wrap cache so the second read skips wrapNext. dbmon mount min −4%, get-trap self-time −19%.

  • 0255729: Stop the store proxy's dev strict-read check from firing on the engine's
    thenable probe. Resolving a promise with a store proxy — refresh(store)'s
    waiter delivers the store, Promise.resolve(store), return store from an
    async function — makes the engine read store.then synchronously in the
    caller's scope. When that scope carries a strict-read label (an effect
    callback, a component body) the read produced a spurious
    STRICT_READ_UNTRACKED warning, and against a refetching derived store it
    could escalate to the PENDING_ASYNC_UNTRACKED_READ throw, rejecting the
    promise being resolved. await refresh(list) inside an action logged the
    warning on every call. The then probe is not a read the user wrote and is
    now exempt from both.

solid-js@2.0.0-rc.7

Patch Changes

  • 215de3b: Align store overloads across the signals, client, and server entry points. Plain stores share StoreOptions, projection forms share ProjectionOptions, plain optimistic stores expose their existing options argument, and derived optimistic stores are typed as refreshable.
  • 3424f9a: Consume the first value of live-derived stores during SSR and reconnect their live sources after hydration.
  • d601119: Remove the experimental patch channel and patch-mode list driver (always opt-in, never default). Graph-native regions own value delivery and the unified-For design owns list structure, so the channel's parallel delivery machinery is retired: patch.ts/patch-driver.ts deleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw, patchDriver/rowProof/driveList) removed, the patchDriver compiler option dropped from both compilers, the insert $ll seam stripped, and the write-side channel struct dieted to the single written-keys bound (t.wk) the core fold/notify paths actually use. Store-family app bundles reclaim up to ~900 B brotli; every measured tier shrinks.
  • ac5159a: Preserve the supplied type in Store<T> instead of adding a shallow readonly mapping.
  • de1c8b5: Revert the complete-seed requirement on derived store forms (fix(signals): require complete store seeds #3258). Derived createStore, createProjection, and derived createOptimisticStore accept Partial<T> seeds again, on maintainer review: requiring a full T forces callers to fabricate a throwaway complete object in the common async case — any object store reconciling on a non-id key needs the options slot, hence the seed slot — while the seed is never observable there (reads pend until the first resolution). The type-honesty concern it addressed is real only for sync draft-reading callbacks and is better served by the seedless-callback direction discussed in Proposal: make derived store APIs type-safe and ergonomic #3194. Since fix(signals): require complete store seeds #3258 never shipped in a release, its pending changeset is dropped rather than superseded; the API is unchanged from 2.0.0-rc.6. The fix(signals): align store overloads #3260 overload alignment (slot order, shallow in options, Refreshable derived returns) is unaffected.
  • Updated dependencies [215de3b]
  • Updated dependencies [ae46c92]
  • Updated dependencies [fc7e626]
  • Updated dependencies [d50e855]
  • Updated dependencies [8f9f369]
  • Updated dependencies [0653673]
  • Updated dependencies [067e3bc]
  • Updated dependencies [8a65e5e]
  • Updated dependencies [f24e53d]
  • Updated dependencies [fa568d3]
  • Updated dependencies [d601119]
  • Updated dependencies [ac5159a]
  • Updated dependencies [de1c8b5]
  • Updated dependencies [e346e61]
  • Updated dependencies [e346e61]
  • Updated dependencies [0255729]
    • @solidjs/signals@2.0.0-rc.7

@solidjs/universal@2.0.0-rc.7

Patch Changes

  • d601119: Remove the experimental patch channel and patch-mode list driver (always opt-in, never default). Graph-native regions own value delivery and the unified-For design owns list structure, so the channel's parallel delivery machinery is retired: patch.ts/patch-driver.ts deleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw, patchDriver/rowProof/driveList) removed, the patchDriver compiler option dropped from both compilers, the insert $ll seam stripped, and the write-side channel struct dieted to the single written-keys bound (t.wk) the core fold/notify paths actually use. Store-family app bundles reclaim up to ~900 B brotli; every measured tier shrinks.
  • Updated dependencies [215de3b]
  • Updated dependencies [3424f9a]
  • Updated dependencies [d601119]
  • Updated dependencies [ac5159a]
  • Updated dependencies [de1c8b5]
    • solid-js@2.0.0-rc.7

@solidjs/web@2.0.0-rc.7

Patch Changes

  • 1226381: Bind GET() grants to the function identity they were declared about (A GET() grant governs an id, not the function it was granted to #3237). The grant — GET/HEAD dispatch plus the CSRF origin-gate exemption — was keyed by id alone, so register -> register -> GET(oldReference) handed the NEW function cross-site GET execution on the strength of a declaration the old one signed. The grant now records the declared function, and a single declaresRead(id) check governs both dispatch and the 405 Allow advertisement; a stale or unverifiable declaration fails closed (GET refused, POST + origin gate required). A declaration or withMeta({ method }) write that would change an existing grant's binding throws in dev and fails closed in prod, never silently rebinds.

  • 7009adf: Bound the request body cap by the bytes actually received: a conforming Content-Length under the limit no longer skips the counting read, so an under-declared body cannot stream past bodySizeLimit into the decoder, and the abort/teardown coupling for abandoned uploads now covers declared-length POSTs too (The body cap is decided by the peer's Content-Length, so every ordinary POST skips it #3236).

  • a14c138: Dedupe the requested single-flight source ids to a first-seen-order set at entry, so a repeated id runs its collector once and echoes once in the response header instead of multiplying work by the caller-controlled list length (The single-flight source list is honored as a multiset, so a caller picks its own amplification factor #3251)

  • c08e974: Document the per-handler wrapInvocation option as entry-only (A per-handler wrapInvocation never sees the calls the dispatched body makes #3240). Ruled: entry-only semantics are kept — the option wraps exactly the invocation the request addressed, and nested direct server-function calls made by the dispatched body are not re-wrapped by it; hop-by-hop policy belongs to the configured (ambient) hook, which wraps every direct call. TSDoc only, no runtime behavior change; the boundary is now pinned by a regression test.

  • fbe5bef: Encrypt the no-JS flash cookie (The flash cookie carries the submission with no SameSite, no lifetime and no __Host- prefix #3239). The flash carries the submitted form input — whatever the user typed — so its payload is now AES-GCM encrypted under a key derived (domain-separated) from the deployment secret: configureServerFunctionsServer({ secret }), falling back to the globalThis.__SOLID_SECRET__ value the Solid bundler plugin injects into server builds. With no secret configured the outcome is withheld rather than sent in the clear (the post still redirects; dev builds warn once). Decryption failure — a tampered cookie, a rotated secret — reads as "no flash". The cookie now also carries SameSite=Lax and Max-Age=60, and encodeFlashCookie/decodeFlashCookie are async.

  • 292bdc5: Enforce provideEvent's exactly-once contract on direct SSR calls too: the invocation count provideEvent's contract is unenforced: calling fn twice double-commits a mutation under a 200 #3172 added to HTTP dispatch now guards both legs through a shared provideEventOnce seam, so a hook that double-invokes or skips the callback fails loudly during a render instead of silently double-committing a mutation or answering undefined, while synchronous direct calls keep returning their value synchronously (provideEvent's exactly-once contract is enforced on HTTP dispatch and nowhere else #3246).

  • 285a717: Defuse the promise the decoder's abort sweep is about to reject (A colliding PromiseConstructor ref id orphans a decoder-minted promise, crashing the process — a gap in #3232's own fix #3267). A PromiseConstructor node whose ref id collides with an already-assigned id (or is malformed) throws mid-registration, leaving a {p, s, f} deferred in the decoder's refs whose promise ownDecodedPromises never claimed — the deferred is not itself a Promise. The end-of-stream sweep then rejected that promise with no owner, and under Node's default policy one unauthenticated POST with a crafted argument body ended the process after the request was already refused 400. The sweep now takes ownership of .p before rejecting it, covering every promise it touches regardless of how the entry reached refs.

  • 8f11ea7: Guard failure channels under an Error carrier's non-enumerable own data slots (A returned Error's non-enumerable slots ship unsanitized — the #3235 guard walks Object.keys but seroval encodes getOwnPropertyNames #3268). The The result guard walks neither Error carriers nor non-enumerable slots, so the channels under them ride unguarded #3235 guard walked Error carriers with Object.keys, but seroval encodes an Error's own properties through getOwnPropertyNames — so a rejected promise or erroring stream parked on a non-enumerable slot (cause is non-enumerable by spec since ES2022, and the ordinary place a wrapped driver error carries its context) was encoded without ever being walked: its failure reason rode the wire verbatim on a committed 200, and the rejection had no owner. The guard now descends an Error's own string-keyed data slots, enumerable or not. Hidden accessors remain the codec's read (4799541's pinned ruling): the walk still does not invoke what the author hid.

  • d0ca3a4: The no-JS flash cookie now records the UNBOUND function base as the submission's url — the request's pathname (<endpoint>/<id>), never the query. A .with()-bound form's action url carries its bound arguments in ?args=…, and integrations match submissions against the action's unbound base (the router's s.url === fn.base): a flash url wearing the binding stored, decoded, and then matched nothing on the post-redirect render. The seed now matches the scripted submission shape exactly — the base as url, bound arguments prepended to input (which the argument parser's ?args prepend already provided).

  • b3586e8: Validate document-shell templates in the document context ([compiler] validate rejects document-shell templates (<html><head><body>) — fatal in client compiles since rc.5 made validate failures errors #3259). The validate pass round-trips templates through a body-context fragment parse, which strips <html>/<head>/<body> wrappers no matter how well-formed the markup — so once [compiler] validate warns but still emits the broken template walk #3099 made validate failures compile errors, a root component owning the document shell failed to compile in plain client mode, and merely importing it (the jsdom component-test configuration) was fatal. Shell-rooted templates now parse as a document and the shell element is compared back — the analogue of the synthetic <table> wrap for table partials, in both the Babel plugin and the native compiler. Genuine restructuring (an implied <head>, flow content in <head>, a <p> split in <body>) still errors. Since <template> parsing flattens shells, actually client-creating one now throws a descriptive dev-mode error from template() pointing at hydrate() — the failure moved from every import to the one broken act.

  • f21e060: Flash falsy no-JS outcomes (0, false, "", null) instead of silently dropping them: the flash decode and the no-JS handler now decide structurally (result presence, Response shape) rather than by truthiness, and dispatch no longer erodes a returned null to undefined on its way to the handler; an undefined outcome keeps its current no-cookie behavior pending ruling (A falsy outcome is no outcome: a committed submission reports nothing to the next render #3248)

  • 5cee0f7: Guard enumerable failure channels carried on Error results: the result-encoding guard walk now descends Error-prototyped carriers (which seroval encodes with their own properties) so a rejecting promise, erroring stream, or throwing iterable assigned onto a returned Error is sanitized and torn down like any other channel, while the carrier keeps its prototype, message, and own data (The result guard walks neither Error carriers nor non-enumerable slots, so the channels under them ride unguarded #3235).

  • 6bb51c9: Keep -0 off the server-function JSON fast path. JSON.stringify(-0) is "0", so a signed zero admitted by isJSONSafe rode the fast path and arrived as +0 — a silent sign flip on the exact guard that already refuses NaN and the infinities for the same reason. -0 now answers "not JSON-safe" and rides the codec, which spells it exactly, on both legs (argument lists and results).

  • ff2ecf1: Own every promise the server-function decoder mints. A rejected promise decoded out of a peer's payload — a rejection frame arriving mid-stream, or an atomic rejected-promise node settling synchronously during decode — had no owner when the consumer never read (or abandoned) the slot, and escaped as an unhandled rejection that ends a Node consumer under its default policy. The decoder now attaches a noop rejection handler at mint time, mirroring the encode side's guardedPromise ownership (A rejecting promise in a result graph that fails to encode takes down the Node process #3216); real consumers still observe the rejection unchanged.

  • c0bc9ba: Adopt a transformFlightResult Response via the ownership seam (ownResponse) before stamping the mutation's cookies and accumulated headers onto it, so a Response the integration retains (a memoized shell) never accumulates one caller's session cookies and serves them to the next (The single-flight fold stamps this request's cookies onto a Response the integration still holds #3234, completing commitEventResponse mutates the returned Response in place, so a cached Response accumulates every user's Set-Cookie #3155)

  • ace227e: Canonicalize resource identity qualifiers instead of comparing raw prop values, so two declarations of one request dedupe to one <link> on both sides of hydration.

    false now means absent, matching both attribute writers: crossorigin={cond && "anonymous"} no longer emits a second, byte-identical link when the condition is false.

    crossorigin is compared by its CORS state rather than its spelling. It is a CORS settings attribute with three states — absent is No CORS, use-credentials (ASCII case-insensitive) is Use Credentials, and every other present value including "", a bare attribute and an invalid one is Anonymous — so the same font is no longer preloaded once per spelling, and the client adopts the server's link instead of mounting a second one for a request the browser already has.

    Qualifier values are length-prefixed, so a value containing the identity delimiters can no longer collide with a different qualifier set and silently suppress another resource (type: "a:media=b" and type: "a", media: "b" were one identity).

    Client-side adoption of a mount-once head resource now matches a server-emitted element on the full request identity rather than the href alone: two preloads sharing an href still differ if their destination, CORS mode, type, media or source set differ. The document client, the standalone frame client and the server all apply the same rules.

  • b7b17ab: Make extractBody own the stream it decodes: the body is read where it lies, never from an internal clone. An unread tee branch queues the whole payload in memory for the life of the read and defeats backpressure and cancellation — the same ownership defect fixed for the upload leg in bufferBodyWithin (A client disconnect on a chunked upload rejects out of handleServerFunctionRequest instead of answering a status #3217The 413 refusal cancels a tee branch, never the upload source #3219). decodeResponse keeps its documented contract (an integration's response stays readable) by cloning at its own entry — a branch that is then read in full; the client transport decodes the response it owns directly, and the server's argument road reuses its one deliberate clone (kept so event.request stays readable) for the empty-body inspection instead of teeing again. This is the clone half of The client transport buffers every response twice and never ends the connection it opened #3244 only; connection teardown on completion is deliberately not included.

  • ed6b605: Throw a clear configuration error for invalid wrapInvocation values (A wrapInvocation option that is not a hook removes the configured authorization gate #3238). A value other than a function or undefinednull, false, an options bag in the wrong slot — used to fail in the quietest available direction: falsy values silently took per-invocation policy (auth, logging) off the call, truthy non-functions threw a bare "not a function" mid-dispatch. The hook is now validated at the point it is resolved for an invocation, on both roads (HTTP dispatch and direct SSR calls), with an error naming wrapInvocation and the received type; undefined stays the one spelling of absence.

  • 6c9f8f4: Refuse an unrecognized X-Server-Function-Format tag before the decode switch runs. The content-type sniffing branches (there for untagged form posts) matched regardless of the tag, so a body tagged with a format this build has no case for — version skew from a newer peer, or a duplicated header that Headers.get joins into one unknown value — was silently reinterpreted as a form and the function ran on an argument it was never sent. Such bodies now answer 400 before dispatch, with a development message naming version skew; untagged bodies keep the sniffing, and an untagged empty body stays a zero-argument call (Zero-argument server function calls 400 behind hosts that convert Node requests (empty POST body stream parses as an argument) #3214).

  • 3393fb6: Refuse to flash when no storable cookie exists for a no-JS outcome (The degrade ladder bounds every field but url, so the cookie is discarded whole while claiming it fit #3249). The degrade ladder (The no-JS flash cookie has no size bound — an outcome past the browser's ceiling vanishes silently #3137) bounds the input echo and the result but never looked at url — pathname + search of a request the caller chose — so a long enough form action pushed the fully-degraded payload past the ~4 KB cookie ceiling and the encoder emitted a cookie the browser discards whole, with truncated: true inside asserting a degradation that never stored. encodeFlashCookie now returns null when even the degraded payload cannot fit, and the no-JS handler falls back to the plain redirect — never an oversized cookie, never a url truncated to a prefix that would attach the outcome to a submission it does not identify. Cookie naming, attributes, and refusal/redirect statuses are untouched (The flash cookie carries the submission with no SameSite, no lifetime and no __Host- prefix #3239, A form navigation refused before dispatch is left on /_server/<id> with everything the user typed gone #3250 pending).

  • d601119: Remove the experimental patch channel and patch-mode list driver (always opt-in, never default). Graph-native regions own value delivery and the unified-For design owns list structure, so the channel's parallel delivery machinery is retired: patch.ts/patch-driver.ts deleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw, patchDriver/rowProof/driveList) removed, the patchDriver compiler option dropped from both compilers, the insert $ll seam stripped, and the write-side channel struct dieted to the single written-keys bound (t.wk) the core fold/notify paths actually use. Store-family app bundles reclaim up to ~900 B brotli; every measured tier shrinks.

  • ace227e: Support imagesrcset and imagesizes in typed image preloads, including the standard form without href. Candidate URLs inside imagesrcset must already be resolved by the integration.

    The responsive pair is image-only. On any other destination the attribute is dropped and the link still ships — an integration that computes imagesrcset for every asset keeps its script and style preloads. An empty or non-string value counts as absent for the same reason, so a source set is never emitted as garbage the browser cannot parse. A descriptor whose only source was such a filtered attribute is dropped entirely rather than emitted as a <link rel="preload"> with nothing to fetch.

    mountHeadResource can adopt a source-set link: it has no href, so it matches a server-emitted link on a null href plus the identity qualifiers — the rule the frame client already applied.

    Development builds warn when imagesrcset uses a width descriptor without imagesizes (the source size falls back to 100vw, so the preload can miss the image the <img> selects), and when a manifest source set carries a relative candidate — candidates are not joined with _base, so they resolve against the document URL whichever base the manifest declares. That check walks the source set the way the spec's parser does, so commas inside a candidate URL are not mistaken for candidate separators.

  • 84a94bc: Scope deferred work nested inside plain-object and array carriers to the producing call's request event (A generator or stream returned inside a container is scoped to no request #3241, completing Generator server function bodies run outside provideEvent: they read the puller's request event, and direct calls clobber each other's locals #3222). The HTTP road already applied the wrapping in the encoded representation (the guard walk's rebuilt shells); the direct SSR road only looked at the returned value itself, so return { rows: cursor() } ran its generator under the render's ambient event — two concurrent direct calls read and wrote each other's locals, and the render's own. The direct road now descends plain-object/array carriers and hands the caller a shallow-rebuilt carrier with the bound wrappers in the deferred slots; the user's returned containers are never written into, and results with nothing deferred keep their identity. Set/Map members, class instances, and frozen/non-writable slots are deliberately out of the carrier set (pinned by test): bodies reached through them stay bound to nothing, as before.

  • a1ff286: Run transformResult for plain thrown errors as its documentation already promises: the hook now runs once at the thrown path's entry (context.thrown set) for every thrown value — not only thrown Response/envelope shapes — and the response tail is selected from its output, while the wire stays sanitized and a hook that itself throws is contained as a sanitized 500 (transformResult sees every failure an author shaped by hand and none that happen to the app #3247).

  • Updated dependencies [215de3b]

  • Updated dependencies [3424f9a]

  • Updated dependencies [d601119]

  • Updated dependencies [ac5159a]

  • Updated dependencies [de1c8b5]

    • solid-js@2.0.0-rc.7

test-integration@2.0.0-rc.7

Patch Changes

  • Updated dependencies [ead7b1a]
  • Updated dependencies [215de3b]
  • Updated dependencies [1226381]
  • Updated dependencies [7009adf]
  • Updated dependencies [a14c138]
  • Updated dependencies [ae46c92]
  • Updated dependencies [c08e974]
  • Updated dependencies [fbe5bef]
  • Updated dependencies [292bdc5]
  • Updated dependencies [285a717]
  • Updated dependencies [8f11ea7]
  • Updated dependencies [d0ca3a4]
  • Updated dependencies [fc7e626]
  • Updated dependencies [d50e855]
  • Updated dependencies [8f9f369]
  • Updated dependencies [3424f9a]
  • Updated dependencies [b3586e8]
  • Updated dependencies [f21e060]
  • Updated dependencies [5cee0f7]
  • Updated dependencies [0653673]
  • Updated dependencies [6bb51c9]
  • Updated dependencies [067e3bc]
  • Updated dependencies [8a65e5e]
  • Updated dependencies [ff2ecf1]
  • Updated dependencies [c0bc9ba]
  • Updated dependencies [ace227e]
  • Updated dependencies [b7b17ab]
  • Updated dependencies [f24e53d]
  • Updated dependencies [ed6b605]
  • Updated dependencies [6c9f8f4]
  • Updated dependencies [3393fb6]
  • Updated dependencies [fa568d3]
  • Updated dependencies [d601119]
  • Updated dependencies [ac5159a]
  • Updated dependencies [ace227e]
  • Updated dependencies [de1c8b5]
  • Updated dependencies [84a94bc]
  • Updated dependencies [e346e61]
  • Updated dependencies [e346e61]
  • Updated dependencies [0255729]
  • Updated dependencies [a1ff286]
    • @solidjs/babel-plugin@2.0.0-rc.7
    • @solidjs/signals@2.0.0-rc.7
    • solid-js@2.0.0-rc.7
    • @solidjs/web@2.0.0-rc.7
    • @solidjs/universal@2.0.0-rc.7
    • @solidjs/h@2.0.0-rc.7
    • @solidjs/html@2.0.0-rc.7

@github-actions
github-actions Bot force-pushed the changeset-release/next branch 30 times, most recently from f5b7e71 to be7d769 Compare September 4, 2026 20:47
@github-actions
github-actions Bot force-pushed the changeset-release/next branch 3 times, most recently from 3d10365 to 3c11f1a Compare September 4, 2026 21:42
@github-actions
github-actions Bot force-pushed the changeset-release/next branch from 3c11f1a to b142842 Compare September 5, 2026 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants