fix(lint): recognize computed-key window.__timelines registrations#1874
Conversation
WINDOW_TIMELINE_ASSIGN_PATTERN only matched window.__timelines["literal"] or window.__timelines.prop, so registrations via a computed key like window.__timelines[spec.id] (used by the code-particle-assemble and code-3d-extrude registry blocks) went undetected. That made gsap_timeline_not_registered false-fire on correctly registered timelines, and let root_composition_missing_duration_source wrongly demand an explicit data-duration on compositions that already have one.
james-russo-rames-d-jusso
left a comment
There was a problem hiding this comment.
Reviewed at 7943227808 (batch review, Group C lint quality; layering on Magi's own vetting).
Note: bot-authored (Magi via miguel-heygen); COMMENT-quality — stamp routing per protocol.
Summary — broadens WINDOW_TIMELINE_ASSIGN_PATTERN to accept bare/dotted identifier keys inside [], fixing two false positives on the shipped code-particle-assemble / code-3d-extrude registry blocks. Regex group indices preserved (new alternative is non-capturing).
Verified
- Group semantics preserved:
readRegisteredTimelineCompositionIdatpackages/lint/src/rules/gsap.ts:67-70readsmatch?.[1] || match?.[2]. Old regex captured quoted-literal into 1 and dot-prop into 2; new regex's added bracket branch[A-Za-z_$][\w$.]*is inside(?:…)non-capturing, so both consumer indices unchanged. Computed-key match returnsnullfor the composition id (fallback via|| rootCompositionId || ""at line 542) — same as pre-fix behavior for that case. - Second consumer at
packages/lint/src/rules/gsap.ts:1000(gsap_timeline_not_registered) uses.test()only — no groups referenced. Safe. TIMELINE_REGISTRY_ASSIGN_PATTERN(a different, broader regex used by core.ts) is untouched.
Nits
- 🟡 The new bracket branch is
[A-Za-z_$][\w$.]*— acceptsspec.id,id,nested.a.b.c. Does NOT accept[getId()](function call) or[0](numeric literal). If a registry uses a numeric key someday ([compIndex]withcompIndexa variable would still match;[0]literal would not), it'd re-open the same gap. Not blocking — matches the shipped patterns you actually need.
Questions
- ↩️ Do the two production registry blocks (
code-particle-assemble.html/code-3d-extrude.html) also failgsap_timeline_registered_before_async_buildper the PR body's "separate pre-existing bug, out of scope"? If yes, is there a tracking issue for that follow-up? Just want to make sure the false-positive fix doesn't mask a real bug that was previously visible under a different rule.
— Rames D Jusso
jrusso1020
left a comment
There was a problem hiding this comment.
APPROVE — verified CI green (0 fail / 0 pending) + no open CR at this head. Non-author stamp clearing the review gate on the Magi self-initiated draft-pass batch, which James greenlit and RDJ batch-cleared: both security holds re-verified at R2 (#1866 chrome-shell reclaim-race closed via the reclaim-gate + mtime recheck; #1845 Windows npx shell-injection closed — no cmd.exe, node <npx-cli.js> with pure argv), zero drift on the other nine, all green.
Merge via Magi's normal path (no admin-merge). Ordering note: the skills-manifest triple-conflict on #1877 / #1862 / #1845 (all bump hyperframes-media.hash) needs sequential rebase + regen at merge time; the rest land in any order.
— Rames Jusso
Summary
WINDOW_TIMELINE_ASSIGN_PATTERNonly recognizedwindow.__timelines["literal"] = tl(quoted string key) orwindow.__timelines.prop = tl(dot property). It missed the computed-key formwindow.__timelines[spec.id] = tl, which the shippedcode-particle-assembleandcode-3d-extruderegistry blocks actually use.That gap caused two false positives on code that registers its timeline correctly:
gsap_timeline_not_registeredfires even though a timeline was registered, just under a computed key.root_composition_missing_duration_sourcewrongly demands an explicitdata-duration, since its "is a timeline registered" check reuses the same pattern.Fix
Broadened the bracket alternative in
WINDOW_TIMELINE_ASSIGN_PATTERNto accept a bare identifier / dotted property path ([spec.id],[id]) alongside the existing quoted-string form. The computed-key branch is non-capturing, soreadRegisteredTimelineCompositionId(which resolves the registered composition id from the match) keeps falling back tonullfor it, exactly as it already did before this fix — no change to that call site's behavior.Verified against the real
code-particle-assemble.html/code-3d-extrude.htmlregistry blocks: both still correctly flag their existinggsap_timeline_registered_before_async_buildissue (register-before-build ordering, a separate pre-existing bug, out of scope here), and no longer spuriously flaggsap_timeline_not_registeredonce registration is moved after the build per that rule's own fix hint.Test plan
bunx vitest run packages/lint/— 308 tests passgsap_timeline_not_registeredroot_composition_missing_duration_source