Skip to content

## [0.9.3] - 2026-03-06 - Streaming Support, request.security Fixes, Transpiler Robustness#153

Merged
alaa-eddine merged 13 commits intomainfrom
dev
Mar 6, 2026
Merged

## [0.9.3] - 2026-03-06 - Streaming Support, request.security Fixes, Transpiler Robustness#153
alaa-eddine merged 13 commits intomainfrom
dev

Conversation

@alaa-eddine
Copy link
Collaborator

Added

  • array.new_box / new_label / new_line / new_linefill / new_table / new_color: Added the six missing typed array factory methods so array<box>, array<label>, etc. can be created with a proper element type. The auto-generator (scripts/generate-array-index.js) now lists them as static factory functions (called with context) rather than instance delegates. isValueOfType in array/utils.ts was extended to accept object values for these types, allowing array.push(label.new(...)) on typed arrays.
  • request.security — Live Streaming Support: request.security now correctly handles live (streaming) bar updates. The secondary context is re-evaluated on each tick, and findSecContextIdx resolves the correct intra-bar index for the current live bar. Paired with drawing-object rollback (see below), streaming ticks no longer produce duplicate drawing objects.
  • str.tostring Format Patterns: Added support for Pine Script's named and pattern-based format strings: "#", "#.#", "#.##", "0.00", and the format.* named constants. The formatter now applies these patterns before falling back to toString().

