Patch Changes
-
#4401
9411bbeThanks @DylanPiercey! - Call the change handler when assigning a name destructured from a property another destructure also declares, such asbin<const/{ a }=input>beside<const/{ a: b }=input>. The second name is read as the first, so assigning it now assigns the first, where it used to compile to a value that went nowhere. A property destructured by a string key, such as"my-key", also no longer produces an invalid server destructure for its change handler. -
#4406
9d7a771Thanks @DylanPiercey! - Write the assets a lazily loaded tag needs where nothing removes them. Those found before the page's<head>renders go in it, or ahead of the first flush on a page without one, so a lazily loaded layout's assets no longer precede its doctype. After that they're written where the tag renders, and when that content may be removed (by a@catch, by the body replacing a@placeholder, or by client control flow), its stylesheets are also copied into the<head>so the tag stays styled when it renders again. A tag whose assets or load trigger a@catchdropped writes them again. Assets used to be written all at once where the first lazy tag rendered, so a@catchreplacing that content could drop the page's entry script, and the stylesheets, modules and load triggers other instances of the tag needed. A load trigger now inserts its module into the<head>. -
#4400
6bba1bcThanks @DylanPiercey! - Leave nothing of a caught<try>body live after the page resumes. Sections the body rendered before its@catchfired no longer stay subscribed to closures, which threw on the client once the closure changed. A@catchthat renders after its<try>already streamed is no longer treated as a<try>itself, so an error thrown in it reaches the enclosing@catchinstead of re-rendering the same@catch. -
#4402
b6486e9Thanks @DylanPiercey! - Fix Tags API<try>content rendered with Class API components on the server. Tags API content inside a Class API component now stops rendering when a<try>around it catches, at any depth and even when it was still awaiting, instead of sending its data and effects for content that never arrived, and its effects wait for in-order content still streaming and drop with a@catch, like any content around them. A Class API component's init code no longer takes the page's out-of-order content with it, which lost a@catchsent after its body streamed and ran its effects early. On a Class API page, a Tags API@catchthat waits on content of its own now shows, streamed after the markers it replaces even while a pending Class API<await>holds them back. -
#4410
7756061Thanks @DylanPiercey! - Write a Class API lazy tag's assets through the Tags API writer when it renders within Tags content. It used to write every pending asset inline, the page's entry script included, so a Tags@catchthat replaced that content left the page unable to hydrate, and the lazy module could be lost for other instances of the tag. -
#4405
bbd3f8cThanks @DylanPiercey! - A toggled class may not repeat a name the rest of itsclassvalue writes:class=["a", { a: on }]is now a compile error, and a stylesheet module read that repeats one only while rendering throws in development. In exchange the client toggles single classes instead of rewriting the attribute:class=["a", on && "b"]and computed keys such as{ [KEY]: on }now toggleb, keepingain the template. -
#4395
2166e2aThanks @DylanPiercey! - Keep the effects of content streamed before a<try>when its@catchreplaces a body that was still streaming, including lazily loaded content and content a@placeholderswapped in meanwhile. The caught body's own effects, lazy content and placeholders still drop, and so now do those of a caught<try>inside content streamed out of order. Effects written by the page before lazily loaded content that holds the stream now run with the page, instead of waiting for that content's module. Held effects of lazily loaded content now run in stream order. -
#4408
98e6b85Thanks @DylanPiercey! - Keep a<try>'s@placeholderuntil a lazily loaded tag in its body has inserted when the tag's module was already loaded, for example by the same tag in the placeholder, but its input was not. The body used to swap in before the tag's content, running its effects early. A lazily loaded tag also no longer throwsNotFoundErroron the client when its input lands after the<try>around it moved its content to show or dismiss the placeholder. -
#4409
b78fd9cThanks @DylanPiercey! - Resolve a lazily loaded tag's assets through the asset runtime its importing template passes, instead of one only a page entry of the same API sets. A Class API lazy tag no longer throwsassetFlush is not a functionon a Tags API page, and a Tags API lazy tag no longer renders nothing on a Class API page. -
#4403
7f17150Thanks @DylanPiercey! - FixUnable to serialize a value shared between independently lazy loaded contentwhen a@placeholdershares a value with a lazily loaded tag in it or before it. The placeholder's data now serializes first, and the lazy tag reads the value back from it. -
#4396
7a7c6acThanks @DylanPiercey! - Read a tag variable's property from its object once any code assigns that property in place, such aslive.open = trueorbox.count++. Reads used to go through a copy of the property taken when the variable itself last changed, so a handler,<lifecycle>listener or<script>reading it after another one assigned it saw the old value. This includes a name destructured from the variable, such asopenin<const/{ open }=live>, and properties assigned deeper in, such aslive.nested.depth = 2. -
#4404
eeabb88Thanks @DylanPiercey! - Let a<define>that calls itself, or a template that renders itself, pass its input per prop once its body is analyzed. A whole read of the input that nothing ends up using, such as an unread<const/all=input>, used to make the inner call build and pass one object through an extra intersection. -
#4396
7a7c6acThanks @DylanPiercey! - Report a compile error when code assigns a rest element, such asrestin<const/{ ...rest }=input.obj>orargsin<for|...args| of=list>. A rest has no change handler to receive a new value, so the assignment used to compile into one that did nothing. Assigning a member of a rest taken beside other names, such asrest.b = 5with<const/{ a, ...rest }=input.obj>, is also an error: that rest is a copy rebuilt whenever its source changes, so later reads never saw the assignment. -
#4398
0e118c3Thanks @DylanPiercey! - Report a compile error when module level code, astatic,server,clientorexportstatement, references a name that exists only while the template renders: a tag variable or parameter,input,$globalor$signal. Such code runs once as the template loads, soexport { count }for a<let/count>, or a static function reading or assigning it, used to compile and then fail when the module loaded or the function ran. -
#4407
10b2e75Thanks @DylanPiercey! - Resume a@catchthat streams after its<try>'s body inside the<try>'s branch, so removing the content around the<try>also stops the catch's effects and closures. It used to stream under an id the client could not tie to any branch, leaving the removed catch running. Content streamed after a@placeholderbody's reorder is also no longer adopted into its<try>when the page's client script runs late, which froze the page once the<try>was removed. -
#4405
bbd3f8cThanks @DylanPiercey! - Render aclassbuilt from stylesheet module reads (CSS modules, vanilla-extract.css.ts, or a<style/styles>block) like a literal class. The client template holds it and toggles such as[styles.a, active && styles.b]or{ [styles.b]: active }update only that class; the server computes each combination's markup once as the module loads instead of on every render. -
#4399
f9d4412Thanks @DylanPiercey! - Build a new array for a whole-array rest such as<const/[...chars]=text>, as destructuring does, instead of reading it as the value it rests. A string or other iterable source used to be read directly, sochars.join("-")threw in the browser, and on the server when the rest was read in another section.