Release RC packages (rc) - #3255
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
github-actions
Bot
force-pushed
the
changeset-release/next
branch
30 times, most recently
from
September 4, 2026 20:47
f5b7e71 to
be7d769
Compare
github-actions
Bot
force-pushed
the
changeset-release/next
branch
3 times, most recently
from
September 4, 2026 21:42
3d10365 to
3c11f1a
Compare
github-actions
Bot
force-pushed
the
changeset-release/next
branch
from
September 5, 2026 08:50
3c11f1a to
b142842
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.7
Patch Changes
validaterejects document-shell templates (<html><head><body>) — fatal in client compiles since rc.5 made validate failures errors #3259). Thevalidatepass 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]validatewarns 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 fromtemplate()pointing athydrate()— the failure moved from every import to the one broken act.patch.ts/patch-driver.tsdeleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw,patchDriver/rowProof/driveList) removed, thepatchDrivercompiler option dropped from both compilers, the insert$llseam 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
validaterejects document-shell templates (<html><head><body>) — fatal in client compiles since rc.5 made validate failures errors #3259). Thevalidatepass 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]validatewarns 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 fromtemplate()pointing athydrate()— the failure moved from every import to the one broken act.patch.ts/patch-driver.tsdeleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw,patchDriver/rowProof/driveList) removed, thepatchDrivercompiler option dropped from both compilers, the insert$llseam 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 shareProjectionOptions, 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:
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.deep()silently unsubscribed from every untouched child after a parent-field edit: the walk bypasses the proxy traps, and a bareReflect.ownKeyson 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.privatizeCommittedregistered its clone only in the global lookup, but family targets resolve children throughfam.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 renderingundefined.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 thetransaction 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 triggersthe 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 scheduledroot 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)andcreateOptimistic(fn, seed)in the same spot showed it. Nothing hascommitted 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-beta
createOptimisticupdate is not visible while sibling<Loading>shows fallback #2933). Refetch flights declare exactly as before, so bareoptimistic 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 actionwrote to a derived store and later called
refresh(store), the lift of themanual-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 refetchwas treated as a brand-new question and pended every leaf — every sibling
row lit up
isPending, and a row-scopedaffects()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 pendinguntil 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'slaneSuspends. 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); inlaneSuspendsonly 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.tsdeleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw,patchDriver/rowProof/driveList) removed, thepatchDrivercompiler option dropped from both compilers, the insert$llseam 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 derivedcreateOptimisticStoreacceptPartial<T>seeds again, on maintainer review: requiring a fullTforces callers to fabricate a throwaway complete object in the common async case — any object store reconciling on a non-idkey 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,shallowin options,Refreshablederived returns) is unaffected.e346e61: Store leaf nodes ride
slotSignal— one pre-shaped literal with_host/_keybackrefs 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)'swaiter delivers the store,
Promise.resolve(store),return storefrom anasync function — makes the engine read
store.thensynchronously in thecaller's scope. When that scope carries a strict-read label (an effect
callback, a component body) the read produced a spurious
STRICT_READ_UNTRACKEDwarning, and against a refetching derived store itcould escalate to the
PENDING_ASYNC_UNTRACKED_READthrow, rejecting thepromise being resolved.
await refresh(list)inside an action logged thewarning on every call. The
thenprobe is not a read the user wrote and isnow exempt from both.
solid-js@2.0.0-rc.7
Patch Changes
StoreOptions, projection forms shareProjectionOptions, plain optimistic stores expose their existing options argument, and derived optimistic stores are typed as refreshable.patch.ts/patch-driver.tsdeleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw,patchDriver/rowProof/driveList) removed, thepatchDrivercompiler option dropped from both compilers, the insert$llseam 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.Store<T>instead of adding a shallow readonly mapping.createStore,createProjection, and derivedcreateOptimisticStoreacceptPartial<T>seeds again, on maintainer review: requiring a fullTforces callers to fabricate a throwaway complete object in the common async case — any object store reconciling on a non-idkey 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,shallowin options,Refreshablederived returns) is unaffected.@solidjs/universal@2.0.0-rc.7
Patch Changes
patch.ts/patch-driver.tsdeleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw,patchDriver/rowProof/driveList) removed, thepatchDrivercompiler option dropped from both compilers, the insert$llseam 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/web@2.0.0-rc.7
Patch Changes
1226381: Bind
GET()grants to the function identity they were declared about (AGET()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, soregister -> 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 singledeclaresRead(id)check governs both dispatch and the 405Allowadvertisement; a stale or unverifiable declaration fails closed (GET refused, POST + origin gate required). A declaration orwithMeta({ 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
bodySizeLimitinto 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
wrapInvocationoption as entry-only (A per-handlerwrapInvocationnever 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 theglobalThis.__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 carriesSameSite=LaxandMax-Age=60, andencodeFlashCookie/decodeFlashCookieare 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
provideEventOnceseam, so a hook that double-invokes or skips the callback fails loudly during a render instead of silently double-committing a mutation or answeringundefined, 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
PromiseConstructornode 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 promiseownDecodedPromisesnever 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.pbefore 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 throughgetOwnPropertyNames— so a rejected promise or erroring stream parked on a non-enumerable slot (causeis 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'ss.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 asurl, bound arguments prepended toinput(which the argument parser's?argsprepend already provided).b3586e8: Validate document-shell templates in the document context ([compiler]
validaterejects document-shell templates (<html><head><body>) — fatal in client compiles since rc.5 made validate failures errors #3259). Thevalidatepass 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]validatewarns 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 fromtemplate()pointing athydrate()— 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,Responseshape) rather than by truthiness, and dispatch no longer erodes a returnednulltoundefinedon its way to the handler; anundefinedoutcome 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
-0off the server-function JSON fast path.JSON.stringify(-0)is"0", so a signed zero admitted byisJSONSaferode the fast path and arrived as+0— a silent sign flip on the exact guard that already refusesNaNand the infinities for the same reason.-0now 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
guardedPromiseownership (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
transformFlightResultResponse 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.falsenow means absent, matching both attribute writers:crossorigin={cond && "anonymous"}no longer emits a second, byte-identical link when the condition is false.crossoriginis 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"andtype: "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
extractBodyown 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 inbufferBodyWithin(A client disconnect on a chunked upload rejects out of handleServerFunctionRequest instead of answering a status #3217–The 413 refusal cancels a tee branch, never the upload source #3219).decodeResponsekeeps 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 soevent.requeststays 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
wrapInvocationvalues (AwrapInvocationoption that is not a hook removes the configured authorization gate #3238). A value other than a function orundefined—null,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 namingwrapInvocationand the received type;undefinedstays the one spelling of absence.6c9f8f4: Refuse an unrecognized
X-Server-Function-Formattag 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 thatHeaders.getjoins 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 aturl— 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, withtruncated: trueinside asserting a degradation that never stored.encodeFlashCookienow returnsnullwhen 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 noSameSite, 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.tsdeleted, the compiler-contract exports (registerPatch/registerRowOps/registerSlotPatch/patchableRaw,patchDriver/rowProof/driveList) removed, thepatchDrivercompiler option dropped from both compilers, the insert$llseam 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
imagesrcsetandimagesizesin typed image preloads, including the standard form withouthref. Candidate URLs insideimagesrcsetmust 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
imagesrcsetfor 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.mountHeadResourcecan 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
imagesrcsetuses a width descriptor withoutimagesizes(the source size falls back to100vw, 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'slocals, 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
transformResultfor plain thrown errors as its documentation already promises: the hook now runs once at the thrown path's entry (context.thrownset) 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 (transformResultsees 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]
test-integration@2.0.0-rc.7
Patch Changes