Skip to content

Commit 33e302d

Browse files
committed
fix(runtime): publish rebound timeline before apply
1 parent cf9c36d commit 33e302d

2 files changed

Lines changed: 14 additions & 1 deletion

File tree

packages/core/src/runtime/init.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,13 +2708,18 @@ describe("initSandboxRuntimeModular", () => {
27082708
const replacement = createMockTimeline(10);
27092709
window.__timelines = { main: first };
27102710
const applied: Array<Record<string, unknown>> = [];
2711+
const deliveryOrder: string[] = [];
27112712
vi.spyOn(window.parent, "postMessage").mockImplementation((message: unknown) => {
27122713
if (typeof message !== "object" || message === null) return;
27132714
const payload = message as Record<string, unknown>;
2715+
if (payload.type === "timeline" || payload.type === "runtime-data-applied") {
2716+
deliveryOrder.push(String(payload.type));
2717+
}
27142718
if (payload.type === "runtime-data-applied") applied.push(payload);
27152719
});
27162720

27172721
initSandboxRuntimeModular();
2722+
deliveryOrder.length = 0;
27182723
window.__player?.seek(0.25);
27192724
registerRuntimeDataHandler("captions", async () => {
27202725
await Promise.resolve();
@@ -2733,6 +2738,7 @@ describe("initSandboxRuntimeModular", () => {
27332738
expect(first.time()).toBeCloseTo(7 / 30, 5);
27342739
expect(replacement.time()).toBeCloseTo(37 / 30, 5);
27352740
expect(applied[0]).toMatchObject({ channel: "captions", requestId: 7 });
2741+
expect(deliveryOrder.slice(0, 2)).toEqual(["timeline", "runtime-data-applied"]);
27362742
});
27372743

27382744
it("does not seek a removed timeline after runtime data is cleared", async () => {

packages/core/src/runtime/init.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,14 @@ export function initSandboxRuntimeModular(): void {
15821582
}
15831583
syncTimedElementVisibility(state.currentTime);
15841584
};
1585-
reconcileTimelineAfterRuntimeData = reconcileTimeline;
1585+
reconcileTimelineAfterRuntimeData = () => {
1586+
reconcileTimeline();
1587+
// The parent treats runtime-data-applied as permission to re-seek immediately. Publish the
1588+
// replacement duration first; otherwise that seek is clamped by the bootstrap timeline (often
1589+
// one second) and a style switch appears frozen on the first caption segment until some later
1590+
// polling tick happens to post the rebuilt timeline.
1591+
postTimeline();
1592+
};
15861593
(window as Window & { __hfForceTimelineRebind?: () => void }).__hfForceTimelineRebind =
15871594
reconcileTimeline;
15881595

0 commit comments

Comments
 (0)