fix(core): re-register hf-timelines-built listener in maybePublishRenderReady (#1279)

Compositions that defer gsap.timeline() registration past DOMContentLoaded
(via setTimeout, template instantiation, or dynamic script loading) hit a
race where __renderReady stays false forever:

1. At DOMContentLoaded, __hfTimelinesBuilding is false — init.ts skips
   the hf-timelines-built listener and sets __renderReady = true
2. The deferred script runs, calls gsap.timeline().to() which sets
   __hfTimelinesBuilding = true via the batching proxy
3. The deferred maybePublishRenderReady() sees building=true, sets
   __renderReady = false, but never registers a listener to retry
4. __renderReady stays false, __hf.duration returns 0, pollHfReady
   times out with "Composition has zero duration"

Fix: when maybePublishRenderReady encounters __hfTimelinesBuilding=true,
register a one-shot hf-timelines-built listener to retry — matching the
pattern already used at init time for the synchronous batching case.

Closes #1260
This commit is contained in:
Miguel Ángel
2026-06-08 16:45:40 -04:00
committed by GitHub
parent b4210f6567
commit 1bcd6ec3b3
11 changed files with 437 additions and 106 deletions
@@ -0,0 +1,16 @@
{
"name": "Distributed: Three.js WebGL boundary",
"description": "2s composition (20 frames @ 10fps) with a Three.js purple cube on a dark background. Validates that the GSAP batching proxy correctly forwards WebGL render callbacks and that CDP screenshot capture composites WebGL canvas layers — catches the v0.6.80 regression where the plain-object proxy silently dropped eventCallback() and other non-allowlisted GSAP methods, producing black frames.",
"tags": ["distributed", "threejs", "webgl"],
"minPsnr": 25,
"maxFrameFailures": 0,
"minAudioCorrelation": 0.9,
"maxAudioLagWindows": 120,
"renderConfig": {
"fps": 10,
"chunkSize": 10
}
}