Fixed

  • While-Loop Test Condition Hoisting (infinite-loop crash): array.size() and similar calls in a while condition were being hoisted to a temp variable outside the loop by the default CallExpression walker, making them one-shot evaluations and causing an infinite loop followed by a crash. MainTransformer now registers a WhileStatement handler and transformWhileStatement was rewritten to use a recursive walker with hoisting suppressed throughout the entire test condition.
  • Array Pattern Scoping Crash: isArrayPatternVar was determined using a global (non-scoped) set in ScopeManager. A local function variable whose name happened to match an outer-scope destructured tuple element was falsely treated as an array pattern, causing a runtime crash. Fixed by adding a shape guard: the flag is only set when decl.init is a computed MemberExpression (the _tmp_0[0] pattern produced by the AnalysisPass destructuring rewrite).
  • For-Loop Namespace Wrapping (math.min$.get(math, 0).min): In the for-loop test condition walker, MemberExpression nodes unconditionally recursed into their object, causing the Identifier handler to wrap context-bound namespace objects (math, array, ta, …) with $.get(). Fixed by skipping recursion and addArrayAccess for identifiers that are the object of a MemberExpression and are context-bound namespaces.
  • request.security Cross-Timeframe Value Alignment: barmerge.gaps_off / barmerge.lookahead_off were passed as strings; their truthiness caused findLTFContextIdx to take the wrong branch (returning the first intra-bar instead of the last). Fixed by converting barmerge string enums to booleans. Added normalizeTimeframe() to map non-canonical formats ('1h''60', '1d''D') so isLTF determination is correct. Fixed secondary context date-range derivation to use effectiveSDate from marketData and extend secEDate to cover the last bar's intra-bars.
  • barmerge Missing from CONTEXT_BOUND_VARS: barmerge.gaps_off / barmerge.lookahead_off (used in request.security()) were not in the transpiler's context-bound list, so they were left as bare identifiers instead of being mapped to the runtime context. Added 'barmerge' to settings.ts.
  • barstate.isconfirmed Wrong Bar: Was checking whether the last bar's close time equalled the session close via closeTime[length-1] (always the last bar in history) instead of the currently-executing bar. Fixed to use closeTime.data[context.idx] for correct per-bar evaluation.
  • array.get() Out-of-Bounds → NaN: array.get(arr, -1) and other out-of-bounds accesses returned undefined (native JS), causing crashes when Pine Script code accessed properties (e.g., .strength) on the result. The method now returns NaN (Pine's na) for negative or out-of-range indices.
  • Drawing Helpers — na Color Resolution: Drawing object helpers' _resolve() method now detects NAHelper instances and returns NaN, fixing cases where border_color=na (and similar na arguments) were silently ignored in box.new(), line.new(), etc. BoxHelper also gains a dedicated _resolveColor() that preserves NaN instead of letting it fall through an || fallback to the default color.
  • Streaming Rollback for Drawing Objects: All five drawing types (box, line, label, linefill, polyline) now track a _createdAtBar property and expose a rollbackFromBar(barIndex) method. Context.rollbackDrawings() calls this during _runPaginated / updateTail to remove any drawing objects created on the current streaming bar before re-running it, preventing duplicate objects from accumulating across live ticks.

Fix for typed arrays handling
Fix Box/Line instances member functions access
Fix : non computed properties access
The arrayPatternElements set in ScopeManager is global (not scoped per function). When a function like calcFibLevels has local variables (fib236, priceRange, etc.) that share names with destructured tuple results in the outer scope, they were falsely flagged as array pattern elements.
Fix: Added a shape guard — isArrayPatternVar is only true when decl.init is a computed MemberExpression (the _tmp_0[0] pattern from the AnalysisPass destructuring rewrite). This ensures same-named local variables in functions are processed normally.
Fix 2 — Missing barmerge namespace (settings.ts):

barmerge.gaps_off / barmerge.lookahead_off (used in request.security()) were not in the CONTEXT_BOUND_VARS list, so the transpiler didn't map them to the runtime context.
Fix: Added 'barmerge' to the list.

Fix 3 : MemberExpression handler: Skip recursion into context-bound namespace identifiers (mirroring the MainTransformer behavior) — these are namespace objects, not series variables
Identifier handler: Added safety check to skip addArrayAccess for namespace identifiers that are objects of MemberExpressions

Fix 4 : Added bounds checking — returns NaN (Pine's na) for negative or out-of-bounds indices instead of undefined.

Test Results
1041 tests pass, 0 failures
pressure-zone-analyzer.pine runs successfully (both stripped and full versions with

================================
Fixes Applied
1. Transpiler bug: Namespace identifiers in for-loop test conditions get $.get() wrapping
File: PineTS/src/transpiler/transformers/StatementTransformer.ts

Problem: In the for-loop test condition walker, the MemberExpression handler was unconditionally recursing into the object of namespace method calls (like math.min, array.size), which caused the Identifier handler to wrap namespace objects with $.get(). This turned correct math.min(array.size(...)) into broken $.get(math, 0).min($.get(array, 0).size(...)).

Fix: Two changes:

MemberExpression handler: Skip recursion into context-bound namespace identifiers (mirroring the MainTransformer behavior) — these are namespace objects, not series variables
Identifier handler: Added safety check to skip addArrayAccess for namespace identifiers that are objects of MemberExpressions
2. Runtime crash: array.get() with out-of-bounds index
File: PineTS/src/namespaces/array/methods/get.ts

Problem: array.get(arr, -1) returned undefined (native JS behavior), causing crashes when accessing UDT properties like .strength on the result.

Fix: Added bounds checking — returns NaN (Pine's na) for negative or out-of-bounds indices instead of undefined.

Test Results
1041 tests pass, 0 failures
pressure-zone-analyzer.pine runs successfully (both stripped and full versions with request.security)

===========================
1. While-loop test condition hoisting bug (the crash fix)
Problem: while array.size(zones) > maxZones had array.size() hoisted to a temp variable outside the loop, making it a one-shot evaluation → infinite loop → crash on undefined.zoneLine
Root cause: No WhileStatement handler in MainTransformer.ts, so the default walker let the CallExpression handler hoist calls from the test condition
Fix: Added WhileStatement handler to MainTransformer.ts and rewrote transformWhileStatement in StatementTransformer.ts with proper call/member/identifier handling and suppressed hoisting
2. For-loop namespace wrapping (from previous session)
math.min(array.size(...)) in for-loop tests was incorrectly wrapped as $.get(math, 0).min(...)
Fixed by skipping addArrayAccess for context-bound namespace identifiers
3. barstate.isconfirmed (from previous session)
Was checking last bar's close time via closeTime[length-1] instead of current bar
Fixed to use closeTime.data[context.idx] (raw array access on the Series)
4. str.tostring format patterns (from previous session)
Added support for "#", "#.#", "#.##", named formats
5. array.get bounds checking (from previous session)
Out-of-bounds access now returns NaN instead of undefined
Convert barmerge string enums ('gaps_off'/'lookahead_off') to boolean in security.ts - truthy strings caused findLTFContextIdx to take the wrong code path (returning first intrabar instead of last). Add normalizeTimeframe() to map non-canonical timeframe formats ('1h'→'60', '1d'→'D') for correct isLTF determination. Fix secondary context date range derivation (effectiveSDate from marketData, secEDate covering last bar's intrabars).
…ew_linefill, new_table, new_color in PineTS/src/namespaces/array/methods/

Updated the auto-generator (scripts/generate-array-index.js) — added the new methods to the staticMethods list so they're treated as factory functions (called with context) not instance delegates

Fixed isValueOfType type validation (PineTS/src/namespaces/array/utils.ts) — added cases for box, label, line, linefill, table, color types to accept objects (and null), so array.push(label.new(...)) works on typed arrays
…lback for drawing objects

Drawing helpers (_resolve) now detect NAHelper instances and return NaN,
fixing border_color=na being ignored in box.new() and other constructors.
BoxHelper gains _resolveColor() to preserve NaN instead of falling through
the || fallback.

All five drawing object types (box, line, label, linefill, polyline) now
track _createdAtBar and expose rollbackFromBar(), wired through
Context.rollbackDrawings() and called in _runPaginated / updateTail so
that streaming ticks no longer accumulate duplicate drawing objects.
## [0.9.3] - 2026-03-06 - Streaming Support, request.security Fixes, Transpiler Robustness
@alaa-eddine alaa-eddine merged commit ad26f8d into main Mar 6, 2026
1 check passed
@github-actions github-actions bot locked and limited conversation to collaborators Mar 6, 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