Describe the bug
After an element has been dragged in Studio (which writes a global gsap.set("#el", { x, y }) above the timeline declaration, per #2099), resizing it writes tl.set("#el", { width, height }, 0) also above the declaration. const tl is then referenced in its temporal dead zone, the composition script throws, and every animation in the composition stops working.
Cause: findInsertionPoint in packages/parsers/src/gsapWriterAcorn.ts anchors new tl.* statements after the last located GSAP call. When the only located call is a global hold, that position is before const tl = gsap.timeline(...). addLabelToScript and addAnimationWithKeyframesToScript share the same insertion point.
Minimal reproduction
<div id="root" data-composition-id="main" data-start="0" data-duration="2" data-width="1920" data-height="1080">
<div id="box" class="clip" data-start="0" data-duration="2" data-track-index="1"
style="position:absolute; left:100px; top:100px; width:400px; height:300px; background:tomato"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
window.__timelines["main"] = tl;
</script>
Or directly against the writer:
const s1 = addAnimationToScript(script, { targetSelector: "#box", method: "set", position: 0, properties: { x: 53, y: 157 }, global: true }).script;
const s2 = addAnimationToScript(s1, { targetSelector: "#box", method: "set", position: 0, properties: { width: 512, height: 670 } }).script;
// s2: gsap.set(...); tl.set(...); const tl = gsap.timeline(...)
Steps to reproduce
npx hyperframes preview on the composition above.
- Drag
#box on the canvas (a global gsap.set is written above the timeline).
- Resize
#box with a corner handle.
Expected behavior
tl.set("#box", { width, height }, 0) is inserted after const tl = gsap.timeline(...).
Actual behavior
gsap.set("#box", { x: 53, y: 157 });
tl.set("#box", { width: 512, height: 670 }, 0);
const tl = gsap.timeline({ paused: true });
→ ReferenceError: Cannot access 'tl' before initialization; the composition script aborts. Workaround: put any tl.* call (e.g. tl.set({}, {}, 0);) right after the declaration so there is a located call to anchor on.
Environment
hyperframes CLI 0.8.77 (also reproduced on main @ 0985b45), macOS, Chrome.
Additional context
Fix PR to follow. The legacy recast writer in gsapParser.ts (insertAfterAnchor) has the same shape, but its write path is retired, so the PR leaves it alone.
Describe the bug
After an element has been dragged in Studio (which writes a global
gsap.set("#el", { x, y })above the timeline declaration, per #2099), resizing it writestl.set("#el", { width, height }, 0)also above the declaration.const tlis then referenced in its temporal dead zone, the composition script throws, and every animation in the composition stops working.Cause:
findInsertionPointinpackages/parsers/src/gsapWriterAcorn.tsanchors newtl.*statements after the last located GSAP call. When the only located call is a global hold, that position is beforeconst tl = gsap.timeline(...).addLabelToScriptandaddAnimationWithKeyframesToScriptshare the same insertion point.Minimal reproduction
Or directly against the writer:
Steps to reproduce
npx hyperframes previewon the composition above.#boxon the canvas (a globalgsap.setis written above the timeline).#boxwith a corner handle.Expected behavior
tl.set("#box", { width, height }, 0)is inserted afterconst tl = gsap.timeline(...).Actual behavior
→
ReferenceError: Cannot access 'tl' before initialization; the composition script aborts. Workaround: put anytl.*call (e.g.tl.set({}, {}, 0);) right after the declaration so there is a located call to anchor on.Environment
hyperframes CLI 0.8.77 (also reproduced on
main@ 0985b45), macOS, Chrome.Additional context
Fix PR to follow. The legacy recast writer in
gsapParser.ts(insertAfterAnchor) has the same shape, but its write path is retired, so the PR leaves it alone.