Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/badges/api-color.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions .github/badges/api-coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions .github/badges/api-types.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions .github/badges/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,57 @@
# Change Log

## [0.9.4] - 2026-03-11 - Color Namespace, Transpiler Overhaul, request.security & Drawing Improvements

### Added

- **`color` Namespace Refactor**: Extracted the full color implementation from `Core.ts` into a dedicated `src/namespaces/color/PineColor.ts` module. Adds complete `COLOR_CONSTANTS` (all named palette colors), improved hex/rgb/rgba/`#RRGGBBAA` parsing, `color.from_gradient()` with NaN guard, and a full test suite.
- **`alert()` Stub**: Added the missing `alert()` function (previously only `alertcondition` existed). Emits to the context event bus so downstream code can subscribe without crashing.
- **`max_bars_back()` No-Op**: Added `max_bars_back(source, length)` as a compatibility stub. Returns its source argument unchanged (PineTS maintains full history, so there is no lookback cap to configure).
- **`linefill` Instance Methods**: `LinefillObject` now exposes `get_line1()`, `get_line2()`, and `set_color()` directly on the instance, enabling UDT field-chain patterns like `myStruct.fill.set_color(c)`.
- **UDT `.new()` Named Arguments**: `MyType.new(field1=val1, field2=val2)` now works correctly. The UDT constructor detects a named-argument object and maps keys to fields instead of positional assignment.
- **`linefill.new` Thunking**: Added `linefill.new` to `FACTORY_METHODS` so it receives the arrow-function thunk treatment in `var` declarations, preventing orphaned linefill objects from being created on every bar.
- **`math.__neq()` — Inequality Operator**: Added `math.__neq(a, b)` to handle Pine Script's `!=` / `<>` operator with proper NaN semantics (mirrors `math.__eq`).

### Fixed

#### Transpiler

- **For-Loop Init & Update `$.get()` Wrapping**: The for-loop init and update expressions lacked `addArrayAccess`, `MemberExpression`, and `CallExpression` handlers. Series variables appearing in loop bounds (e.g., `for i = 0 to bar_index - 1`) were left as raw Series objects, causing the update ternary to evaluate to `NaN` and producing infinite loops or bodies that never executed.
- **While-Loop Test Condition**: `while bar_index > cnt` and similar conditions with Series variables were not wrapped in `$.get()`, so the comparison always evaluated against a raw Series object (→ `NaN`). Fixed by adding missing `addArrayAccess` and namespace-object skip logic to `transformWhileStatement`.
- **Function-Scoped Variable Resolution**: Added `isVariableInFunctionScope()` to `ScopeManager`. `createScopedVariableReference()` now correctly resolves `var` declarations inside nested `if`/`for` blocks *within* functions to the local context (`$$`) instead of the global context (`$`).
- **Optional Chaining for `na` UDT Drawing Fields**: `hasGetCallInChain()` now traverses `MemberExpression` *and* intermediate `CallExpression` nodes to detect `$.get()` in deeper chains. Inserts `?.` on the final method call so `myStruct.line?.set_x2(x)` does not crash when the field is `na`/`undefined`.
- **User Function vs Method Call Disambiguation**: Added `isChainedPropertyMethod` guard — when the callee object is itself a `MemberExpression` (e.g., `myObj.x.set()`), the call is not mistakenly redirected through `$.call()` even if `set` happens to be a user-defined function name. Added `_skipTransformation = true` on function-reference identifiers inside `$.call()` to prevent them from resolving to same-named variables.
- **`hasGetCallInChain()` Chain Expression Traversal**: Extended to walk through `ChainExpression` wrapper nodes (`?.` optional chains) so already-wrapped intermediate nodes are also checked when determining whether to insert optional chaining.
- **`ReturnStatement` Walk-Through**: `MainTransformer`'s `ReturnStatement` handler now recurses into complex return arguments when not in function scope, preventing untransformed expressions in nested return statements.
- **`parseArgsForPineParams` NaN Handling**: Fixed dynamic Pine Script signatures passing `NaN` values through the argument normalizer, which caused downstream `isNaN` checks to misidentify valid numeric `0` values.
- **Await Propagation in User-Defined Functions**: Functions containing `request.security` calls (which are async internally) now correctly propagate `async`/`await` through the function declaration, preventing unresolved Promise objects from reaching callers.
- **Tuple Destructuring in User Functions**: Fixed the Pine Script parser emitting single-bracket `[a, b]` returns instead of the required double-bracket `[[a, b]]` tuple form when `=>` arrow functions ended with an `if/else` that returned a tuple.
- **Function Parameter Namespace Collision Renaming**: Parameters whose names collide with built-in namespaces (e.g., a parameter named `color`) were being looked up as namespace objects instead of local variables. The transpiler now renames such parameters to avoid the collision.
- **ArrayExpression Function Parameter Scoping**: Function parameters used inside array literal arguments (e.g., `[output, ...]`) were incorrectly resolved to the global scope (`$.let.output`) instead of the local raw identifier (`output`). Added `isLocalSeriesVar` check in `ExpressionTransformer`.
- **Switch Statement Tuple Destructuring**: IIFE array returns inside switch branches were not wrapped in the required `[[a, b, c]]` double-bracket form, causing `$.init()` to treat the tuple as a time-series and extract only the last element.
- **Array/Matrix Typed Declarations**: The Pine Script parser now correctly parses `array<float>`, `matrix<int>`, and other generic typed declarations in variable declarations and function signatures. Strong-typing tests cover all primitive and object element types.

