Skip to content

Validate eval/rsg_version against firmware lifecycle#1698

Open
chrisdp wants to merge 3 commits intomasterfrom
feature/eval-rsg-version-validation
Open

Validate eval/rsg_version against firmware lifecycle#1698
chrisdp wants to merge 3 commits intomasterfrom
feature/eval-rsg-version-validation

Conversation

@chrisdp
Copy link
Copy Markdown
Contributor

@chrisdp chrisdp commented May 3, 2026

Summary

Adds firmware-aware diagnostics for eval(...) calls and the manifest's rsg_version entry, driven by lifecycle metadata in a new src/RokuConstants.ts.

What this catches

Code Manifest minFirmwareVersion Outcome
1147 evalIsDeprecatedAtRsgVersion (any) resolves to rsg_version ≥ 1.2 flag every eval(...) call as removed
1148 rsgVersionRequiresMinFirmware rsg_version=1.3 < 15.0 flag manifest
1149 invalidRsgVersionFormat rsg_version=banana (any) warning on the manifest line
1150 rsgVersionDeprecated rsg_version=1.2 ≥ 15.1 suggest upgrading to 1.3
1151 rsgVersionRemoved rsg_version=1.0 ≥ 9.0 error: device no longer honors the entry
1151 rsgVersionRemoved rsg_version=1.1 ≥ 14.5 error: silently treated as 1.2

Default-firmware behavior change

When the user hasn't configured minFirmwareVersion, brighterscript now assumes a default of 15.0.0 so these diagnostics are useful out of the box. Users targeting older firmware can opt out by setting minFirmwareVersion explicitly.

This also affects the existing optional-chaining FW check (BrsFileValidator.ts) — same default applied uniformly via the new Program.getEffectiveMinFirmwareVersion() helper.

Implementation

  • src/RokuConstants.ts — single source of truth for RSG version lifecycle (introducedAt / becameDefaultAt / deprecatedAt / removedAt / replacement), DEFAULT_MIN_FIRMWARE_VERSION, OPTIONAL_CHAINING_MIN_FIRMWARE_VERSION, EVAL_REMOVED_AT_RSG_VERSION. Adding a new RSG version is one entry there; downstream validators pick it up.
  • Manifest.ts — adds parseManifestEntries() (line-aware) alongside the existing parseManifest(). Public API unchanged.
  • Program.ts — adds getEffectiveMinFirmwareVersion() (sanitizes garbage input → DEFAULT) and getRsgVersion() (data-driven default selection). Both getManifestEntries() and getManifestPath() are protected for now — no stable public API yet, will firm up when the manifest gets proper file-tracking support.
  • ProgramValidator.ts — new manifest validator deriving diagnostics from RSG_VERSIONS. Removal takes precedence over deprecation; deprecation only fires when the user's effective firmware actually meets the deprecation threshold (so users on pre-deprecation firmware aren't nagged).
  • BrsFileValidator.ts — adds validateEvalIsNotDeprecated next to the existing optional-chaining check; both route through getEffectiveMinFirmwareVersion().

Sources for lifecycle data

Known gaps / TODOs

These are documented inline so we can revisit as the manifest infrastructure matures:

  • Manifest isn't a tracked file — diagnostics use a { srcPath, pkgPath } stub. Should be replaced by proper file tracking. Code actions for manifest diagnostics are deferred until then.
  • getManifestEntries / getManifestPath accessed via bracket notation — protected for now to avoid committing to a public API.
  • becameDefaultAt semantically broadened — for 1.0/1.1/1.2 it's "device silent fallback"; for 1.3 it's "Roku's cert-policy expected default" (since 1.3 isn't a runtime default but is required by Roku's static analysis tool). TODO comment in RokuConstants flags this for confirmation with Roku.

Test plan

  • npm test — 2808 passing (+ ~40 new), 0 failing
  • npm run lint — clean
  • Per-version test coverage in ProgramValidator.spec.ts (every diagnostic in fire/don't-fire scenarios across firmware windows)
  • eval validator tests in BrsFileValidator.spec.ts covering manifest-explicit / manifest-silent / dotted-method / case-insensitive
  • parseManifestEntries line-aware parser tests
  • Program.getRsgVersion / getEffectiveMinFirmwareVersion sanitization tests

🤖 Generated with Claude Code

Adds firmware-aware diagnostics for `eval` calls and the manifest's
`rsg_version` entry, driven by lifecycle metadata in a new
`src/RokuConstants.ts`.

New behavior:
- `eval(...)` is flagged when the effective rsg_version >= 1.2 (where
  Roku sunset eval as a compile error).
- Manifest `rsg_version` is validated against the configured firmware:
  - rsg_version=1.0 → flagged as deprecated/removed depending on the
    user's effective min FW.
  - rsg_version=1.1 → flagged as removed at firmware 14.5 (Roku
    silently treats it as 1.2 from there on).
  - rsg_version=1.2 → flagged as deprecated at firmware 15.1+ in
    favor of 1.3 (cert deadline 2026-10-01).
  - rsg_version=1.3 → flagged as requiring firmware 15.0+.
  - Invalid format (non-semver) → warning.

When the user hasn't configured `minFirmwareVersion`, brighterscript
now assumes a default of 15.0.0 so these diagnostics are useful out
of the box. Users targeting older firmware can opt out by setting
`minFirmwareVersion` explicitly.

Lifecycle data lives in a single `RSG_VERSIONS` map sourced from
Roku's developer release notes and channel-manifest documentation;
adding a new rsg_version is one entry there.
Comment thread src/bscPlugin/validation/BrsFileValidator.ts Outdated
Comment thread src/Program.ts Outdated
Comment thread src/Program.ts
Comment thread src/bscPlugin/validation/ProgramValidator.ts Outdated
Comment thread src/Program.ts Outdated
Comment thread src/bscPlugin/validation/ProgramValidator.ts Outdated
Comment thread src/DiagnosticMessages.ts Outdated
chrisdp added 2 commits May 5, 2026 16:43
Address PR feedback:
- Add Availability/AvailabilityInfo to Callable. Eval is tagged with
  os.deprecated=9.0.0 and rsg.removed=1.2.0; a single CallExpression
  visitor walks any global callable's availability. Adding a new
  callable's lifecycle is just metadata.
- The validator emits at most one diagnostic per call: rsg axis takes
  precedence; os axis fires only when rsg is silent. Avoids duplicate
  diagnostics on the same line for the common-case modern firmware.
- Replace evalIsDeprecatedAtRsgVersion with two generic diagnostics
  (`globalCallableRemoved`, `globalCallableDeprecated`) parameterized by
  name + axis + threshold + current. Messages match the existing style of
  featureRequiresMinFirmwareVersion (threshold AND current target).
- Diagnostic codes 1147–1152 are renumbered so they appear in numeric
  order in DiagnosticMessages.ts.
- Mark Callable.isDeprecated as @deprecated; availability supersedes it.
- Rename getEffectiveMinFirmwareVersion -> getMinFirmwareVersion. Cache
  it and getRsgVersion. Both return canonical coerced semver strings so
  downstream callers don't re-coerce.
- Drop redundant semver.coerce calls in ProgramValidator.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants