---
title: "oneecma"
url: https://recursiveai.org/oneecma/
description: "An ECMAScript interpreter for .NET in C#, whose product is its error reports. When a script fails it says what went wrong, where the value came from and how to fix it, in text sized for an LLM or as JSON. Limits, [JsExport] bindings, record and replay. MIT or Apache-2.0."
---

# oneecma

An ECMAScript interpreter for .NET whose product is its error reports. When a script fails, it says what went wrong, where the failing value came from and how to fix it.

OneEcma is not affiliated with or endorsed by Ecma International. ECMAScript® is a registered trademark of Ecma International.

```sh
dotnet add package RecursiveAI.OneEcma
```

- [Getting started](https://recursiveai.org/oneecma/docs/getting-started/)
- [Docs](https://recursiveai.org/oneecma/docs/)
- [Cookbook](https://recursiveai.org/oneecma/cookbook/)
- [GitHub](https://github.com/recursive-ai-oss/oneecma-csharp)
- [NuGet](https://www.nuget.org/packages/RecursiveAI.OneEcma)

## A quick look

`checkout.js` reads `order.items`, but the order it awaited holds `lineItems`. The report shows where `order` came from and suggests the fix. The headline is V8’s wording, so code that reads `err.message` keeps working.

[Text, compact and JSON reports](https://recursiveai.org/oneecma/cookbook/error-reports/)

*Program.cs · C#*

```
var engine = new ScriptEngine(new ScriptEngineOptions
{
    Limits = new EngineLimits { Fuel = 50_000_000, WallClockMs = 2_000 },
});
try
{
    engine.Evaluate(File.ReadAllText("checkout.js"), "checkout.js");
}
catch (JsException e)
{
    Console.Error.WriteLine(DiagnosticRenderer.Render(e.Report!));
}
```

*The report · stderr*

```
error[TypeError]: Cannot read properties of undefined (reading 'reduce')
 --> checkout.js:7:23
  |
6 |   const order = await loadOrder(7);
  |                 ------------------ `order` comes from here: { id, lineItems, total }
7 |   const total = order.items.reduce((sum, i) => sum + i.price, 0);
  |                       ^^^^^ `order.items` is undefined
  |
  = help: did you mean `order.lineItems`? (Array, 2 items)
  = stack: main (checkout.js:7)
```

### Reports that explain

Where the failing value came from, the locals of each frame, async stacks stitched across `await`, and suggestions drawn only from what the object holds. A run that succeeds pays nothing for them.

### Sized for a model, or as JSON

A compact rendering fits an LLM’s context, and a versioned JSON report carries the same facts for tools. Syntax errors come all at once, with safe repairs if you ask.

### Every script under limits

Fuel, memory, wall clock, call depth, string length and cancellation. The engine has no file, network, process or environment access of its own.

### .NET bindings written at build time

Mark types `[JsExport]` and a source generator writes the marshalling, with no reflection. A wrong argument names the .NET member, the path and both types.

### Record and replay

The clock, random numbers and host-call results are recorded, so a failed run replays anywhere with the same values and the same report.

### ES2026, Intl and source maps

The ES2026 language and built-ins, Intl for six locales, and ECMA-426 source maps that point reports at the code you wrote.

## test262, and Node byte for byte

On the pinned test262 suite, 22,973 language and 18,337 built-ins tests pass, with no unexpected failures and every documented failure listed with its reason. `err.message` and `err.stack` are compared with Node on a differential corpus. On lodash, preact and a React server render, each checked byte for byte against Node, it takes 0.62 to 1.08 times Jint’s time, on a fresh engine per run.

- [Conformance](https://recursiveai.org/oneecma/docs/overview/#conformance)
- [Benchmarks](https://recursiveai.org/oneecma/docs/benchmarks/)

## The packages

- **RecursiveAI.OneEcma**: The engine, Intl included: `ScriptEngine`, the host API, limits, reports, source maps, record and replay. No dependency beyond the .NET base class library. 1.0.0.
- **.Generators**: `RecursiveAI.OneEcma.Generators` is the `[JsExport]` source generator. It runs in the compiler and adds nothing to your output. 1.0.0.
- **.Cli**: `RecursiveAI.OneEcma.Cli` is the `oneecma` command: `run`, `check` and `repl`. NativeAOT binaries for Windows, Linux and macOS are on the [GitHub release](https://github.com/recursive-ai-oss/oneecma-csharp/releases/tag/v1.0.0). 1.0.0.
- **.NET**: .NET 10, pure C#. NativeAOT and trimming are supported. Every package shares one version. MIT or Apache-2.0.

## Go further

- [GitHub](https://github.com/recursive-ai-oss/oneecma-csharp)
- [NuGet](https://www.nuget.org/packages/RecursiveAI.OneEcma)
- [Getting started](https://recursiveai.org/oneecma/docs/getting-started/)
- [All docs](https://recursiveai.org/oneecma/docs/)
- [Cookbook](https://recursiveai.org/oneecma/cookbook/)
- [Untrusted JavaScript](https://recursiveai.org/oneecma/cookbook/sandbox/)
- [Code a model wrote](https://recursiveai.org/oneecma/cookbook/run-model-code/)
- [[JsExport] bindings](https://recursiveai.org/oneecma/cookbook/jsexport/)
- [From Jint or ClearScript](https://recursiveai.org/oneecma/cookbook/migrate-from-jint-clearscript/)
- [Changelog](https://github.com/recursive-ai-oss/oneecma-csharp/blob/v1.0.0/CHANGELOG.md)