#### Runtime

- **`plotcandle` and `barcolor`**: Fixed incorrect argument mapping and color resolution in both functions. `barcolor` now correctly applies per-bar color overrides to the candlestick series, and `plotcandle` produces properly structured OHLC plot data.
- **`request.security` Expression Handling**: Complex expressions passed as the `expression` argument (not just simple identifiers or plot references) now evaluate correctly in the secondary context. Also fixed user-defined method expressions being passed across context boundaries.
- **`request.security_lower_tf` Pine Script Behavior**: Rewrote lower-timeframe (LTF) aggregation to match TradingView's behavior — values are collected as intra-bar arrays, and the correct array element (first vs. last vs. all) is returned depending on `lookahead` / `gaps` settings.
- **Normalized Timeframes**: `timeframe.in_seconds()` and related utilities now correctly handle all non-canonical formats (`'1h'`→`'60'`, `'1d'`→`'D'`, `'1w'`→`'W'`) and return `NaN`/`0` when given `undefined` or an unrecognised string.
- **Plot Color Change Detection**: Fixed false positives in the plot color-change detector that caused unnecessary re-renders when the color value was numerically identical but represented by different intermediate Series wrappers.
- **`str.split()` Returns Pine Array**: `str.split()` was returning a plain JavaScript array. It now returns a `PineArrayObject` so array namespace methods (`.get()`, `.size()`, etc.) work on the result.
- **Label Colors & Backgrounds**: Fixed `label.set_textcolor()` and `label.set_bgcolor()` not applying when called after construction, and resolved parsing inconsistencies in `parseArgsForPineParams` that treated valid color `0` as `na`.
- **`color.from_gradient` NaN Guard**: Added `null`/`NaN`/`undefined` guards for all five arguments; previously a missing value produced `#NANNANNAN` hex strings.
- **Improved Color Parsing**: `PineColor` now handles all Pine Script color representations uniformly: 6-digit hex, 8-digit hex (`#RRGGBBAA`), `rgb()`, `rgba()`, named constants, and `color.new()` output.
- **Polyline Rendering Fixes**: Fixed `polyline.new()` crash when `points` contained `na` entries, incorrect `xloc` handling for bar-index vs. time coordinates, and missing default line/fill colors.
- **Array `new_*` Capacity Handling**: `array.new<T>(size, initial)` variants now clamp the requested capacity to `MAX_ARRAY_SIZE` and correctly initialise all elements to the provided default (was previously initialising to `undefined` in some typed constructors).
- **Table Cell Null Guard**: `table.cell()` now guards against `null`/`undefined` row or column indices, preventing a crash when table access patterns involve conditional creation.
- **`chart.fg_color`**: Fixed `chart.fg_color` returning the wrong value (`bg_color` was returned for both properties due to a copy-paste error).
- **Default Colors for Polyline and Table**: `polyline.new()` and `table.new()` no longer require explicit color arguments; sensible defaults are applied when colors are omitted or `na`.
- **User Functions Treated as Native Functions**: Fixed a regression where user-defined functions registered in `settings.ts` were forwarded through the native namespace dispatcher instead of the user function call path.
- **Sourcemap Generation for Browser Dev Build**: Fixed the rollup sourcemap pipeline for the `build:dev:browser` target so browser DevTools correctly resolve transpiled runtime errors to TypeScript source lines.

---

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

