github marko-js/marko @marko/runtime-tags@6.4.1

3 hours ago

Patch Changes

  • #4378 79b3092 Thanks @DylanPiercey! - Fix a handler inside an <if> or <for> throwing after resume when the branch's condition reads state assigned only by code that never runs in the browser. Such a branch's owner is now resumed from the payload, since the branch's own runtime is not in the page's bundle to link it by its marker.

  • #4391 96848cc Thanks @DylanPiercey! - Stream a <try>'s @catch in its body's place, so it shows without JavaScript. When none of the body has streamed yet, the @catch takes its place outright. Once part of the body has streamed, the @catch follows it and an empty reorder removes that part. A @catch with an <await> of its own still streams out of order, so nothing after it waits. A <try> whose body settles before the stream reaches it no longer writes reorder markers, and a @catch that throws partway no longer streams its partial content.

  • #4374 33b61a7 Thanks @DylanPiercey! - Drop a <const/b=a> that nothing reads, together with an a only it read, instead of keeping both in the server output.

  • #4367 8775e27 Thanks @DylanPiercey! - Resume each <if>, <for> and <show> by its own condition. One whose condition reads only input no longer resumes as though it could change in the browser just because another tag of the same kind in the same content has a condition that reads state.

  • #4366 70a0594 Thanks @DylanPiercey! - Fix a <define> or template that renders itself throwing after the page resumes when its input is read whole somewhere pruning removes, such as an unread <const/all=input/>.

  • #4355 28705bd Thanks @DylanPiercey! - Report in development when a resumed unescaped placeholder ($!{}) rendered HTML that is not a balanced fragment, such as a truncated excerpt with an unclosed tag, since updating it would remove the wrong nodes.

  • #4355 28705bd Thanks @DylanPiercey! - Stop re-parsing an unescaped placeholder's ($!{}) markup when it updates to equal markup, which lost focus, <details> state and element identity inside it, including on the first update after the page resumes.

  • #4388 d290dd8 Thanks @DylanPiercey! - Speed up streaming pages with many <try> tags or many out-of-order @placeholder parts still waiting. Each <try> no longer creates an AbortController or adds an abort listener to the one around it, and parts waiting in a reorder no longer get rechecked on every flush. Content that a caught <try> body's <await> rendered no longer streams.

  • #4370 8706358 Thanks @DylanPiercey! - Stop rejecting a <for> whose by= names a loop param at compile time, a check that also rejected an outer binding sharing a param's name. Keying by a param now fails at render, since by= is evaluated before the loop runs.

  • #4367 8775e27 Thanks @DylanPiercey! - Resume functions written in a <for> loop's items, such as <for|fn| of=[() => 1]> or of=[{ f: () => n++ }], when the loop's content keeps one for the browser. They were never registered, so the page could not serialize them. A function reaching the items through a call (of=[fn].concat(list)) is still not registered.

  • #4387 67a4665 Thanks @DylanPiercey! - Fix compile crashes when a tag variable declared in one branch, such as an <if>, is read from content inside another branch, such as its <else>, and when a hoisted tag variable is the value of a <const> or is spread onto a tag. A read only goes through a closure when JavaScript's scoping would allow it; any other read of a tag variable, including one above its declaration, goes through the hoisted variable alone, without an unused closure. A hoisted read also keeps the owner scopes only up to the section its getter is in, so fewer scopes serialize their owner.

  • #4393 d6f7051 Thanks @DylanPiercey! - Fix a tag variable hoisted out of one branch of an <if>/<else> chain reading the other branch when its own is not rendered. Calling it returned whatever the rendered branch held in the same place, such as one of its elements in an optimized build, and iterating it yielded that value; it now returns undefined and yields nothing.

  • #4374 33b61a7 Thanks @DylanPiercey! - Stop resuming every section around a tag variable that is read before its declaration in the same content (each enclosing <if>, <for>, <await>, <try> and tag body), as though the read came from outside them.

  • #4383 f8c44b4 Thanks @DylanPiercey! - Stop the server output from declaring a <const> that aliases another value, or the parts destructured from one: each read is written as what it reads. A pattern holding a rest is still declared as written, since the rest needs it. In the browser output, an expression that reads both a value and its properties keeps its own optional chaining, rather than guarding only the first property.

  • #4385 2e71ddc Thanks @DylanPiercey! - Fix $global and $signal inside <html-comment>. A $global read there threw $global is not defined during the server render, and $signal crashed the client compile instead of giving the comment's expression its own abort signal.

  • #4374 33b61a7 Thanks @DylanPiercey! - Drop an <id> whose variable nothing reads instead of minting an id for it.

  • #4356 6a048d5 Thanks @DylanPiercey! - Keep values reachable when later resume data reuses them. A value first sent with the loop values or closures of content passed to a dynamic tag no longer throws on the server (leaving the stream open) when a later flush reuses it, and a value the main stream sent stays reachable from the main stream after a lazily loaded tag's data reuses it, instead of aborting debug renders and being dropped from optimized ones. Content passed to a dynamic tag that reads closures from more than one owner now always links those owners, so it no longer throws on resume when an owner's scope data arrives after it.

  • #4374 33b61a7 Thanks @DylanPiercey! - Drop a controlled <let> (one with a valueChange) that nothing reads or assigns in emitted code, as an uncontrolled one already is, instead of shipping its signals and its change handler. Its impure values still run, in both outputs, with what they read.

  • #4366 70a0594 Thanks @DylanPiercey! - Stop shipping an empty setup call for a controllable element whose value and change handler come before a spread (<select value=x valueChange=y ...attrs>), and for an <html-script> or <html-style> whose spread writes its nonce.

  • #4382 0ef1dd1 Thanks @DylanPiercey! - Stop guarding reads that can never be nullish with optional chaining in the browser output: a value destructured only through a nested pattern, such as <const/{ a: { b } }=obj/>, since destructuring already throws when it is nullish, and a tag's params, which are always an array.

  • #4384 3a6135e Thanks @DylanPiercey! - An <if>, <for> or <show> whose only siblings are components that render nothing is addressed by its element, without a marker of its own, as it already was beside a <let> or the rest of an <if> chain.

  • #4374 33b61a7 Thanks @DylanPiercey! - Let an <if>, <for> or <show> use its parent element as its marker when its only siblings render nothing (such as <let>, <const>, <script> or a scriptlet), as it already did when it was the only child.

  • #4390 c3b0ff7 Thanks @DylanPiercey! - Fix a @placeholder that throws while the page streams. The stream no longer ends early, an outer @placeholder no longer stays on the page forever, the server no longer crashes with Cannot read properties of null (reading 'next'), and the effects of the <try> body it replaces no longer run. A @placeholder inside a caught <try> body no longer renders.

  • #4392 05b1590 Thanks @DylanPiercey! - Report a compile error when code assigns a variable that comes from array destructuring, such as x in <const/[x]=input.list> or key in <for|[key, value]| of=entries>. An array has no change handler to receive the new value, so this used to compile into a server render that threw a ReferenceError and a client handler that threw when called. Assigning a variable destructured from an object, including an object inside an array, still calls that object's change handler.

  • #4377 af210b3 Thanks @DylanPiercey! - Fix client rendering of a branch holding a Class API tag defined only by a renderer: the tag now keeps its marker, so the nodes after it are found where the walk stores them.

  • #4359 77a91db Thanks @DylanPiercey! - Fix a <try>'s @placeholder staying on the page forever when a nested <try> streamed in its body: a nested @placeholder before the body's first <await>, a nested @catch that fired while earlier content held the stream, or a nested @placeholder that throws, which now shows the outer @catch. The inline reorder runtime is also smaller.

  • #4353 536a056 Thanks @DylanPiercey! - Fix a resumed page running one <script> twice and never running another, or leaving content un-updated, when nested content reads a variable from an outer section that has the same name as one of its own.

  • #4386 c8dbc4f Thanks @DylanPiercey! - Fix a ReferenceError on the server when a <define> tag that is only ever rendered directly (<Foo/>), or never used, has attributes reading a variable nothing else reads. The server no longer evaluates those attributes, matching the browser, so an attribute with a side effect no longer runs only on the server.

  • #4374 33b61a7 Thanks @DylanPiercey! - Apply a native spread of an alias of a <const> alias, such as <const/o=input.attrs/><const/p=o/><div ...p/>, on the client. It read a value its source never stored, so the attributes were missing after a client render.

  • #4376 067f904 Thanks @DylanPiercey! - In development, reading a custom tag's variable in its own body before the tag's <return> now throws "Cannot access before initialization" in the browser even when the read shares an expression with other values (such as ${x + y}), instead of silently reading undefined. A <define> tag's variable read in its own body (such as a recursive <${0 || Foo}/>) no longer throws that error in the browser, since its value never comes from a <return>.

  • #4374 33b61a7 Thanks @DylanPiercey! - Stop looking up an element or <html-comment> on the client when nothing reads its tag variable, and write an unread <html-comment/c> without the space a resumed one needs.

  • #4389 2906a96 Thanks @DylanPiercey! - Stop rendering a <try> body past an error thrown in lazily loaded content, or in a nested <try> without a @catch. The rest of the body no longer streams next to the @catch, and the render no longer fails with Invalid value used as weak map key or stalls without ever showing the @catch.

  • #4355 28705bd Thanks @DylanPiercey! - Fix a Cannot read properties of null (reading 'namespaceURI') error when a <for> body is only an unescaped placeholder of a loop parameter (<for|html| of=list>$!{html}</for>). It threw on the first client render, and after resume whenever a row was added.

  • #4366 70a0594 Thanks @DylanPiercey! - Warn when a native tag's content attribute is ignored because the tag has a body, which always renders instead.

Don't miss a new marko release

NewReleases is sending notifications on new releases.