fix(engine,core): wait for async timelines and force rebind before capture

Two fixes for compositions that register timelines after async data
loading (e.g. fetch for TopoJSON map data):

1. engine/frameCapture: remove the hosts.length <= 1 early return
   so the timeline readiness poll runs for ALL compositions, not just
   multi-composition galleries. Single-composition pages with async
   setup were silently skipped.

2. core/runtime/init: expose window.__hfForceTimelineRebind() which
   resets childrenBound and re-runs bindRootTimelineIfAvailable().
   The renderer calls this after all timelines are confirmed present,
   ensuring the root player discovers late-registered timelines from
   fetch callbacks.

Without these fixes, compositions using fetch() to load data at
runtime would render blank frames because the root player bound
timelines before the async setup completed, and seek() never
reached the unbound composition timeline.
This commit is contained in:
Miguel Ángel
2026-05-18 00:39:10 -04:00
parent 5aff328a9b
commit 2c84c9a55d
2 changed files with 13 additions and 1 deletions
+8 -1
View File
@@ -356,7 +356,7 @@ async function pollSubCompositionTimelines(
): Promise<void> {
const expression = `(function() {
var hosts = document.querySelectorAll("[data-composition-id]");
if (hosts.length <= 1) return true;
if (hosts.length === 0) return true;
var timelines = window.__timelines || {};
for (var i = 0; i < hosts.length; i++) {
var id = hosts[i].getAttribute("data-composition-id");
@@ -366,6 +366,13 @@ async function pollSubCompositionTimelines(
return true;
})()`;
const ready = await pollPageExpression(page, expression, timeoutMs, intervalMs);
if (ready) {
await page.evaluate(`(function() {
if (typeof window.__hfForceTimelineRebind === "function") {
window.__hfForceTimelineRebind();
}
})()`);
}
if (!ready) {
const missing = await page.evaluate(`(function() {
var hosts = document.querySelectorAll("[data-composition-id]");