### Added
Expand Down
8 changes: 4 additions & 4 deletions docs/api-coverage/color.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ parent: API Coverage
| `color.from_gradient()` | ✅ | Create color from gradient |
| `color.new()` | ✅ | Create new color |
| `color.rgb()` | ✅ | Create color from RGB values |
| `color.b()` | | Get blue component |
| `color.g()` | | Get green component |
| `color.r()` | | Get red component |
| `color.t()` | | Get transparency component |
| `color.b()` | | Get blue component |
| `color.g()` | | Get green component |
| `color.r()` | | Get red component |
| `color.t()` | | Get transparency component |
10 changes: 5 additions & 5 deletions docs/api-coverage/pinescript-v6/color.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
"color.yellow": true
},
"Color Functions": {
"color.b()": false,
"color.b()": true,
"color.from_gradient()": true,
"color.g()": false,
"color.g()": true,
"color.new()": true,
"color.r()": false,
"color.r()": true,
"color.rgb()": true,
"color.t()": false
"color.t()": true
}
}
}
22 changes: 11 additions & 11 deletions docs/api-coverage/pinescript-v6/types.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,14 @@
"position.top_right": true
},
"scale": {
"scale.left": false,
"scale.none": false,
"scale.right": false
"scale.left": true,
"scale.none": true,
"scale.right": true
},
"settlement_as_close": {
"settlement_as_close.inherit": false,
"settlement_as_close.off": false,
"settlement_as_close.on": false
"settlement_as_close.inherit": true,
"settlement_as_close.off": true,
"settlement_as_close.on": true
},
"shape": {
"shape.arrowdown": true,
Expand Down Expand Up @@ -209,14 +209,14 @@
"splits.numerator": true
},
"text": {
"text.align_bottom": false,
"text.align_bottom": true,
"text.align_center": true,
"text.align_left": true,
"text.align_right": true,
"text.align_top": false,
"text.format_bold": false,
"text.format_italic": false,
"text.format_none": false,
"text.align_top": true,
"text.format_bold": true,
"text.format_italic": true,
"text.format_none": true,
"text.wrap_auto": true,
"text.wrap_none": true
},
Expand Down
22 changes: 11 additions & 11 deletions docs/api-coverage/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,17 @@ parent: API Coverage

| Function | Status | Description |
| ------------- | ------ | ----------- |
| `scale.left` | | Left scale |
| `scale.none` | | No scale |
| `scale.right` | | Right scale |
| `scale.left` | | Left scale |
| `scale.none` | | No scale |
| `scale.right` | | Right scale |

### Settlement_as_close

| Function | Status | Description |
| ----------------------------- | ------ | --------------------------- |
| `settlement_as_close.inherit` | | Inherit settlement as close |
| `settlement_as_close.off` | | Settlement as close off |
| `settlement_as_close.on` | | Settlement as close on |
| `settlement_as_close.inherit` | | Inherit settlement as close |
| `settlement_as_close.off` | | Settlement as close off |
| `settlement_as_close.on` | | Settlement as close on |

### Shape

Expand Down Expand Up @@ -230,14 +230,14 @@ parent: API Coverage

| Function | Status | Description |
| -------------------- | ------ | --------------------- |
| `text.align_bottom` | | Bottom text alignment |
| `text.align_bottom` | | Bottom text alignment |
| `text.align_center` | ✅ | Center text alignment |
| `text.align_left` | ✅ | Left text alignment |
| `text.align_right` | ✅ | Right text alignment |
| `text.align_top` | | Top text alignment |
| `text.format_bold` | | Bold text format |
| `text.format_italic` | | Italic text format |
| `text.format_none` | | No text format |
| `text.align_top` | | Top text alignment |
| `text.format_bold` | | Bold text format |
| `text.format_italic` | | Italic text format |
| `text.format_none` | | No text format |
| `text.wrap_auto` | ✅ | Auto text wrap |
| `text.wrap_none` | ✅ | No text wrap |

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pinets",
"version": "0.9.3",
"version": "0.9.4",
"description": "Run Pine Script anywhere. PineTS is an open-source transpiler and runtime that brings Pine Script logic to Node.js and the browser with 1:1 syntax compatibility. Reliably write, port, and run indicators or strategies on your own infrastructure.",
"keywords": [
"Pine Script",
Expand Down
1 change: 1 addition & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ const BrowserConfigDev = {
format: 'umd',
name: 'PineTSLib',
exports: 'auto',
sourcemap: true,
},
plugins: [
excludeMockProvider(),
Expand Down
8 changes: 8 additions & 0 deletions scripts/generate-matrix-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ ${getters.map((g) => ` ${g}: ${g}`).join(',\n')}
})
.join('\n');

// Type-specific aliases for matrix.new<TYPE>() → matrix.new_TYPE()
// The transpiler rewrites generic type params to method name suffixes
const typeAliases = ['float', 'int', 'string', 'bool', 'color', 'line', 'label', 'box', 'linefill', 'table'];
const typeAliasInstall = typeAliases.map(t => ` this.new_${t} = new_fn(context);`).join('\n');

const classCode = `// SPDX-License-Identifier: AGPL-3.0-only
// This file is auto-generated. Do not edit manually.
// Run: npm run generate:matrix-index
Expand All @@ -146,6 +151,9 @@ export class PineMatrix {
${getterInstall}
// Install methods
${methodInstall}
// Type-specific aliases — used internally by PineTS to handle strong types.
// The transpiler rewrites matrix.new<float>(...) → matrix.new_float(...)
${typeAliasInstall}
}
}

Expand Down
Loading
Loading