Skip to content

v0.13.0 - Libraries & Named Arguments for Every Built-in - #477

Merged
alexgrover merged 11 commits into
mainfrom
dev
Oct 22, 2026
Merged

alexgrover merged 11 commits into
mainfrom
dev

Conversation

@alexgrover

@alexgrover alexgrover commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Release 0.13.0. See the [0.13.0] entry in CHANGELOG.md: Pine Script libraries (import / export) with pluggable import resolvers (#458), and named arguments for every built-in function and method (#464).

Made with Cursor


Note

Medium Risk
Large surface area across transpiler, runtime, and new network/file import paths; incorrect linking or named-arg mapping could change indicator output broadly, though the release is heavily test-backed.

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

alexgrover and others added 11 commits October 20, 2026 16:29
…rs take their defaults

A user method called with method syntax and named arguments, `obj.m(a = x)`, received the named arguments as one positional value; they now bind to the method's parameters after the receiver, as in the function-syntax call `m(obj, a = x)`. A built-in method name or a namespace receiver (`label.new(text = ...)`) is left alone.

A parameter a named-argument call skips (`f(10, z = 7)` with a defaulted `y`) read as na: the gap was passed as an explicit `undefined`, which reaches the function wrapped as a series and bypasses the default. Codegen now fills it with the parameter's default value, which Pine restricts to a literal or a built-in variable, so it evaluates the same at the call site. A string parameter defaulting to `na` gets the empty string, as in the signature.

Expected values are computed by hand from Pine's binding rules.

Co-authored-by: Cursor <cursoragent@cursor.com>
`import <user>/<library>/<version> [as <alias>]` is parsed (the alias defaults to the library name), and so are `export` before functions, methods, types and enums, and the `library()` declaration, which now also runs as an indicator would.

Library sources come from an import resolver set with `PineTS.setImportResolver`: a function `(path, info) => source`. Before transpiling, `Indicator.resolveImports` collects the script's libraries and theirs; a `CachedImportResolver` requests each path once, shared across runs and with request.security contexts. Ready-made resolvers: `ImportResolver.fromMap`, `fromFiles` (Node.js), `fromUrl`, `fromGitHub` (raw.githubusercontent.com, or the contents API with a token for private repositories) and `chain`.

The linker (pineToJS/linker.ts) splices each library's declarations into the importing script's Pine AST where its imports stood, renamed with a `<user>$<library>$<version>$` prefix (`$` is not a Pine identifier character), and rewrites `alias.member` references: functions, `alias.Type.new()`, type annotations, `alias.Enum.field`, and `alias.method(obj)` as `obj.method()`. The rest of the pipeline sees ordinary user code, so each call site keeps its own `var` / `ta.*` state. Exported methods keep their name for method-syntax dispatch; private ones are renamed. Only declarations reachable from the script are linked, so a library's unresolved import only fails when the script uses code that needs it. An alias named like a built-in namespace keeps reaching the built-ins the library does not export.

Docs: docs/libraries.md.
Co-authored-by: Cursor <cursoragent@cursor.com>
The resolver API was closures returned by an `ImportResolver` object of factories, typed as a function-or-`{ resolve }` union, with caching added silently by an outside wrapper. It is rebuilt like the data providers:

- `IImportResolver` interface (`resolve`, `configure`), mirroring `IProvider`.
- `BaseImportResolver<TConfig>`: `resolve()` drives the cache (one request per import path, concurrent requests shared, errors not kept, optional `cacheDuration`, emptied by `configure()` / `clearCache()`) and the fail-early configuration check, and delegates to `_resolveNative()`, as `getMarketData()` delegates to `_getMarketDataNative()`.
- One class per source, each in its own folder with a typed config and `configure()`: `GitHubImportResolver`, `FileImportResolver`, `UrlImportResolver`, `MapImportResolver`, `ChainImportResolver`, and `FunctionImportResolver` for a plain function.
- `ImportResolver` registry of ready instances (`ImportResolver.GitHub.configure({ url, token })`) and `registerImportResolver`, mirroring `Provider`.
- `FileImportResolver` reads files with `fs` and is stubbed in browser builds, as `MockProvider` is (the rollup plugin now handles both).

Two wiring fixes come with it. A `request.*` secondary context inherits its parent's resolver in `markAsSecondary(parent)` instead of at each call site. An `Indicator` run with another resolver resolves its imports again, and transpiles again if the sources differ; it kept the first resolver's libraries.

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

The usage guide gets a Libraries section (setImportResolver, the ImportResolver registry and classes, link to the Libraries page); the README lists libraries in its features, documentation links and roadmap; AGENTS.md shows the linker in the Stage 1 pipeline and src/imports/ and tests/imports/ in the file tree; the pineToJS README describes the linking step. The Libraries page tables are aligned.

Co-authored-by: Cursor <cursoragent@cursor.com>
Named arguments were only read by the functions that parse their own
named-arguments object. Everywhere else the whole object landed in the
first parameter: ta.sma(source = close, length = 5) was na on every bar,
and the same held for math, str, color, ticker, timeframe, chart.point,
syminfo, the type conversions, array.new_*, strategy getters and risk
rules, array / matrix / map functions and methods, and user methods.

- Codegen: a named call to a built-in listed in BUILTIN_PARAMS (parameter
  names per overload, Pine v6 reference order), or to a user method,
  compiles to its positional form; the overload is picked by the names. A
  skipped parameter is passed as a bare undefined so its default applies.
- Runtime: collection objects (array / matrix / map) spread a trailing
  named-arguments object in method calls, drawing helpers find it behind
  trailing undefineds, and table.new / cell / clear / merge_cells,
  linefill.set_color and footprint.get_row_by_price spread it too.
- parseArgsForPineParams reads a Series passed for a scalar parameter at
  the current bar and skips undefined: a positional number / bool used to
  drop every argument after it (plot, plotchar, barcolor, bgcolor, ...).
- Positional fixes found by the sweep: plot linestyle, fill() between
  hlines (no show_last), strategy() positional settings, label.new /
  box.new sizes in points, matrix.sort order constants.

Co-authored-by: Cursor <cursoragent@cursor.com>
Libraries: import / export with pluggable cached import resolvers
Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	src/transpiler/pineToJS/codegen.ts
Named arguments for every built-in function and method
Co-authored-by: Cursor <cursoragent@cursor.com>
changelog + version bump (0.13.0)
@cursor

cursor Bot commented Oct 22, 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: 17f34a3a-04d8-4e95-8ba0-bfe8b9ac89f7)

@alexgrover
alexgrover merged commit 7e04d6b into main Oct 22, 2026
2 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 22, 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