mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-14 18:01:20 +08:00
3739e6e32a
Rendering a composition and mounting one now derive root discovery, scope identity, asset sources and order, hoisted links, variable carriers and nested-host enumeration from the same module. Each keeps its own I/O, which is where they genuinely differ. The compiler's local depth cap and root lookup and the runtime's three pre-filtered head parameters are gone; the runtime hands over the head node and lets the module decide what comes out of it. Four divergences are settled here. Each changes behaviour, so each is stated with what actually differs rather than with a description of the edit. Inline head scripts. The compiler looped head scripts with a src branch and no else, so an inline one was silently discarded on render while the runtime ran it. The compiler was losing code, not holding a convention. Head and content scripts now run through one loop, head first, order preserved. A non-templated sub-composition with an inline head script went from zero collected scripts to one, wrapped, with its body intact. Link hoisting. Conditional on render, unconditional on mount, so a templated sub-composition's webfont link was dropped in video and kept in preview. Hoisting is the superset and matches what the author declared, so hoisting wins. A templated composition with a stylesheet link in its head went from no external links to that link. The parity fixture that previously recorded this shape as a known exclusion now gates it instead. Anonymous hosts. With a host naming no id, the compiler fell back to the first declared composition and scoped to it; the mount left the content unflattened and injected its stylesheet into the host head unscoped, so a composition's CSS leaked into whatever mounted it. The compiler's answer wins. The mount now flattens like every other mount and restores the declared id afterwards. The injected rule went from a bare class selector to one scoped to the composition. This flips an assertion that documented the old behaviour as intentional. Its premise no longer holds. What that test actually cared about, the root and its content being present under the host, still holds and is still asserted; the claim that nothing was flattened is now false and the test asserts the scoping instead. Scope ids. The compiler splits the CSS scope id from the script composition id; they differ only when a host names an id the content does not declare, and there the scripts follow the declared id so their self-referencing queries resolve. The runtime used one for both. The split wins: a host naming captions-comp over content declaring captions now emits scripts bound to captions while its CSS still scopes to captions-comp. Left alone deliberately: the variable-carrier divergence and its TODO, recursion on the mount path, and the three copies each of the flattened-root helper and the id assignment. The first two are behaviour changes with their own units. The third looks mergeable and is not cheaply, and it touches the instancing contract the pixel harness guards. Verified: core 1694 passing, producer 573 passing, the parity contract now nine tests with fixtures gating the two divergences it can observe. Lint clean, typecheck:runtime and the runtime preview guards clean, package cycles unchanged. A trap worth recording: the parity test's compiler arms import core's built dist while the mount arm imports source, so core must be rebuilt before that lane means anything after a compiler change. Skipping it produces a phantom divergence.