Patch Changes
-
d70dda5: Carry authored
istanbul/c8ignore pragmas through the remaining #2138 cases: a pragma immediately before a component (including through a fragment) leads that component'schildrengetter, pragmas inside fragments are preserved, and SSR prop-hoist copies them onto the shared descriptor'sget(). -
bf71c28: DOM output no longer declares positional walks to nodes nothing reads. A text node ahead of an appended expression, like
User :in<h1>User : {name()}</h1>, used to getvar _el$3 = _el$2.firstChildeven though the insert appends with anullmarker. A minifier keeps that property read, since it could be a getter, so it shipped as_el$2.firstChild;. Both compilers now drop afirstChild/nextSiblingwalk when no later statement reads its node, including a walk that only fed another dropped walk. -
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). -
96ffcf7: Production builds compile a
<Show>that needs no component to the ternary it renders: nokeyed, no spread, onlywhenandfallback, with JSX children or a one-parameter callback whosewhenis a plain read (eachu()readswhenagain). Dev builds keep the component and its stale-read error. ThelowerShowoption overrides the default (!dev). The native compiler's SSR pass also no longer returns a TSRX module's static templates unescaped when one element in the module is marked as safe. -
b2cb0c7: The server build escapes string literals in a ternary branch, after
&&, and in everyreturnof a function child, including areturninsideif,switch,tryor a loop. The server now renders them as text, as the client does, in children and in attribute values (#4710). A function value in an attribute keeps its literals as written at every depth, because the server stringifies its source. -
701cbb3: SSR escapes the children of
<style>and<script>under<svg>and<math>. There they are ordinary elements whose text parses as markup, so only HTML-namespace<style>/<script>render raw text (#4704). -
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.