Skip to content

ANIM-b slice 2: -webkit- transition/animation aliases, @-webkit-keyframes, and web frame fixtures for easings, direction and fill backwards - #201

Merged
thejackshelton merged 83 commits into
masterfrom
anim-b2
Oct 6, 2026
Merged

thejackshelton merged 83 commits into
masterfrom
anim-b2

Conversation

@thejackshelton

Copy link
Copy Markdown
Contributor

ANIM-b slice 2 (T065), web side: the -webkit- transition and animation aliases, @-webkit-keyframes, and Chrome frame fixtures that prove the easing, direction and fill-mode values the web profile was missing. It stays out of the state-program, the driver and state.ts (the native animation lane, slice 1, owns those).

What changed

  • Aliases. packages/dragon/src/css/aliases/animation.ts adds 14 aliases, one sorted line in aliases.ts. These are Chrome 145's alias_for entries (css_properties.json5 lines 9700-9733 and 9928-9945):

    • -webkit-animation and -webkit-animation-{delay, direction, duration, fill-mode, iteration-count, name, play-state, timing-function};
    • -webkit-transition and -webkit-transition-{delay, duration, property, timing-function}.

    None is parsed with UseAliasParsing: in css_parsing_utils.cc, shorthands_custom.cc and longhands_custom.cc it is used only for background, mask and perspective. So each alias parses exactly as its property. They use ALIAS: legacy -webkit- aliases of supported properties resolve as in Chrome (44 aliases) #172's mechanism. aliases.ts now also accepts the transition and animation list properties as alias targets, since those stay out of LONGHANDS (T065 option B).

  • @-webkit-keyframes is registered as keyframesAtRule, so it parses as @Keyframes, as Chrome's ConsumeKeyframesRule(webkit_prefixed) does (css_parser_impl.cc 895-898 and 1531-1581, a new ports.json entry).

    • KeyframesRule.prefixed records which form was written.
    • keyframesOverride in analysis/animations.ts applies Chrome's KeyframeStyleShouldOverride: an unprefixed rule beats a prefixed one of the same name in either order, and otherwise the later rule wins. Dragon refuses @layer, so all rules share one layer.
    • It has its own feature, at-rule:@-webkit-keyframes, so the row names the fixture that proves it.
    • Refusals name the rule as written, for example @-webkit-keyframes inside @media is not supported (package MQ-R).
  • Frame fixtures (group animations, picked up by the anim-* glob, ltr and rtl at 400x300, captured from Chrome by pnpm regen's anim-capture):

    • anim-easings: transitions with ease-in, ease-out, ease-in-out, step-start and step-end, plus the longhand form. The state is set, then cleared, so each runs both ways.
    • anim-timing: animations with every easing: linear, ease, ease-in, ease-out, ease-in-out, an overshooting cubic-bezier(), steps(4, jump-none), steps(3, jump-both), step-start and step-end, plus the longhand form.
    • anim-direction: alternate, reverse, and fill-mode backwards with positive delays. This includes reverse backwards, where the before-phase holds the to value, and alternate backwards with three iterations.
    • anim-webkit: every alias, an alias and its property in the same rule in both orders, and the @-webkit-keyframes precedence. That covers an unprefixed rule before and after a prefixed one, and two prefixed rules.

Rows promoted (web, animation context, all exact)

  • animation-direction:alternate, animation-direction:reverse
  • animation-fill-mode:backwards
  • animation-timing-function:cubic-bezier(), :ease-in, :ease-out, :ease-in-out, :steps()
  • transition-timing-function:ease-in, :ease-out, :ease-in-out
  • at-rule:@-webkit-keyframes

That is 12 new rows. Existing rows gain the new fixtures as further proof cases, and no status changes. step-start and step-end key steps(), which anim-steps already proved for transitions; anim-easings and anim-timing add cases for them. iOS and Android rows wait for the device run (the driver's job).

Music-player north-star delta

None: examples/music-player/dragon/north-star-check.json did not change in the regen.

What passed

  • pnpm typecheck.
  • pnpm regen via /tmp/job.sh animb2-regen: fixed point after 4 passes. I then ran pnpm notices:gen for the new ports entry.
  • vitest, 115/115 pass across 10 files: dragon aliases, seams, registry-claims, keyframes, anim-program, animations and animation-kinds; parity anim-frames (the host frame lanes and chrome-dual against the new captures), chrome-ports and registry-claims.
  • The full pnpm test was not run, per the lane contract.

Changed tests, and why

  • dragon/test/aliases.test.ts:
    • The alias count goes from 44 to 58.
    • Sample values were added for the 14 animation targets.
    • The parse comparison now also compares Declaration.animation, since an animation declaration's longhands are empty.
    • The fixture-coverage check also reads anim-webkit/view.css for the animation aliases.
    • New tests for @-webkit-keyframes: it parses as @Keyframes in any case, it is refused where @Keyframes is, and it follows the AddKeyframeStyle precedence.
  • dragon/test/registry-claims.test.ts: an alias family must still be a property family. The one exception is animation, whose own properties are ANIM_LIST_PROPERTIES plus the ANIM_SHORTHANDS keys. The no-alias-is-a-property check now covers those too, so the check is wider, not looser.
  • dragon/test/seams.test.ts:
    • -webkit-keyframes joins keyframes as accepted.
    • The byte-identical pin drops -webkit-keyframes from its list, as ANIM-b1 dropped keyframes. The new hash, a0302641…, is what the base a36ce22 gives for the same list. I ran it on the base, so every other at-rule's refusal is unchanged.
  • dragon/test/keyframes.test.ts: "@-webkit-keyframes stays refused" becomes "a valid one is accepted". A nameless one (none) and one inside @layer are still refused.
  • dragon/test/animations.test.ts: the band-gate test used ease-in-out, which this PR proves. It now uses transition-delay: inherit, which is still unproven, and keeps its intent.

Outside the spec

Reviewed diff: about 52 KB. Everything else is regen output under .macroscope/ignore.md shapes.

🤖 Generated with Claude Code

thejackshelton and others added 30 commits October 4, 2026 14:36
…runtime reference and the Chrome resize traces

Native targets are checked and lowered in every @media band, and accept @media where their profile proves at-rule:@media and
each media feature in the media context (R13, retiring the until-MQ-R refusal). The band table (typed atoms, truth vectors) and
the band state program fold every band into the state program as the internal env#band variable (R4, R5); MediaRuntime is the
TypeScript reference of the runtime (one size change, one band delta, one layout); rt-band.ts is the device band lookup with
Chrome's 1/64 px comparisons and float media size (R2, R3). Transitions a size change would start are refused on native until
MQ-Rt (R8). Six media-runtime fixtures with resize scripts run on the band runtime and in Chrome through setViewportSize at DPR
1, 2, 2.625 and 3 (resize-capture.ts), and their passing cases derive the media profile rows.
…t before any enforce-mode compile of a media fixture (dpr-vectors saw ios blocked)
…tted CSS of the media-runtime fixtures, DPR, pixel, break and hit captures and vectors, profiles with the media rows, north-star check, lanes.json)
…oves to parity); rt-band in the translator subset; .gitattributes in step order; pins the new fixtures move (hit suite 2084, state scripts, glyph clearance additions, s4b/s5 at-rule example, android-profile and hit identity scope)
…tted CSS of the media-runtime fixtures, DPR, pixel, break and hit captures and vectors, profiles with the media rows, north-star check, lanes.json)
… banded transitions and animations refused on native (MQ-Rt), near-threshold slack combinations refused at run-time switching until MQ-R0 (with the off-grid sweep), android-views band programs on the resize lanes, the (assignment, band) cap as a diagnostic, '@' reserved in document ids, mqr-forms for the other comparison forms
…tted CSS of the media-runtime fixtures, DPR, pixel, break and hit captures and vectors, profiles with the media rows, north-star check, lanes.json)
…; anim-bands: ios refuses a banded transition until MQ-Rt; the resize test names the backend in its step label)
…ers): the resize-capture step moves to scripts/regen-steps/mq-r1.ts (after capture, so before profile-rows), the media-runtime group to one sorted GROUPS line, .gitattributes sorted; hit suite 2092 beside master's animator suite
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: fed6f56
Run: https://github.com/compiled-run/dragoncss/actions/runs/37275478198
…lowering takes the image naturals and its programs the images and moving transforms; the hit suite checks move to master's p1-floor.json
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: 4d4251d
Run: https://github.com/compiled-run/dragoncss/actions/runs/37326048481
… (the hit suite grows by the media-runtime layout vectors)
…, used by nativePrograms and nativeBandPrograms alike, so an img under a transform only a band change moves gets the direct draw in every band
… expected-quads and expected-resize, both sides' package.json scripts
…'s lowering includes the interaction variants; both sides' record fields, exports and imports; p1-floor.json takes master's until regen re-derives it
…tes scrolls that script, fragment links or focus start, and the native output starts none); web still refuses it
…and gridItem fields, grid lowering and grid contexts

