You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A run of statements that only builds static structure -- plus holes where
its dynamic values go -- is described once and materialized by cloning a
cached node, instead of compiling to one opcode per element, static
attribute and static text node.
Measured on a 1000-row krausest create before this change: of ~37ms of
rendering JS, ~14.6ms is that static structure, ~7.4ms of it in DOM calls
(8 createElement, 6 setAttribute, 13 insertBefore per row -- 34 DOM calls
per row, 340k for 10k rows).
The pre-pass runs in `compileStatements`, so it needs no wire-format
change and works on already-published templates. A run is extracted only
when it is an element-rooted subtree of at least two elements whose holes
are dynamic attributes or last-child dynamic content. Components, blocks,
splattributes, modifiers, comments, trusted HTML and mid-child content
holes all end a run; bailing is always safe, since the caller then
compiles the statements the ordinary way. Coverage measured over 766 of
this repo's own test templates: 40% of static structure sits in runs of
two or more elements, and both benchmark rows (krausest and dbmon) are a
single 8-element run covering all of theirs.
Two paths are emitted for each run, chosen at runtime:
- when the tree builder can clone, the subtree is materialized in one step
and the dynamic values are filled in at their holes
- otherwise the run's original statements execute, in their original order
The second path is not a nicety. Rehydration matches against
server-rendered nodes and the SSR serializer interleaves block markers
with construction, so both need each step in order: filling holes after
the fact sets attributes after their element was flushed, and looks for a
dynamic block's markers after its enclosing elements are already closed.
An earlier attempt to serve both paths from a descriptor walk failed 16
rehydration tests for exactly that reason, leaving stray `%-b:0%` markers.
Cloning also keeps namespaces correct for free -- the cached node is built
with the ordinary DOM operations, in context -- which a serialized HTML
skeleton would not.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
0 commit comments