Recursive AI
LibraryC#Available

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.

dotnet add package 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
Program.csC#
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 reportstderr
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)
What it does

What it does

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.

How it’s checked

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.

The packages

Go further