Skip to content

Commit afe020a

Browse files
fix(core): a GSAP call added after the first seek fires once, not twice (#4948)
The seek path skips its silent re-render on timelines with a zero-duration callback, because that re-render re-arms the callback and the next forward seek fires it again. The answer was cached per timeline on the first seek, so a tl.call added later was never seen: the re-render ran and the call fired twice. The check now reads the timeline's current children on every seek.
1 parent b3c5207 commit afe020a

2 files changed

Lines changed: 25 additions & 15 deletions

File tree

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,6 +2897,29 @@ describe("initSandboxRuntimeModular", () => {
28972897
expect(seekCalls).toEqual([{ time: 2, suppressEvents: false }]);
28982898
});
28992899

2900+
it("fires a call added after the first seek exactly once", () => {
2901+
const root = document.createElement("div");
2902+
root.setAttribute("data-composition-id", "main");
2903+
root.setAttribute("data-root", "true");
2904+
root.setAttribute("data-start", "0");
2905+
root.setAttribute("data-duration", "10");
2906+
root.setAttribute("data-width", "1920");
2907+
root.setAttribute("data-height", "1080");
2908+
document.body.appendChild(root);
2909+
2910+
const main = gsap.timeline({ paused: true }).to({ x: 0 }, { x: 1, duration: 10 });
2911+
window.__timelines = { main };
2912+
initSandboxRuntimeModular();
2913+
window.__player?.renderSeek(1);
2914+
2915+
const fired = vi.fn();
2916+
main.call(fired, [], 2);
2917+
window.__player?.renderSeek(2);
2918+
window.__player?.renderSeek(3);
2919+
2920+
expect(fired).toHaveBeenCalledTimes(1);
2921+
});
2922+
29002923
it("shows pip video at global start time even when host composition starts late", () => {
29012924
// Regression: resolveStartForElement used to add the host composition's start on top of
29022925
// the video's own data-start, causing double-offset. A pip video with data-start="45.40"

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

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4249,7 +4249,6 @@ export function initSandboxRuntimeModular(): void {
42494249
const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
42504250
typeof value === "object" && value !== null;
42514251

4252-
const gsapCallbackTweenCache = new WeakMap<RuntimeTimelineLike, boolean>();
42534252
const GSAP_CALLBACK_NAMES = [
42544253
"onStart",
42554254
"onUpdate",
@@ -4271,9 +4270,6 @@ export function initSandboxRuntimeModular(): void {
42714270
};
42724271

42734272
const hasZeroDurationCallbackTween = (timeline: RuntimeTimelineLike): boolean => {
4274-
const cached = gsapCallbackTweenCache.get(timeline);
4275-
if (cached != null) return cached;
4276-
42774273
if (!("getChildren" in timeline) || typeof timeline.getChildren !== "function") {
42784274
return false;
42794275
}
@@ -4283,13 +4279,9 @@ export function initSandboxRuntimeModular(): void {
42834279
children = timeline.getChildren(true, true, true);
42844280
} catch (err) {
42854281
swallow("runtime.init.gsapCallbackChildren", err);
4286-
gsapCallbackTweenCache.set(timeline, false);
4287-
return false;
4288-
}
4289-
if (!Array.isArray(children)) {
4290-
gsapCallbackTweenCache.set(timeline, false);
42914282
return false;
42924283
}
4284+
if (!Array.isArray(children)) return false;
42934285

42944286
for (const child of children) {
42954287
if (!isObjectRecord(child)) continue;
@@ -4300,13 +4292,8 @@ export function initSandboxRuntimeModular(): void {
43004292

43014293
const totalDuration = readGsapDuration(child, "totalDuration");
43024294
const duration = totalDuration ?? readGsapDuration(child, "duration");
4303-
if (duration != null && duration <= 0.000001) {
4304-
gsapCallbackTweenCache.set(timeline, true);
4305-
return true;
4306-
}
4295+
if (duration != null && duration <= 0.000001) return true;
43074296
}
4308-
4309-
gsapCallbackTweenCache.set(timeline, false);
43104297
return false;
43114298
};
43124299

0 commit comments

Comments
 (0)