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

4 hours ago

Minor Changes

  • #4343 c4a7d6c Thanks @DylanPiercey! - <try> now requires its <@catch> and <@placeholder> to be written directly inside it, once each, with only content. Placing either inside control flow such as <if> or <for>, repeating it, or giving it attributes is now a compile error that says how to fix it. A <try> with neither is also a compile error, since it had no effect.

Patch Changes

  • #4346 961a0c1 Thanks @DylanPiercey! - Fix interactive content inside an <await> stopping after resume once a later sibling <if> or <for> branch is removed. The removed branch had claimed the await content as its own, aborting its $signal and stopping its updates.

  • #4349 d210293 Thanks @DylanPiercey! - Fix a <try> @placeholder flashing its content and then showing again on the client when an <await> settles and its content, or the @catch content its rejection renders, starts another <await>. The placeholder now ends only once the renders of the settling update have run, so it stays up until the nested value settles, and resolved content no longer shows before it has finished rendering.

  • #4350 6f4f80c Thanks @DylanPiercey! - Fix a <try> @placeholder that could stay up for good. Removing content that holds a pending <await> now dismisses the placeholder, even when the promise never settles or settles in the same update that removes it. An <await> given a new value just as its previous one settles no longer throws or renders the older value.

  • #4317 bef2c30 Thanks @DylanPiercey! - Serialize a controllable <let>'s valueChange handler in a tag whose other state resumes only for its input, so when the parent passes constant input, an assignment after resume still calls the handler.

  • 2bf2f15 Thanks @DylanPiercey! - A template whose only client work lives in branches that read a tag variable from a sibling branch no longer fails to load with $setup is not defined. A <define> body that renders itself before its event handlers or other setup work now runs that setup in every nested call, not only the outermost one.

  • #4341 86c225d Thanks @DylanPiercey! - Fix a ReferenceError during server rendering when a custom tag receives an attribute tag, or an <if>/<for> of attribute tags, that it never reads and that reads a value nothing else uses. Attribute tags a tag never reads are now left out of both the server and browser output, as is content it never reads, whether passed as the tag's body or inside an attribute tag, so values read only there are no longer kept or serialized for it.

  • #4340 a18b26e Thanks @DylanPiercey! - Fix a ReferenceError in the browser for a dynamic tag with a body that chooses between imported templates (<${useB ? B : A}>Hello</>, <${show && A}>Hello</>): the body is now kept when only one of the templates reads input.content or when the name can be falsy, and left out of the browser code when nothing can render it.

  • #4322 9e61b54 Thanks @DylanPiercey! - Fix client rendering crashing or updating the wrong nodes when a tag that renders no DOM (for example one with only a <script>) is the only child of an element or sits next to text.

  • #4330 f15a75f Thanks @DylanPiercey! - Run the production CommonJS runtime (dist/html.js, dist/dom.js) in strict mode. The build moved module-scope declarations above its "use strict" directive, so the directive was dropped.

  • #4327 aa69f52 Thanks @DylanPiercey! - Keep a render's resume comments its own. An <html-comment> value that starts with the render's resume comment prefix (such as M_) is now escaped on the server, so resume no longer adopts it as a marker and writes updates into it. A page entry compiled with a runtimeId and rendered inside another page no longer switches the enclosing render's runtimeId, which left the outer page unable to resume; development builds report the nested mismatch, and also report two renders on a page whose $global.renderIds start one another.

  • #4342 e4ff095 Thanks @DylanPiercey! - Keep the key order of a child tag's rest input, such as ...rest from <const/{ first, ...rest }=input/>, the same in the browser as on the server when the parent passes attributes and attribute tags.

  • #4338 7fe4bad Thanks @DylanPiercey! - Fix content that resumes after its owner, such as content behind a <try> placeholder, keeping stale server-rendered values after the page changed a value it reads while it was pending. Its catch-up render now flushes as the content arrives instead of waiting for an unrelated update, and a <script> it re-runs does so then rather than during that later update. A <let> in that content keeps its server-rendered value instead of taking the changed initial value, as a <let> does whenever its value= changes.

  • #4333 e1733f1 Thanks @DylanPiercey! - Fix a Cannot read properties of undefined (reading 'parentNode') error in optimized builds when a lazily loaded tag (import ... with { load }) that renders a <try>, <await>, or other control flow is imported by a template with no client code of its own. The page entry now keeps that content's resume markers until its module loads.

  • #4350 6f4f80c Thanks @DylanPiercey! - Register a <lifecycle> tag's onDestroy without creating an AbortController for it. An error thrown from onDestroy now escapes the update, as one thrown from onMount or onUpdate does, instead of being reported from an abort event.

  • #4317 bef2c30 Thanks @DylanPiercey! - Abort a $signal read in <lifecycle> (or another tag whose attributes update together, like a dynamic tag) when those attributes update, and report the debug warning for an unserialized $global key read there or in an <if> condition.

  • #4338 7fe4bad Thanks @DylanPiercey! - Fix a Tags API parent that re-renders a Class API child, which renders Tags API content of its own, treating the rest of that update as a fresh render: a <let> after the class child followed its initial value instead of keeping its own, and the resumed page threw Cannot read properties of undefined. That Tags API content now renders, and runs its effects, as part of the parent's update, so a change to its own state in the same update renders once.

  • #4322 9e61b54 Thanks @DylanPiercey! - Keep an <if>, <for>, or other control flow tag that is the only child of <html>, <head>, or <body> from removing nodes it did not render (such as resume scripts or injected elements) when it updates, and from skipping the asset flush before </head>, which put page assets ahead of the doctype.

  • #4321 51f693a Thanks @DylanPiercey! - Fix a Cannot read properties of undefined error after resume when a template or <define> that renders itself reads the tag variable of its recursive call and that returned value changes in the browser.

  • #4342 e4ff095 Thanks @DylanPiercey! - Fix a child tag that reads members of a repeated attribute tag, such as input.item.foo with two <@item> tags, showing the last <@item> in the browser instead of the first, and a Cannot read properties of undefined error on the first update after resume. A later <@item> that nests an attribute tag in <if> or <for> no longer throws a ReferenceError in the browser.

  • #4334 2048f4b Thanks @DylanPiercey! - Compile a template edited under a warm compile cache to the same output as a cold compile. Generated names and register ids no longer keep counting from the template's previous analysis ($template2, …/inc2), so a server and client whose caches saw different edits agree on register ids.

  • #4323 e04b368 Thanks @DylanPiercey! - Fix server-rendered <for> and <if> content that removed the wrong nodes after resume. A branch whose content is only a ${} or $!{} placeholder now resumes as a range, so removing it no longer takes a neighboring element or text with it, or leaves part of its unescaped HTML behind. A single-element loop item that streamed in across several flushes now removes its element instead of only a resume comment.

  • #4335 bc8add9 Thanks @DylanPiercey! - In debug builds, report a locked ReadableStream sent to the browser instead of silently dropping it, and say in the unserialized $global read warning that serialized globals are embedded in the page, so only non-secret values belong in serializedGlobals.

  • #4335 bc8add9 Thanks @DylanPiercey! - Write an error's or typed array's constructor name from the built-in the serializer matched instead of from the value itself. An own constructor property, such as one Object.assign(new Error(message), JSON.parse(body)) copies from an API response, could otherwise put arbitrary code into the page's resume script.

  • #4335 bc8add9 Thanks @DylanPiercey! - Treat setImmediate and clearImmediate as unserializable like any other server function instead of writing them into the resume script, where browsers lack both and the whole payload threw a ReferenceError.

  • #4335 bc8add9 Thanks @DylanPiercey! - Fix resuming a page that shares more than 909,069 values, where one of them came back as a function's name string instead of the value.

  • #4325 686ff03 Thanks @DylanPiercey! - Settle a server render once: aborting $global.signal after the render completes no longer reports an error to the finished stream, and a completed or aborted render detaches from that signal. A value that throws while serializing (such as a getter) now aborts the whole render with its error, even inside a <try>, instead of leaving it pending or dropping its data, and a promise serialized with lazy loaded content holds the stream open until it settles. A @catch that fires while the stream consumes a @placeholder no longer writes the output twice, and toString stops an asynchronous render it throws for.

  • #4339 c3a40b0 Thanks @DylanPiercey! - Fix server rendering of a <select> or <textarea> whose attributes come from a spread. A spread without value no longer selects an <option value=""> on the server while the browser keeps its default option, and a null or undefined spread no longer throws Cannot read properties of null.

  • #4347 457da14 Thanks @DylanPiercey! - Fix a custom tag's variable staying undefined in the browser when the content holding the tag is created together with the input the tag returns, such as <child/v x=item/> in a <for> row, an <await> or @catch body, content rendered with parameters, a directly called <define>, or a tags template rendered by a class component. Rows a <for> adds after the page resumes were affected too.

  • #4348 c5ef2e4 Thanks @DylanPiercey! - Fix <script> and other effects inside a <try> whose content is waiting on an <await>. An update that changed only the hidden content ran its effect right away against the detached DOM and did not run it again when the content returned; it now waits for the content like any other effect there. An effect queued by several updates while the content waits now runs once when it returns, instead of once per update. Effects waiting on a <try> still streaming from the server, such as event handlers in content the client creates there or a server <script> sent before that content completes, now run when the content arrives instead of being dropped.

  • #4351 87a5db1 Thanks @DylanPiercey! - Fix <try> error handling in the browser. An error thrown while rendering a @placeholder that the browser creates is now caught by the same <try>'s @catch, as it is on the server, instead of escaping the update.

  • #4326 747b079 Thanks @DylanPiercey! - Fix server streaming around <try>. A promise sent to the browser from a <try> that had already settled could end the stream before a later <await> rendered, a promise in a @placeholder could lose its resolution when a sibling <try> caught, lazily loaded content flushed after its <try> caught could discard other lazy content's queued resume data, and lazily loaded content directly inside a <try> did not resume as part of its branch. A value that cannot be serialized in lazily loaded content inside a <try> now fails the render as it does elsewhere, instead of showing the @catch. @placeholder and async @catch content inside a <select value> now also mark their matching <option> as selected.

  • #4324 f69d5e6 Thanks @DylanPiercey! - Fix updates reaching the wrong node when content reads values from two different enclosing bodies, such as a tag body nested in another tag body that reads a <let> from each. The two values could share the key that records which update applies to that content, so changing one of them updated the node that shows the other.

  • Updated dependencies [2048f4b]:

    • @marko/compiler@5.42.10

Don't miss a new marko release

NewReleases is sending notifications on new releases.