Skip to content

fix: guard indicator params and WASM kernels - #110

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

cursor[bot] merged 1 commit into
mainfrom
cursor/indicator-wasm-guards-0692

Conversation

@joeblau

@joeblau joeblau commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

Closes #97
Closes #98
Closes #99
Closes #100

Behavior

  • Invariant: indicator params are finite and within each input's declared min/max #97, indicator params. addIndicator, updateIndicator, constructor config.indicators, and updateConfig({ indicators }) drop a non-finite param back to that input's default, then clamp to the declared min/max and round integer inputs, the same way the indicators dialog does. Length helpers that used Math.max(1, Math.floor(...)) now use lengthParam, so a NaN length is the default length instead of NaN.
  • Invariant: main-pane indicator outputs are finite or null #98, indicator outputs. Autoscale treats only finite numbers as prices: seriesMinMax uses Number.isFinite where it used to skip only NaN, and non-finite levels are ignored. A custom indicator that emits Infinity no longer collapses the main scale to 0–1.
  • Invariant: WASM sma/ema kernels are only called with 1 <= period #99, WASM sma/ema. WasmKernels.sma and ema return an all-NaN array when period floors to below 1, including NaN and Infinity. They no longer write before the destination and trap. The parity test no longer expects that trap.
  • Invariant: WASM minmax input is NaN-free #100, WASM minmax. minmax is documented: one NaN makes both results NaN. visibleMinMax uses the kernel only when every high and low in the window is finite, and otherwise uses the scalar loop that skips non-finite prices. The chart render path still passes null and does not scan.

Tests

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

Benchmarks

node bench/suite/run.mjs --samples=7 --sizes=100000, Node 24, median ms/op, back to back.

Case Before After
100000 setData sorted 0.6487 0.6488
100000 setData shuffled 27.5375 28.0972
100000 DataStore single bar append 0.0007 0.0004
100000 chart appendData streaming 0.2062 0.1888
100000 stored 200 visible redraw 0.9025 0.7359
100000 stored 200 visible live 0.8061 0.7687
100000 stored 5000 visible redraw 8.1432 10.3596
100000 stored 5000 visible live 10.1445 9.5226

Sorted setData is unchanged (0.6487 ms vs 0.6488 ms). The render medians move within the noise of this run; the 5000-bar redraw minimums were 5.69 ms before and 6.97 ms after.

Open in Web Open in Cursor 

Clamp indicator params at the API, ignore non-finite indicator outputs when autoscaling, and return NaN from sma/ema when period is below 1 instead of trapping. visibleMinMax skips the SIMD kernel on non-finite windows.

Co-authored-by: Joe Blau <joeblau@users.noreply.github.com>
@cursor
cursor Bot merged commit 543a652 into main Nov 10, 2026
8 checks passed
@cursor
cursor Bot deleted the cursor/indicator-wasm-guards-0692 branch November 10, 2026 20:14
@joeblau joeblau mentioned this pull request Nov 11, 2026
joeblau added a commit that referenced this pull request Nov 11, 2026
- Set @bloxwap/chart (and the workspace apps) to 0.5.0 for the invariant
  and tsrs release (#74, #75, #105–#110)
- Docs, README, llms.txt, OpenAPI and the site's structured data name 0.5.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants