Getting started
editInstall the package
Add the Meziantou.Framework.JavaScriptEngine package to a project:
dotnet package add Meziantou.Framework.JavaScriptEngineThe 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);- JsEngineOptions sets the limits of each entry into JavaScript. See Limits and sandboxing.
- CreateFunction creates a JavaScript function implemented by a .NET delegate. Reading and writing properties, such as
GlobalObject.SetProperty, happens insideengine.Enter(). See Engines and realms and Functions. - The callbacks of promises run when you call RunJobs. See Async code and promises.
- An uncaught JavaScript error is thrown as a JsException. See Handling errors.
Next steps
- Engines and realms: engines, realms, scopes and threads.
- Running code: scripts, modules and errors.
- Exchanging values: values, objects, functions and binary data.