Getting started

edit

Install the package

Add the Meziantou.Framework.JavaScriptEngine package to a project:

dotnet package add Meziantou.Framework.JavaScriptEngine

The examples of this documentation omit the using directives: add using Meziantou.Framework.JavaScriptEngine;.

Run a script

Create an engine, create a realm, and run the script in the realm:

using var engine = new JsEngine();
var realm = engine.CreateRealm();

var result = realm.Execute("const name = 'world'; `Hello, ${name}!`");
Assert.Equal("Hello, world!", result.AsString());
  • JsEngine runs the code and owns its limits and its job queue. It is disposable.
  • JsRealm is a global environment: a global object and its built-ins (Array, Math, JSON...).
  • Execute returns the value of the last statement of the script, as a JsValue. AsString reads a string value.

Expose a function, run promises, catch errors

This example limits the execution of the scripts, gives them a .NET function, runs promise callbacks and catches a JavaScript error:

using var engine = new JsEngine(new JsEngineOptions
{
    Timeout = TimeSpan.FromSeconds(5), // per entry into JavaScript
    RecursionLimit = 1_000,
});

var realm = engine.CreateRealm();

// Expose a .NET function to the scripts. They can pass any value, and fewer arguments than expected: convert the
// arguments explicitly (AsNumber throws when a value is not a number)
using (engine.Enter())
{
    realm.GlobalObject.SetProperty("add", realm.CreateFunction("add", 2, (thisValue, arguments) =>
    {
        var left = arguments.Length > 0 ? engine.ToNumber(arguments[0]) : double.NaN;
        var right = arguments.Length > 1 ? engine.ToNumber(arguments[1]) : double.NaN;
        return left + right;
    }));
}

var result = realm.Execute("const values = [1, 2, 3].map(x => add(x, 10)); values.join('-')");
Assert.Equal("11-12-13", result.AsString());
Assert.Equal("6,NaN", realm.Execute("[add('5', 1), add(1)].join()").AsString());

// The promise jobs run when the host asks for them
realm.Execute("globalThis.log = []; Promise.resolve().then(() => log.push('job')); log.push('script');");
engine.RunJobs();
Assert.Equal("script,job", realm.Execute("log.join()").AsString());

// An uncaught JavaScript error is a JsException
var exception = Assert.Throws<JsException>(() => realm.Execute("null.x"));
Assert.StartsWith("TypeError", exception.Message, StringComparison.Ordinal);

Next steps