mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
fix(core,cli): address review — guard __renderReady, drop pre-quantization, add tests
- Guard __renderReady with `if (state.capturedTimeline)` in all three paths (setTimeout(0) and .finally() were setting it unconditionally even when bindRootTimelineIfAvailable returned false) - Remove redundant fps=30 pre-quantization in snapshot — renderSeek already calls quantizeTimeToFrame internally with the runtime's canonicalFps, so pre-quantizing was double-quantizing at a potentially wrong grid - Add regression tests: __renderReady is set when timeline exists, stays undefined when no timeline is available
This commit is contained in:
@@ -276,17 +276,14 @@ async function captureSnapshots(
|
|||||||
for (let i = 0; i < positions.length; i++) {
|
for (let i = 0; i < positions.length; i++) {
|
||||||
const time = positions[i]!;
|
const time = positions[i]!;
|
||||||
|
|
||||||
// 30 = runtime's default canonicalFps (not exposed on PlayerAPI)
|
|
||||||
await page.evaluate((t: number) => {
|
await page.evaluate((t: number) => {
|
||||||
const player = (window as any).__player;
|
const player = (window as any).__player;
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
const safe = Math.max(0, Number(t) || 0);
|
const safe = Math.max(0, Number(t) || 0);
|
||||||
const frame = Math.floor(safe * 30 + 1e-9);
|
|
||||||
const quantized = frame / 30;
|
|
||||||
if (typeof player.renderSeek === "function") {
|
if (typeof player.renderSeek === "function") {
|
||||||
player.renderSeek(quantized);
|
player.renderSeek(safe);
|
||||||
} else if (typeof player.seek === "function") {
|
} else if (typeof player.seek === "function") {
|
||||||
player.seek(quantized);
|
player.seek(safe);
|
||||||
}
|
}
|
||||||
if ((window as any).gsap?.ticker?.tick) {
|
if ((window as any).gsap?.ticker?.tick) {
|
||||||
(window as any).gsap.ticker.tick();
|
(window as any).gsap.ticker.tick();
|
||||||
|
|||||||
@@ -576,4 +576,52 @@ describe("initSandboxRuntimeModular", () => {
|
|||||||
expect(player?.getTime()).toBeCloseTo(1, 1);
|
expect(player?.getTime()).toBeCloseTo(1, 1);
|
||||||
expect(childTimeline.time()).toBeCloseTo(1, 1);
|
expect(childTimeline.time()).toBeCloseTo(1, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("sets __renderReady only after timeline is bound, not at __playerReady time", async () => {
|
||||||
|
const root = document.createElement("div");
|
||||||
|
root.setAttribute("data-composition-id", "main");
|
||||||
|
root.setAttribute("data-root", "true");
|
||||||
|
root.setAttribute("data-start", "0");
|
||||||
|
root.setAttribute("data-width", "1920");
|
||||||
|
root.setAttribute("data-height", "1080");
|
||||||
|
document.body.appendChild(root);
|
||||||
|
|
||||||
|
(window as Window & { __timelines?: Record<string, RuntimeTimelineLike> }).__timelines = {
|
||||||
|
main: createMockTimeline(10),
|
||||||
|
};
|
||||||
|
|
||||||
|
initSandboxRuntimeModular();
|
||||||
|
|
||||||
|
const win = window as Window & {
|
||||||
|
__playerReady?: boolean;
|
||||||
|
__renderReady?: boolean;
|
||||||
|
__player?: { _timeline: RuntimeTimelineLike | null };
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(win.__playerReady).toBe(true);
|
||||||
|
expect(win.__renderReady).toBe(true);
|
||||||
|
expect(win.__player?._timeline).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not set __renderReady when no timeline is available", () => {
|
||||||
|
const root = document.createElement("div");
|
||||||
|
root.setAttribute("data-composition-id", "main");
|
||||||
|
root.setAttribute("data-root", "true");
|
||||||
|
root.setAttribute("data-start", "0");
|
||||||
|
root.setAttribute("data-width", "1920");
|
||||||
|
root.setAttribute("data-height", "1080");
|
||||||
|
document.body.appendChild(root);
|
||||||
|
|
||||||
|
(window as Window & { __timelines?: Record<string, RuntimeTimelineLike> }).__timelines = {};
|
||||||
|
|
||||||
|
initSandboxRuntimeModular();
|
||||||
|
|
||||||
|
const win = window as Window & {
|
||||||
|
__playerReady?: boolean;
|
||||||
|
__renderReady?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(win.__playerReady).toBe(true);
|
||||||
|
expect(win.__renderReady).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1463,7 +1463,9 @@ export function initSandboxRuntimeModular(): void {
|
|||||||
.finally(() => {
|
.finally(() => {
|
||||||
externalCompositionsReady = true;
|
externalCompositionsReady = true;
|
||||||
bindRootTimelineIfAvailable();
|
bindRootTimelineIfAvailable();
|
||||||
(window as Window & { __renderReady?: boolean }).__renderReady = true;
|
if (state.capturedTimeline) {
|
||||||
|
(window as Window & { __renderReady?: boolean }).__renderReady = true;
|
||||||
|
}
|
||||||
runAdapters("discover", state.currentTime);
|
runAdapters("discover", state.currentTime);
|
||||||
bindMediaMetadataListeners();
|
bindMediaMetadataListeners();
|
||||||
installAssetFailureDiagnostics();
|
installAssetFailureDiagnostics();
|
||||||
@@ -1650,9 +1652,10 @@ export function initSandboxRuntimeModular(): void {
|
|||||||
if (bindRootTimelineIfAvailable() && state.capturedTimeline !== prevTimeline) {
|
if (bindRootTimelineIfAvailable() && state.capturedTimeline !== prevTimeline) {
|
||||||
player._timeline = state.capturedTimeline;
|
player._timeline = state.capturedTimeline;
|
||||||
}
|
}
|
||||||
// Re-run adapters to discover new elements
|
|
||||||
runAdapters("discover", state.currentTime);
|
runAdapters("discover", state.currentTime);
|
||||||
(window as Window & { __renderReady?: boolean }).__renderReady = true;
|
if (state.capturedTimeline) {
|
||||||
|
(window as Window & { __renderReady?: boolean }).__renderReady = true;
|
||||||
|
}
|
||||||
postTimeline();
|
postTimeline();
|
||||||
postState(true);
|
postState(true);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user