Patch Changes
-
8d6de07: Native elements with several spread sources compile to the runtimes' array form instead of a
mergeProps()call, in DOM and SSR output:<div id="x" {...a} {...b}>becomesspread(el, [{ id: "x" }, a, b], …)on the client andssrElement("div", [{ id: "x" }, a, b], …)on the server. The runtimes read the sources directly — later sources win per key, only the winning source is read — with no merge proxy to build and walk, and a reactive spread is a plain thunk called inside the tracking scope, so it mints no memo and consumes no hydration id on either side (the hydratable SSR() => mergeProps(…)wrapper is gone for the same reason). A lone spread still passes straight through (#3105). Requires@solidjs/webwith thespread/ssrElementarray forms (#3418, #3419). -
6d2bdeb: Move delegated event handlers off the
$$<type>element key Solid 1 uses.Solid 1 delegates from
documentand fires any$$click/$$input/… it finds while walking up from the target, so a 1.x runtime on the same page — an older embedded widget, a devtools panel built on 1.x — ran every delegated handler in a 2.x app a second time. Compiled output and the runtime now stamp_$$<type>/_$$<type>Datainstead; neither version can see the other's handlers, in either nesting direction.The key, the
_$SOLID_EVENT_OWNERmark, and the walk rules are documented inclient.tsas the delegated-event wire contract shared by every Solid copy on a page. Anything readingel.$$clickdirectly must switch toel._$$click. -
246eeeb: Emit non-identifier getter keys in compiled props literals as string literals (
get "aria-label"() {}) instead of computed keys (get ["aria-label"]() {}). Same property, but a computed key drops the whole object literal off V8's boilerplate path into per-property runtime definition; on a seven-getter props literal the computed form costs ~45% more to build. Applies to every getter site in both compilers: component props, dynamic element attributes (DOM, SSR, universal). -
63560a1:
componentNamesnow applies to SSR output. Under the option both compilers keep thecreateComponentcall they otherwise inline toComp(props)and pass the source tag name —createComponent(Comp, props, "Comp")— so the server runtime's observe/devcreateComponentlabels the owner and a server finding'sownerPathreads<App> › <Page>like the client's. Without the option (prod builds) SSR output is unchanged.@solidjs/vite-pluginalready passes the option for its dev and observe postures, so app server builds pick this up with no config change.Fixes
ssrScopeunder transparent owners: the virtual hole scope swapped the current owner's id counter, but content inside a hole resolves ids by walking past transparent owners, so with one in between (the server-component scope owner; now the labelled component owner) the hole's content took ids from the enclosing counter and disagreed with the client. The scope now swaps the nearest id-bearing owner. -
350f65f: TSRX:
@for … index/keyitems and@catcherrors pass through toFor/Erroredas the accessors Solid hands out; the compilers no longer rewrite reads of those bindings into calls (#3474). Authoritem(),i()(under a custom key), anderr()exactly as in JSX. A destructuring pattern in one of those positions is rejected with a diagnostic, since there is nothing to destructure — the default keyed@foritem is still a raw value and still destructures.projectTsrxForTypecheckemits the same(item, i) =>/(err, reset) =>arrows@tsrx/soliddoes, so the two typecheck projections now agree. -
1643d2a: The universal renderer's
spread()follows the@solidjs/webcontract (#3388):reffolds into the props effect and is re-applied only when its identity changes (refs run with no owner, so nothing they create is disposed by the fold); children keep their own ownedinsert— that effect owns the child subtree — but a plain object whosechildrenis a data property inserts the value with no effect at all. Three reactive nodes become two when children flow through the spread, one when they don't.spreadalso resolves a lone function source inside its own tracking scopes and accepts an array of sources —spread(node, [a, b], skipChildren)— the union of their keys with later sources winning, only the winning source read, function sources called inline with no merge and no memo. Both compilers' universal output uses it: a lone spread passes straight through (reactive included, no moremergeProps(() => …)), and several sources compile to the array instead of amergeProps()call.