Patch Changes
-
01ac18c: Compiler
componentNamesoption: component owner labels that survive minification. With the flag on, DOM output carries the tag as written in source as a thirdcreateComponentargument —<Home />compiles tocreateComponent(Home, props, "Home"),<Ui.Button />to"Ui.Button",<this.Row />to"this.Row"— and the dev and observe runtimes label the component's owner with it (<Home>in diagnosticownerPaths, attribution chains, and the devtools_component.name), falling back toComp.nameas before. Until now an observe-tier production bundle reported hot scopes and holds under whatever the minifier left of the function name (<Xt> › <Kn>), and alazy()or HMR wrapper hid the tag name even in dev. Off by default and byte-identical output when off; SSR (which inlines the call) and universal output never emit it; the productioncreateComponentignores the argument. Both compilers implement it in parity (shared fixtures, cross-mode ratchet).@solidjs/vite-pluginenables it for the dev andobservepostures. -
7d985b6: Fix SSR XSS: strings yielded by flow-control memos rendered unescaped
<Show when={s}>{s}</Show>,<For>{v => v}</For>,<Dynamic component={() => s} />,
<Switch>/<Match>, boundary fallbacks and any component that returns a string through a
memo rendered that string raw on the server. The server flow controls return memos for
hydration-id alignment;escape()passed functions through by identity, and the resolver
appended whatever they later produced without escaping.One rule now:
escape(x)at a hole covers everything reachable fromx— strings, array
items, and what a function yields when the resolver calls it (a deferred-escape wrapper).
Finished{ t }nodes pass through.Loadingescapes its content the way it already
escaped its fallback. The compilers stop wrapping fragment / mixed component children in
_$escape(they are values; escaping them too double-escaped through
<Comp>{props.children}</Comp>), and a single-expression fragment at a hole keeps the
hole's wrap. Live-hole tags ride the wrapper and$slotsurvives the array copy, so
frames behave as before. -
ab4c40c: Object-valued
style/classbindings are read in the TRACKED half of their effect.style()andclassName()enumerate their object in the effect's untracked commit phase, so a proxy value — a store sub-object (style={state.style},class={row.classes}), merged props, anything arriving through a spread — was identity-reactive only: in-place key mutations never re-applied, and every leaf read trippedSTRICT_READ_UNTRACKEDin dev. Both compilers now wrap the compute value of a non-inlinestyle={expr}/class={expr}in a new compiler primitive,readShallow(), andspread()applies it to those two keys as it copies.readShallowis an identity passthrough for strings, plain objects and proxy-free arrays (a fresh literal is already the compute's own — the common case pays atypeof); a proxy is copied with oneownKeystrap (its own trap keeps the key set tracked) plus one tracked read per key; arrays are re-mapped only when an element is a proxy. Inline literals are untouched — they already compile per property. Provably-string expressions (string/template literals, concatenation) and literal objects/arrays skip the wrap at compile time. New Tier-1 benchstyle-class-object: plain-object rows at parity; store-backed rows go from identity-only (and, in dev, ~97 ms per 500 elements of diagnostics) to per-key reactive at ~3.5 ms. Octane svg-dashboard (prod build, store-backed style/attrs through spread): mount at parity, style_spread_pulse −6%, select_toggle −7%.spread()shares the same enumeration: its compute half copied the source withfor…in+hasOwn, which on a proxy source (merge()/omit(),{...props}in a component, store records — nearly every spread) is anownKeystrap plus twogetOwnPropertyDescriptortraps per key, each allocating a descriptor and a getter closure. It now takes the key set from oneReflect.ownKeystrap (the trap keeps the key set tracked) and reads each string key once; plain sources useObject.keys, the exact own-enumerable set the old loop yielded. New Tier-1 benchspread-enumerate(500 elements, 8 keys):merge(static, reactive)376 → 537 ops/s (+43%), store record 253 → 415 ops/s (+64%), plain object at parity.