Skip to content

fix: guard canvas size and scroll offset - #107

Merged
cursor[bot] merged 1 commit into
mainfrom
cursor/canvas-scroll-guards-0692
Nov 10, 2026
Merged

cursor[bot] merged 1 commit into
mainfrom
cursor/canvas-scroll-guards-0692

Conversation

@joeblau

@joeblau joeblau commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

Closes #93
Closes #94

Behavior

Checks sit on the calls that write layout and scroll state. The render loop is unchanged.

  • Invariant: canvas size and pixelRatio are finite and > 0 #93, canvas size and pixelRatio. The constructor and resize throw chart-ts: invalid pixelRatio … unless the ratio is finite and > 0, the same shape of error takeScreenshot already uses. resize also throws chart-ts: invalid chart width/height … unless both CSS sizes are finite and >= 0, and it does not change the canvas when it throws. resolveConfig and updateConfig reject a non-finite or negative width, height, priceAxis.width, or timeAxis.height before the config is stored. 0 stays a legal size.
  • Invariant: the time scale's scroll offset stays finite #94, scroll offset. scroll, scrollTo, and fitRange (scrollBy, scrollTo, zoomToRange) ignore a non-finite argument, matching zoom. clampScroll resets a non-finite offset to 0 before clamping, so a NaN cannot stick across the next gesture.

Tests

1909 tests passed. Coverage is 100% line, branch, and function. bun run typecheck:tsc and bun run check:invariants passed.

Benchmarks

node bench/suite/run.mjs --samples=7 --sizes=100000, Node 24, median ms/op. The two builds were timed back to back. These paths do not run during setData, appendData, or render.

Case Before After
100000 setData sorted 1.0025 1.0617
100000 setData shuffled 28.4973 29.8749
100000 DataStore single bar append 0.0005 0.0005
100000 chart appendData streaming 0.2223 0.1965
100000 stored 200 visible redraw 0.7345 0.8024
100000 stored 200 visible live 0.7693 0.7990
100000 stored 5000 visible redraw 10.5311 9.0193
100000 stored 5000 visible live 9.0146 9.4136

The differences are run-to-run noise. Minimums for the 5000-bar redraw were 5.94 ms before and 5.77 ms after.

Open in Web Open in Cursor 

Reject a non-finite pixel ratio or layout length, and ignore non-finite scroll and zoom-range input so the time scale cannot stick on NaN.

Co-authored-by: Joe Blau <joeblau@users.noreply.github.com>
@cursor
cursor Bot force-pushed the cursor/canvas-scroll-guards-0692 branch from 8355d28 to 727f94b Compare November 10, 2026 19:50
@cursor
cursor Bot merged commit e7cee99 into main Nov 10, 2026
8 checks passed
@cursor
cursor Bot deleted the cursor/canvas-scroll-guards-0692 branch November 10, 2026 19:51
@joeblau joeblau mentioned this pull request Nov 11, 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.

Invariant: the time scale's scroll offset stays finite Invariant: canvas size and pixelRatio are finite and > 0

2 participants