Skip to content

fix(runtime): resolve the na helper to NaN in Series.from() (UDT = na defaults) - #315

Merged
alexgrover merged 1 commit into
devfrom
fix/na-helper-udt-defaults
Sep 17, 2026
Merged

alexgrover merged 1 commit into
devfrom
fix/na-helper-udt-defaults

Conversation

@alexgrover

@alexgrover alexgrover commented Sep 16, 2026

Copy link
Copy Markdown
Member

Problem

Running a Pine v6 script with a user-defined type whose fields default to na (e.g. LuxAlgo's RSI Divergence: Out-of-Sample Optimizer) throws on the first bar:

Cannot call 'array.unshift' with argument 'value'='[object Object]'.
An argument of 'literal object' type was used but a 'float' is expected.

Root cause

  • type SimState declares float rsi = na. The transpiler emits the default as ['float', na], where na at runtime is the NAHelper singleton.
  • Type.new resolves defaults via Series.from(default).get(0). Series.from() only unwrapped helpers whose __value is a Series (time, time_close); NAHelper.__value is a scalar NaN, so the helper fell through and was wrapped as an opaque object. The field ended up holding the helper itself.
  • na(obj.x) masked the problem (NAHelper.any special-cases the helper), but nz(obj.x, 50) only checks null/undefined/NaN, so it returned the helper unchanged. On bar 0 the script hits exactly sim.rsi := nz(sim.rsi, 50) and then sim.rsi_hist.unshift(sim.rsi), which rejects the object.

Fix

Series.from() now resolves any __value helper whose value is a scalar (the na helper) to that scalar. This is the common unwrap point, so it fixes UDT = na defaults, nz(na), math.* on such fields, and any other consumer in one place. Duck-typed on __value to avoid a SeriesCore circular import.

Tests

  • New regression test in tests/core/udt-field-defaults.test.ts (explicit \= na` defaults resolve to a real na (NaN), not the na helper object`). Fails with the exact error above before the fix; passes after.
  • Full suite: 175 files / 1878 tests pass.
  • The original reporting script now runs end-to-end on the Mock provider (690-bar RSI plot with zero NaNs, divergence drawings emitted, dashboard table populated).

Note

Medium Risk
Central conversion in Series.from() affects any code path that unwraps __value helpers, though the change is narrow and well-covered by tests.

Overview
Fixes UDT fields declared with = na (e.g. float x = na) storing the runtime NAHelper object instead of NaN, which broke nz(), arithmetic, and typed array operations that expect scalars.

Series.from() now unwraps duck-typed helpers with __value: it still returns backing Series instances for dual-use helpers like time, and for scalar __value (including na’s NaN) wraps that value in a one-element Series instead of treating the whole helper as an opaque object.

Adds a v6 UDT regression test covering nz(obj.x, …), na(obj.x), and obj.x + 1 so defaults behave like real na end-to-end.

Reviewed by Cursor Bugbot for commit a606e27. Bugbot is set up for automated code reviews on this repo. Configure here.

UDT field defaults declared as `float x = na` stored the runtime NAHelper
object in the field instead of NaN. `na(obj.x)` masked it (NAHelper.any
special-cases the helper), but `nz(obj.x, v)` returned the helper untouched,
and pushing that into a typed array threw:

  Cannot call 'array.unshift' with argument 'value'='[object Object]'.
  An argument of 'literal object' type was used but a 'float' is expected.

Series.from() only unwrapped helpers whose `__value` is a Series (time,
time_close). NAHelper's `__value` is a scalar NaN, so it fell through and was
wrapped as an opaque object. Resolve scalar `__value` helpers at this common
unwrap point so UDT defaults, nz(), math.* and every other consumer see a
real NaN.

Adds a regression test to tests/core/udt-field-defaults.test.ts.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Sep 16, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_325eab94-ca17-4a79-ba82-29b87330c6a2)

@alexgrover
alexgrover merged commit 8063043 into dev Sep 17, 2026
2 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant