Repository navigation
fix(core): resolve a relative data-start inside the clip's own composition - #5336
jayhemnani9910 wants to merge 3 commits into
Conversation
ec8f7c9 to
a92f48e
Compare
jrusso1020
left a comment
There was a problem hiding this comment.
The runtime fix looks correct, and the test fails without it. Before this merges, the render-side resolver that claims to mirror this one should be scoped the same way.
What I checked:
- The docs claim holds.
docs/reference/html-schema.mdxsays "References stay within one composition", and the runtime was resolving document-wide. compositionScopeOf(startResolver.ts:49) treats a composition host as belonging to its parent composition. Sodata-start="card-a"on a sibling host still resolves in the parent scope, and the document-wide fallback (:61) keeps cross-composition references working as before.- Ran
vitest run src/runtime/startResolver.test.ts: 33/33 pass. Mutation check: withstartResolver.tsreverted and the new test kept, it fails withexpected 1 to be 3.
Please address in this PR:
packages/engine/src/services/referenceResolver.ts:33(findReferenceTargetEl) still doesgetElementByIddocument-wide. Its header says it "Mirrors the browser runtime's startResolver so snapshot/render agree". The producer uses it to place video, image and audio inparseVideoElements/parseImageElements/parseAudioElements, throughrenderMediaCollector.ts. Your repro passes because the engine works in composition-local time and both mounts are the same block, so the first#firsthappens to have the same local timing. With two different compositions that share an id at different local times, the runtime now picks the in-scope element and the engine still picks the first one in the document. A<video data-start="intro">would then get its visibility window from one clip and its extracted frames from another. Scoping the engine lookup the same way (nearest[data-composition-id], host counts as its parent's) keeps the two in step.packages/sdk/src/session.ts:384says "refId remains a bare global id, matching runtime resolution". That is no longer true after this change, so update the comment, or the SDK's lookup if it should follow.
No other open PR targets this. #4334 is a different startResolver bug, as the description says.
— Rames
…own composition The engine's reference resolver still looked an id up document-wide, so with two different compositions sharing an id the producer placed media from the first one while the runtime used the clip's own. Scope it the same way as the runtime's startResolver, with the same document-wide fallback, and correct the SDK comments that called the runtime lookup global.
The scoped lookup needs parentElement, closest and querySelectorAll, but RefResolverEl is exported from @hyperframes/engine. Make them optional and fall back to the document-wide lookup when an adapter lacks them.
|
Both points are in 13eacd9, plus 9ac9d2b. Engine. I also rendered it: SDK. I fixed the comment and left the lookup. Left alone: a reference to a clip in a different composition (the fallback path) still comes out in the referencing composition's local time on the render side. With Engine, SDK, producer and CLI suites give the same results as the PR head before these commits, plus the two new tests. |
a92f48e to
9ac9d2b
Compare
What
A relative
data-start(data-start="first","first + 0.5") now looks for the referenced clip inside the referencing clip's own composition first, and only falls back to the document-wide lookup when nothing there matches.Why
The docs say references resolve inside the same composition, and
hyperframes timelineand the audio mix already do that. The runtime start resolver useddocument.getElementById, so once two compositions in the rendered document contain the same id, every reference to it resolves against the first one in the document.The common way to hit this is mounting one block twice. Each instance keeps the block's own ids, so the second instance's relative clips are timed off the first instance and drop out of the render.
Repro on 0.8.142 (also on current main):
compositions/card.htmlindex.htmlroot:(
tone.wavis any audio file longer than 4 s.)hyperframes lintis clean, andhyperframes timelineshowssecondat 1-2 s incard-aand 3-4 s incard-b. Inhyperframes render --fps 10, sampling the centre pixel per frame:The beep plays at 1-2 s and 3-4 s as expected, so in
card-bthe sound plays over a frame where its clip is missing.card-b'ssecondresolves to 1 s (the end ofcard-a'sfirst), a time whencard-bis not on screen yet.Related work
No existing issue or PR found. #4481 fixed the same repeated-id problem for Studio's timeline rows. #4334 is a different
startResolverproblem (the walk-up from a wrapped mount) and does not overlap.How
findReferenceTargettakes the referencing element. It finds that element's composition (for a composition host, its parent composition) and returns the first element with the referenced id whose own composition is the same one. If none matches, the existinggetElementByIdanddata-composition-idlookups run unchanged, so a reference that only exists elsewhere in the document resolves as before.Test plan
startResolver.test.tsmounts one composition twice and checks the second instance's referenced clip starts at 3 s. It fails without the change (resolves to 1) and passes with it.oxlint,oxfmt,tsc, fallow and the comment checks pass.