Repository navigation
fix(studio-server): cascade GSAP cleanup when deleting subtrees - #3655
Conversation
miga-heygen
left a comment
There was a problem hiding this comment.
Reviewed at exact 69cc4ffef.
GSAP deletion cascade — when an element subtree is deleted, all GSAP tweens targeting any descendant's #id or [data-hf-id] selector are now removed, not just the root element's.
Key correctness checks:
-
Survivor walk prevents false removal: after removing the element,
walkCompositionDescendants(doc, survivor)deletes any selector from the removal set that a surviving element still uses. This prevents erasing a tween that targets a shared selector in a different composition instance (e.g. two<template>instances with the same#box). Test "retains shared selectors used by a surviving composition instance" validates this. -
Positional re-parse loop preserved: animation writer IDs are count-based and renumber after each removal. The
for (;;)loop correctly re-parses after each tween deletion so later matches aren't skipped by stale IDs. -
Nested composition templates:
findScriptElementsDeep+walkCompositionDescendantstraverse into<template data-composition-id>boundaries, so tweens inside nested composition templates are also cascaded. Test "cascades a stable-id deletion into nested composition template scripts" validates this. -
No-op when element absent: if
findTargetElementreturns null, the function is never called and the source is returned unchanged. Test "does not strip scripts when the requested element is absent" validates this. -
Dead comment removed: the
ponytailcomment inuseElementLifecycleOps.tsdocumented the exact gap this PR closes — correctly removed.
+103/-40, 5 files. LGTM.
— Miga
Deleting a parent through Studio's server fallback left its GSAP tweens and descendant tweens in the source. Share subtree cleanup with the HTML parser, matching each element's DOM id and stable id and visiting nested composition-template scripts. Reparse after each removal so multiple tweens are all removed.
If a selector still matches a surviving element, retain its animations to protect repeated composition instances. This intentionally handles direct id/stable-id selectors; broad or computed selectors remain unchanged. SDK undo/redo behavior is unchanged.
Builds on #1566 by @vanceingalls, updated for the parser/server package split.
Validation: 197 targeted parser/source-mutation/file-route tests passed (2 existing todo); parser and studio-server typechecks, oxlint/oxfmt, and commit hooks passed.