Repository navigation
@solidjs/web@2.0.0-rc.22
Pre-releasePatch Changes
-
366c0eb:
renderToStream().pipe()no longer throwsbuffer.flush is not a functionwhen the render is abandoned from inside its first write (#4745). With a shell of 16384 characters or more, a pre-flush redirect increateSSRResponse, a sink whosewritethrows or asignalaborted from inside that write leftpipeflushing a buffer that had noflush, and the unhandled rejection ended the process under Node's default handling. -
90d1a51: A viewer that joins a running
broadcastis sent each live range once, as it shows now. Its snapshot used to carry the frame as it first rendered and then every changed hole whole again, so a late joiner downloaded a big live table twice (about 600 ms to join a 2,000-row table, now about 120 ms). -
3ce08e9: A string
classvalue no longer stores a property on the element when it is rendered on the client.className()cleared its applied-classes snapshot withnode._$classes = undefinedbefore every string write, which added an own property to each element the first time its class was set, even though only an objectclassvalue ever fills that snapshot. It now clears the snapshot only when one exists. Mounting 1,000 table rows with six string class bindings each allocates about 118 KB less (1,793 KB to 1,675 KB), and a uibench tree render is 5 to 10% faster. Behavior is unchanged. The hydrating path still seeds the snapshot as before. -
1212095: Serializing a value that holds a cycle no longer copies the parts of it that have nothing to replace. An object an async memo answered with and a store also held stayed one object in the hydration data only when the store had no cycle; with one, the client got two copies (#4846).
-
8506dbf: fix(web): a
deferStreamsource that rejects on the server hydrates as a rejection, soreset()refetches it on the client (#4747) -
bd38a8f: Delegated events no longer keep an unmounted component alive through
currentTarget. Event delegation simulatedcurrentTargetwith a getter created for each event, and V8 can keep the first such getter in the shape every event of that type shares, along with the event, its target and the component around it.currentTargetis now set as a plain value when a delegated handler runs. -
c927463: fix(web):
useHeadtags of content behind a boundary's fallback are withdrawn while the fallback shows (an<Errored>keeps its content alive forreset(), so the error page kept the failed page's title) and come back when the content reveals (#4873) -
4ba1731: A controlled input no longer loses typed text when its signal write is held (an async derivation of it is pending) and another binding in the same template re-runs, such as a sibling
isPendingclass flipping: a stateful DOM prop (value,checked, …) in a grouped effect or a spread skips an unchanged write while the effect is a stale reader of an open hold, and the hold's landing writes the bound value (#4872). Outside a hold every run still writes (#2016, #4186). -
803d269: feat(web): dev warns
INVALID_HTML_NESTINGwhen hydration claims an element the browser's HTML parser moved out of its parent (invalid nesting across a component boundary:<div>in<p>,<a>in<a>,<tr>straight in<table>); the key-miss warning for a<form>names a form nested in a form (#4875) -
54456c9: A live server component's attribute whose value is still pending at the top of the render (no
<Loading>around it) no longer writes the live-hole comment markers inside the tag or the attribute value (<div<!--lh:1--> style="…"<!--lh:/1-->>), which broke the element. The element keeps its attribute address, and the binding registers once the tag's pending values resolve, so later values update the attribute as anattrop. -
c50abb6: A
dynamicmount of a live server component that switches arguments and comes back to its first call (a windowed view scrolling back to the slice the page was served with) shows that call again. The equals gate compared the incoming binding with the one the memo holds, which is the first resolution's, so the way back read as "nothing changed" and the mount stayed on the other address.A live connection cancelled before its body's
startarrived now reads as a death, and the loop reconnects. A remount replaying a warm store gives up on a row-op record by cancelling the new connection so the resume re-sends the hole whole; with nothing open yet, the end read as a completion and the mount was left with no live connection. -
f675c66: fix(web): a server function mutation with nothing folded and no metadata still reaches every flight consumer, so a router revalidates after a direct call or a core
action(#4883) -
5a05b21: A disposed
Portalno longer stays reachable through a live node of the same shape: every portal node shares one_$hostgetter that reads the slot's accessor from the node (#4852). -
246a491:
insertno longer carries the portal host tagging in a bundle that renders no<Portal>: Portal installs it on first use. A hand-writteninsert(..., { host })outside Portal now needsinstallHostTagging()first. -
32b4294: Fail renderToStream when the default serializer reports a synchronous error before the first flush, matching asynchronous failures. No HTML is sent, onCompleteAll is skipped, and createSSRResponse returns 500 when consuming the stream. An error an
<Errored>contained does not fail the render when it cannot be serialized: its record and the rejection of its source, deferStream or streamed, are sent as a plain Error with its message, the fallback stays, and the error hook hears the failure once. A rejection nothing contained still fails the render. -
218fe4a: The DOM list reconciler no longer throws
NotFoundErrorwhen user code moved a list node past the end of its list and the same update removes or replaces that node. The append step used the node after the list as its anchor even after the pass had taken it out of the parent; it now falls back to the marker, or the end of the parent. -
dfb1812: The DOM list reconciler does less work for common small edits. A node moved from one end of a list to the other takes one DOM move, a list whose nodes did not change returns before reading the parent, and the window map is an index stamp on the new nodes instead of a
Map. On the Octane board js-framework's reorder operations take about 20% less time and a text hole beside sibling nodes updates about 13% faster. Bundles with the web runtime are 33 bytes smaller minified. -
b38d592: List reconciliation moves every connected node with
Element.moveBefore()where the browser has it, not only the node holding focus, and no longer usesreplaceChild()there. Moved rows stay connected, so focus and other node state survive any reorder, and a reorder places nodes instead of detaching and reattaching them: dbmon's 1,000-row sort drops from ~2.0 ms to ~0.75 ms, and shuffles and reverses get 3–7% faster. The per-passdocument.activeElementread is gone. New nodes and browsers withoutmoveBefore()keepinsertBefore()as before. -
9c917ea: A ref callback that reads a sync memo on a row mounted while an async memo is in flight no longer leaves that update held forever (#4767). Refs run in the attribute effect's commit half with no owner; a memo born into the hold has only a staged value, and an ownerless read of it threw
NotReadyError(A19 exception 1), which errored the effect mid-hold so the transaction never landed.runRefCallbacknow marks the read, andservereturns the staged value only when the ref's creating pass was born into that memo's hold (F-7); productionref()always goes throughrunRefCallbackso the mark is present outside dev too. -
7230c08: A ref callback (
ref={el => …}) now runs the way a render effect's callback runs at creation (#4761). It is untracked and runs in the context of the pass that creates the element, so its reads see what that pass is building. Before, it ran with no owner, so its reads were outside reads that saw the screen before the pass committed. A non-keyed<Show>/<Match>branch that an optimistic write had hidden could not come back: its ref read the narrowed accessor, got the old falsy condition, and threw a stale read that halted the app.A ref still owns nothing. In dev, creating a memo, effect or root inside it throws
PRIMITIVE_IN_EFFECT_CALLBACK, andonCleanupinside it throwsCLEANUP_IN_FORBIDDEN_SCOPE. Set those up in the factory that returns the ref, which runs in the component body. Writes,refresh, action calls andonFlushstay allowed in a ref, as in an effect callback. -
c8c5eb1: Server rendering only treats nodes the runtime made as finished markup.
ssr(),ssrElement()and the frames sink now stamp their nodes with theSymbol.for("solid.ssrNode")symbol (as$, a value no data can hold), and every insert position checks it instead of the object's shape. A plain object with atkey (ort,handp), such as one parsed from JSON, is data: it renders nothing and gets the dev warning UNRECOGNIZED_INSERT_VALUE, like any other plain object. The async-memo landing check (ASYNC_MEMO_ELEMENT) uses the same brand, so such data now serializes like other data instead of being refused. Server only; no client bytes. -
eabc4c5: A bound
<select value>marks its matching<option selected>while the server renders, not in a pass over the finished html (#4891). The old pass was switched on for the whole process by a module-scopessrSelectValues()call in any module that had a bound select, so every render after it scanned its full html and every streamed fragment, even with no select in it. Both compilers now read the select's value once ahead of its children (ssrSelect) and keep it on a transparent owner the select's children render under (ssrIn). Each compiled server<option>asksssrOptionwhether it is selected. Options a<For>, a component or a later async pass renders inside the select are matched too, and a select whose options stream in after a<Loading>inside it is no longer left unmarked.ssrSelectValuesandresolveSSRSelectValuesare removed. A multiple select's bound value is matched as the client assigns it, entry by entry from an array, with no comma split. An option whose text content is markup (novalueattribute) is not matched. -
8a6de0f: Dev builds now warn with
STRICT_READ_UNTRACKED(#1742) when an element's event handler expression reads reactive state, e.g.onClick={selected() ? a : b}or aprops.onClickthe parent passed a reactive expression. A handler is bound once, where its element is created, so such a read is not meant to be reactive; the warning says to read the value inside the handler function instead. A pending async read there throwsPENDING_ASYNC_UNTRACKED_READ, as in a component body. The read still tracks, so dev re-mounts on a change exactly as production does.Production output is unchanged byte for byte. In dev DOM output both compilers wrap each handler expression that can read reactive state (anything but an identifier, an inline function or a literal), including the
[handler, data]form's bound values on delegated events, in a newstrictHandler(() => expr)helper from@solidjs/web. It readsexprthroughstrictReadTracked, a dev-only strict-read window that keeps tracking (internal, from@solidjs/signalsviasolid-js). No production-compiled module imports either, so they tree-shake away. -
7b405e9: Add
setTrustedTypesPolicy(policy), so Solid renders on pages that enforcerequire-trusted-types-for 'script'. The app passes a Trusted Types policy it created, and the runtime assigns theTrustedHTMLthat policy returns, for compiled template markup, for the server HTML the frames client parses, and for thehtmltagged template's text decoding. On the server it is a no-op, so an isomorphic entry can call it. Nothing changes for apps that do not call it. -
b3731b0: A text value that shares its parent with other children (
<p>Count: {n()}</p>) no longer reads the text node's.databefore each write. The node remembers the last value written and later updates compare against that, which takes a signal-driven text update from about 0.59 µs to about 0.35 µs. The first write to a node still compares with the DOM. One behavior difference: if something outside Solid rewrites such a text node and the value then re-evaluates to what Solid last wrote, the text is no longer written back. -
Updated dependencies [cf839ea]
-
Updated dependencies [8858189]
-
Updated dependencies [c927463]
-
Updated dependencies [4ba1731]
-
Updated dependencies [c50abb6]
-
Updated dependencies [e76279f]
-
Updated dependencies [32b4294]
-
Updated dependencies [9c917ea]
-
Updated dependencies [7230c08]
-
Updated dependencies [c8c5eb1]
-
Updated dependencies [231a3d8]
-
Updated dependencies [8a6de0f]
- solid-js@2.0.0-rc.22