Skip to content

Fix performance and DX review findings - #3

Merged
ryu-man merged 23 commits into
mainfrom
fix/codex-review
Oct 16, 2026
Merged

ryu-man merged 23 commits into
mainfrom
fix/codex-review

Conversation

@ryu-man

@ryu-man ryu-man commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Fixes all 20 findings from the performance and DX review of @ixirjs/pulse. There is one commit per fix, and each fix has a focused test that I confirmed fails without it.

Behavior changes (minor changeset)

  • Spring velocity (spring() / springEasing()): sampled springs now take velocity in progress per second, the same unit the live spring uses. Before, the value was divided by 1000, so callers who compensated for that will need to scale their values down by 1000.
  • Timeline call() / set(): these entries now run on the timeline's own clock instead of setTimeout. Pause, seek, playbackRate and finished now apply to them, and they don't fire while the timeline plays in reverse.
  • Input validation in animate: a prop with no target value (for example x: [100] or {}) now throws a TypeError that names the prop.
  • Reduced motion: presence transitions and gradients now honor prefers-reduced-motion. Both take a respectReducedMotion option.

Fixes (patch)

  • Native Node ESM: relative imports are fully specified, and prepack now smoke-tests the built package with a Node import.
  • Controllers:
    • A controller now settles on where the animation actually ended, so reverse, alternate, fill: 'none' and fractional iterations finish in the right state.
    • Teardown can safely run more than once.
    • An rAF loop cancelled from inside its own callback no longer restarts.
  • Morph: the path parser stops at malformed path data instead of looping forever.
  • Flip:
    • Expired shared-layout records are cleared when a new one is written.
    • cubic-bezier() easing strings are now honored.
  • Gestures: wheelable releases its layer hint on cleanup.
  • Timeline: an entry's duration counts all of its iterations.
  • Scroll:
    • inView checks intersectionRatio, not just whether the element overlaps the viewport.
    • scroll() measures progress from the element's resting position, ignoring the transform it is driving.
  • Size keywords: width and height keywords are measured in the element's own box-sizing.
  • Svelte peer: the minimum is now ^5.29.0, the first version with {@attach}. The README's transform shorthand table is corrected.
  • Easings: preset factories are marked pure, so unused easings are tree-shaken. A size-limit budget covers importing a single easing.

Performance

  • Frame batch: the shared batch used by flip and scroll now runs every read before any write. This removes forced layout between attachments in the same frame.
  • Ancestor suppression: an animating ancestor's transform is now turned off once per frame for all measurements, instead of once per measured element.

Notes

  • The root size budget goes from 20 kB to 20.5 kB. The current size is 20.23 kB.
  • bun run verify passes, covering check, lint, 666 tests and size-limit.

@ryu-man
ryu-man merged commit a41d3f1 into main Oct 16, 2026
1 check failed
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