Repository navigation
fix(core): a composition behind a wrapper takes its host's start - #6435
Conversation
There was a problem hiding this comment.
Verdict: REQUEST CHANGES · 1 blocker · 0 important · 0 nits · head db8ee7ab
- blocker — required
Test reachabilityfails:Runner mapping needs review: packages/producer/scripts/test-classification.mjs. Editing that file changes its digest, andscripts/test-reachability.json:50still pins the old one (88d7415a…). Re-pin it to47a6204722443284067bf5c464601a252091aab3670ef1626e50ce507b8214fc, as #4610 did. With that one-line change,node scripts/check-test-reachability.mjs --reportpasses locally.
I found nothing wrong in the resolver change. A wrapped root now resolves the way a directly mounted one already did, and timeline.ts already used the nearest composition's start as its fallback.
Scope
Read all 4 files and the callers of resolveStartForElement, resolveHostSlotsForElement and resolveCompositionOrigin. Locally: startResolver.test.ts 44/44, and 7 fail with the old lookup restored. Core src/runtime passes 2557/2557. wrappedMountTiming.integration.test.ts passes with Chrome and ffmpeg. The other CI jobs were still running when I posted this.
Edit accuracy: accurate 271 (base branch 271), smooth 188 of thoseThe gate passes. Quarantined, measured but not gated (0) |
The nearest host or timed wrapper above a mounted root sets its start, so its clock starts when the wrapper shows it, matching how CSS animations already pick their clip.
|
Re-pinned the classification digest in |
Merge 20 more upstream commits (acd0bc3..ad4d3fa, v0.8.205: heygen-com#6403, heygen-com#6363, heygen-com#6209, heygen-com#6395, heygen-com#6424, heygen-com#6426, heygen-com#6442, heygen-com#6430, heygen-com#6402, heygen-com#6435, heygen-com#6439, heygen-com#6449, heygen-com#5436, heygen-com#6455 and docs). No conflicts. Record the 11 open PRs heygen-com#6440-heygen-com#6458 and issue heygen-com#6443 in docs/DECISIONS.md (none adopted), re-check the earlier open PRs, and advance the commit watermark to ad4d3fa, the PR watermark to heygen-com#6458 and the issue watermark to heygen-com#6443. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
What
A composition root with no
data-startof its own now takes its start from the nearest composition host or timed wrapper above it, even when a neutral element (a<section>, a vfx<canvas>, an author's wrapperdiv) sits between them. A wrapper with its owndata-startwins over the host above it, because that wrapper is what shows and hides the composition. Before, only the immediate parent counted, so a wrapped composition was timed on the root clock: it started at 0 instead of its host's start, and once root time passed its own duration its layers went hidden.Why
#4334. With a host at 5 s and one neutral wrapper between it and the inner root, the resolver returned 0 for every host marker (
data-composition-src,-id,-file); with no wrapper it returned 5.Related work
Fixes #4334. Follows the maintainer's call on the issue: keep the resolver marker-only (no special case for
canvas.hf-vfx-src); the exporter keeps copyingdata-startonto its wrapped element.How
inheritedTimingHostinpackages/core/src/runtime/startResolver.tsnow walks to the nearest ancestor carrying a composition marker or adata-start(closest()) instead of checking only the parent. A timed wrapper counts because the runtime hides it outside its window: timing the composition from the host would start its clock early and show it mid-animation. CSS animations already pick their clock the same way (closest("[data-start]")in the CSS adapter). It stops at the first match, so an outer host or a sibling clock is never used, and explicit starts, references and fallbacks are untouched.isCompositionHostuses the same selector, so the marker list has one definition.Test plan
startResolver.test.ts: the full 3x3 matrix from the issue (each marker, 0/1/2 neutral wrappers) plus a nested-host case that must take the nearest host (3 s inside a host at 2 s = 5 s), plus a timed wrapper at 2 s inside a scene at 5 s that must give 7 s. 45 passed, 3 runs. With the old parent-only lookup restored, exactly the 7 new wrapper/nested cases fail; with a host-onlyclosest(), the timed-wrapper case fails (expected 5 to be 7).wrappedMountTiming.integration.test.ts(Chrome + ffmpeg): a scene at 1 s holds, inside a<section>, a composition whose box fades in over its own first second. Halfway through the scene the frame is half grey (between 90 and 165 of 255), not fully faded in. 3 runs green; with the old lookup it fails (expected 255 to be less than 165).src/runtimein core: 104 files passed.tsc --noEmit(core, producer), comment ratchet, producer test classification: clean.Why under 100 lines of source: the bug is one lookup in the one resolver every timing path goes through; the rest of the diff is the matrix and the render test.