Rebuilt from grid-g1a (#32, 2196d59 through 00877f4) onto origin/master as one unstacked branch. input.ts: display grid,
LayoutStyle.grid and LayoutStyle.gridItem (null where unused); validate.ts: array and nullable rules and the grid shape rules;
environment.ts (where master now zooms the input) zooms px track breadths and fit-content limits; the native harness decodes
the fields and the native emitter builds them. lower/grid-layout.ts resolves every item line in the compiler as Blink's
GridLineResolver does. Grid contexts in analysis/context.ts. The engine still refuses display: grid (grid-layout).
Changes for master since #32: replaced elements (REPL-a) in a grid container carry their placement (lowerReplaced, and
checkGrid checks replaced children too); display: grid on a replaced element is refused in lowering and by the validator.
…he lowering, checked by the validator) and for display: grid on a replaced element
…in grid: null and gridItem: null on every style (additive; a JSON round trip with indent 1, as the files are written)
…ed leaves too (REPL-a landed after #32); PASS over 2200 vectors
…ixed point after 3 passes): every vector gains grid: null and gridItem: null (check-grid-input-additive PASS: 2200 vectors, 39964 styles), the translated engine and harness, the native corpora, the animator cases and the host lanes record
…grid fields instead of crashing on it; state-program.test's hand-built style gains grid: null and gridItem: null (CI failure on cbeb232)
…n and device-run steps blame the tree, a setup step falls back to the local run
…ition of a batch prepared at once in its own worktree (master plus PRs 1..k, installed, regenerated to its fixed point under the heavy lease), then assembled in order on the actual chain with the device step; an ejection ends the speculation
… rt-vectors/animator/cases.json (ANIM-b2's frame fixtures bring it to 26), with a short-run check; it pinned 18
@thejackshelton

Copy link
Copy Markdown
Contributor Author

Fixed the landing-proof failure in packages/parity/test/device-vectors.test.ts ('expected 26 to be 18'): the animator suite's declared count is now read from packages/layout/rt-vectors/animator/cases.json (26 with this PR's four frame fixtures; it stays >= 18), and a short animator run is checked to fail, alongside the existing undeclared-suite check. device-vectors.test.ts passes (8/8). Test-only change, no regen needed.

thejackshelton and others added 2 commits October 5, 2026 23:53
…that build's failure ejects); abandoned preparations are waited out before their worktrees are reused; position worktrees kept within a disk budget and removed at a run's end (and after each builder); prepared trees and regen commits checked against regen's declared outputs, not the review-ignore list
MQ-R1 1/2 (T067): @media bands for native in the compiler, the band runtime reference and Chrome resize traces
@thejackshelton thejackshelton added the landing-failed The landing driver stopped this PR; see its comment label Oct 6, 2026
@thejackshelton

Copy link
Copy Markdown
Contributor Author

Landing stopped at step test (pnpm land)

packages/parity/test/device-vectors.test.ts, rerun alone on a quiet machine, exited 1 (log /tmp/land-201-test-solo-1.log)
 ❯ packages/parity/test/device-vectors.test.ts:52:86
     50|     expect(hit).toBeGreaterThanOrEqual(p1Floor.p1.counts.hit);
     51|     // ANIM-b1 3b: the animator suite is declared with one case per fr…
     52|     expect(declared.find((d) => d.corpus === 'p1' && d.suite === 'anim…
       |                                                                                      ^
     53|     const shortHit = whole.map((s) => (s.corpus === 'p1' && s.name ===…
     54|     expect(judgeDeviceVectors(t, shortHit, digests, host)).toMatchObje…

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯


 Test Files  1 failed (1)
      Tests  2 failed | 6 passed (8)
   Start at  23:53:12
   Duration  1.75s (transform 1.12s, setup 0ms, import 1.67s, tests 7ms, environment 0ms)

Found by bisecting the batch #140 #201 #197 (3 proofs): master with #140 passes, adding #201 fails.

Fix the cause, then hand #201 back to the landing queue with the new clean head.

thejackshelton and others added 12 commits October 5, 2026 23:59
Commands: pnpm regen; pnpm run parity:devices; pnpm regen
GRID G1a input: grid and gridItem engine fields, grid lowering and grid contexts, unstacked on master (supersedes #32)
land CI steps: judge a failed job by its failed step (setup failures fall back, never blame the PR)
NA-NATIVE: scroll-behavior is not applicable on native (OVFL lane)
land: parallel position builds (prepare every position of a batch at once; devices serialize)
Commands: pnpm regen; pnpm run parity:devices; pnpm regen
@thejackshelton
thejackshelton merged commit 7ba2678 into master Oct 6, 2026
5 checks passed
@thejackshelton
thejackshelton deleted the anim-b2 branch October 6, 2026 08:09
@thejackshelton thejackshelton removed the landing-failed The landing driver stopped this PR; see its comment label Oct 6, 2026
thejackshelton added a commit that referenced this pull request Oct 6, 2026
…211 CTX-PROOF-3, #195 OVFL-na) into form-a-v2; no conflicts
thejackshelton added a commit that referenced this pull request Oct 8, 2026
…eeps -webkit-keyframes and charsetAtRule; the seams pin drops both from its list, and master gives the same hash for that list (bb433400…)
thejackshelton added a commit that referenced this pull request Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant