JsEngine Class
An ECMAScript agent (https://tc39.es/ecma262/#sec-agents): it owns the realms, the job queue and the execution limits of the scripts it runs. An engine is used by one thread at a time.
public sealed class JsEngine : IDisposable- Implements
Constructors
| Name | Description |
|---|---|
| JsEngine(JsEngineOptions?) | Initializes a new instance of the JsEngine class. |
JsEngine(JsEngineOptions?)
JsEngine.Async.csInitializes a new instance of the JsEngine class.
public JsEngine(JsEngineOptions? options = null)Parameters
optionsJsEngineOptions?
Properties
| Name | Description |
|---|---|
| CurrentRealm | Gets the realm of the running execution context (the current realm). |
| IsScriptRunning | Gets whether a script is running (the execution context stack is not empty). |
| Options | Gets the options of the engine: a copy of the options given to the constructor. The limits can be changed on the thread of the engine; the other options cannot (see JsEngineOptions). |
| Realms | Gets the realms created by JsEngine.CreateRealm (the realms of the ShadowRealm objects are not included). |
CurrentRealm
JsEngine.csIsScriptRunning
JsEngine.Execution.csOptions
JsEngine.csGets the options of the engine: a copy of the options given to the constructor. The limits can be changed on the thread of the engine; the other options cannot (see JsEngineOptions).
public JsEngineOptions Options { get; }Property value
Realms
JsEngine.csGets the realms created by JsEngine.CreateRealm (the realms of the ShadowRealm objects are not included).
public IReadOnlyList<JsRealm> Realms { get; }Property value
Methods
| Name | Description |
|---|---|
| Call(JsValue, JsValue, ReadOnlySpan<JsValue>) | Call(F, V, argumentsList) (https://tc39.es/ecma262/#sec-call). |
| CaptureStackTrace() | Captures the stack trace of the running code, in the format of the stack property of the errors (without the first line). |
| CheckInterrupt() | Throws a JsTerminationException when the running script must stop: the execution is canceled (JsEngineOptions.CancellationToken), a limit of JsEngineOptions or of an execution scope (JsEngine.EnterExecutionScope) is exceeded, or the running entry was already terminated. The host calls it periodically while it runs code on behalf of the script (e.g. WebAssembly code); the engine checks the limits itself while JavaScript code and the built-in functions run. |
| Construct(JsValue, ReadOnlySpan<JsValue>, JsValue) | Construct(F, argumentsList, newTarget) (https://tc39.es/ecma262/#sec-construct); newTarget is the constructor when it is undefined. |
| CreateRealm() | Creates a realm with its intrinsics and an ordinary global object. |
| Dispose() | Releases the resources of the engine: the work posted afterwards does not run (JsEngine.Post), and the pending tasks of JsEngine.ToTask are canceled. |
| EnqueueJob(Action, JsRealm?) | Enqueues a job in the promise job queue (a microtask): it runs from JsEngine.RunJobs, after the jobs already in the queue. |
| Enter() | Makes the engine the engine of the current thread until the returned scope is disposed. The methods of the objects (JsObject.GetProperty...) need it when they are not called by the engine (a callback). |
| EnterActiveScriptOrModule(JsScriptOrModule?) | Pushes an execution context whose ScriptOrModule is scriptOrModule until the returned scope is disposed: it is the active script or module (JsEngine.GetActiveScriptOrModule) of the code it runs, until code that has its own script or module runs (e.g. HostCallJobCallback restores the active script captured by HostMakeJobCallback, so that the code compiled by an eval called by a promise job resolves its imports against it). |
| EnterExecutionScope(JsExecutionLimits?) | Starts an execution scope: the calls made until the returned scope is disposed are one entry into JavaScript, and limits apply to them as a whole, in addition to the limits of JsEngineOptions (which apply to the scope as a whole as well: the calls in the scope do not restart them). It bounds a sequence of calls (e.g. a script and the jobs it enqueues: JsEngine.RunJobs runs each job in its own entry otherwise), or one call of an engine shared by several requests, without changing the options of the engine. The scope also makes the engine the engine of the current thread (JsEngine.Enter). A scope started while JavaScript runs (from a host function) adds its limits to the running entry until it is disposed. |
| EnterNestedJobQueue() | Makes the jobs enqueued from now on go to a new queue, which JsEngine.RunJobs runs, until the returned scope is disposed (e.g. the microtasks of a nested event loop). The jobs left in the nested queue then go to the outer queue. |
| GetActiveScriptOrModule() | GetActiveScriptOrModule(): the script or the module of the innermost running code that has one, or null. |
| GetCurrentLocation() | Gets the position of the running JavaScript code (the call of the running .NET callback), or null when no script runs. |
| GetRegisteredSymbol(string) | Gets the symbol of the global symbol registry of the engine whose key is key, creating it when needed: the symbol that Symbol.for(key) returns in all the realms of the engine. Another engine has its own registry, so the same key gives another symbol there. |
| IsArray(JsValue) | IsArray(value) (https://tc39.es/ecma262/#sec-isarray): true for arrays and proxies of arrays; throws for a revoked proxy. |
| Post(Action, JsRealm?) | Posts work to run on the thread of the engine. It can be called from any thread (e.g. the continuation of an I/O operation). The work runs from JsEngine.RunJobs as a task of the event loop: after the promise jobs already in the queue, in the order it was posted, and followed by the promise jobs it enqueues. A JsException thrown by the work goes to JsHost.ReportJobException; another exception comes out of JsEngine.RunJobs. A host whose JsHost.EnqueueGenericJob is overridden runs the work in its own event loop. |
| RunInRealm<T>(JsRealm, Func<T>) | Runs action with realm as the current realm (the realm of the objects created by the built-ins and the API). |
| RunJobs() | Runs the jobs until the queue is empty: the promise jobs first (in the order they were enqueued), then the generic jobs and the timeout jobs whose delay has elapsed, each followed by the promise jobs it enqueued. The timeout jobs whose delay has not elapsed stay in the queue. |
| RunUntilSettledAsync(JsValue, CancellationToken) | Runs the event loop of the engine until the promise settles: runs the jobs (JsEngine.RunJobs), and waits for posted work and timeout jobs (JsEngine.WaitForJobsAsync) while the promise is pending. The engine is free between two runs of the jobs: the work of the host (e.g. the continuations of its tasks) reaches it with JsEngine.Post. |
| SameValue(JsValue, JsValue) | SameValue(x, y) (https://tc39.es/ecma262/#sec-samevalue). |
| ToBigInt(JsValue) | ToBigInt(value) (https://tc39.es/ecma262/#sec-tobigint). |
| ToBoolean(JsValue) | ToBoolean(value) (https://tc39.es/ecma262/#sec-toboolean). |
| ToDotNet(JsValue) | Converts a JavaScript value to a .NET value: undefined and null are null; a boolean, a number, a string and a BigInt are a Boolean, a Double, a String and a BigInteger; a Date is a DateTimeOffset (null for an invalid date); an array is a List<T> of the converted elements; another object is a Dictionary<TKey, TValue> of its own enumerable properties whose key is a string (read with [[Get]], so the getters run). |
| ToDotNet<T>(JsValue) | Converts a JavaScript value to a .NET value of type T:
Boolean. |
| ToNumber(JsValue) | ToNumber(value) (https://tc39.es/ecma262/#sec-tonumber); it may run code (valueOf). |
| ToObject(JsValue) | ToObject(value) (https://tc39.es/ecma262/#sec-toobject): a TypeError for undefined and null. |
| ToPropertyKey(JsValue) | ToPropertyKey(value) (https://tc39.es/ecma262/#sec-topropertykey); it may run code. |
| ToString(JsValue) | ToString(value) (https://tc39.es/ecma262/#sec-tostring); it may run code, and throws a TypeError for a symbol. |
| ToTask(JsValue) | Gets a task that completes when the promise settles: its result is the value of a fulfilled promise, and the JsException of the rejection reason for a rejected promise. A value that is not a promise is resolved as Promise.resolve does. The promise settles while the engine runs its jobs (JsEngine.RunJobs, or JsEngine.RunUntilSettledAsync), and the continuations of the task run on the thread pool, after the job. The task is canceled when the engine is disposed first. |
| WaitForJobsAsync(CancellationToken) | Waits until a job is ready to run: a promise job, work posted by JsEngine.Post, a generic job, or a timeout job whose delay has elapsed. It completes at once when one is already queued. A host calls it between two calls to JsEngine.RunJobs, while the engine does not run, to implement its event loop. |
Call(JsValue, JsValue, ReadOnlySpan<JsValue>)
JsEngine.Public.csCall(F, V, argumentsList) (https://tc39.es/ecma262/#sec-call).
public JsValue Call(JsValue function, JsValue thisValue, params scoped ReadOnlySpan<JsValue> arguments)Parameters
functionJsValuethisValueJsValueargumentsReadOnlySpan<JsValue>
Returns
Exceptions
JsException- The value is not callable (a TypeError), or the function threw an exception.
InvalidOperationException- The function, the this value or an argument belongs to another engine.
CaptureStackTrace()
JsEngine.Public.csCheckInterrupt()
JsEngine.Execution.csThrows a JsTerminationException when the running script must stop: the execution is canceled (JsEngineOptions.CancellationToken), a limit of JsEngineOptions or of an execution scope (JsEngine.EnterExecutionScope) is exceeded, or the running entry was already terminated. The host calls it periodically while it runs code on behalf of the script (e.g. WebAssembly code); the engine checks the limits itself while JavaScript code and the built-in functions run.
public void CheckInterrupt()Exceptions
JsTerminationException- The script must stop.
Construct(JsValue, ReadOnlySpan<JsValue>, JsValue)
JsEngine.Public.csConstruct(F, argumentsList, newTarget) (https://tc39.es/ecma262/#sec-construct); newTarget is the constructor when it is undefined.
public JsValue Construct(JsValue constructor, ReadOnlySpan<JsValue> arguments, JsValue newTarget = default)Parameters
constructorJsValueargumentsReadOnlySpan<JsValue>newTargetJsValue
Returns
Exceptions
JsException- The value is not a constructor (a TypeError), or the constructor threw an exception.
InvalidOperationException- The constructor, the new target or an argument belongs to another engine.
CreateRealm()
JsEngine.csDispose()
JsEngine.csReleases the resources of the engine: the work posted afterwards does not run (JsEngine.Post), and the pending tasks of JsEngine.ToTask are canceled.
public void Dispose()EnqueueJob(Action, JsRealm?)
JsEngine.Public.csEnqueues a job in the promise job queue (a microtask): it runs from JsEngine.RunJobs, after the jobs already in the queue.
Enter()
JsEngine.csMakes the engine the engine of the current thread until the returned scope is disposed. The methods of the objects (JsObject.GetProperty...) need it when they are not called by the engine (a callback).
public JsEngineScope Enter()Returns
Exceptions
InvalidOperationException- Another thread is using the engine.
Remarks
An engine is used by one thread at a time: the thread that enters it owns it until it disposes its outermost scope. The owning thread can enter the engine again (nested scopes, callbacks); another thread gets an InvalidOperationException instead of corrupting the state of the engine.
EnterActiveScriptOrModule(JsScriptOrModule?)
JsEngine.Execution.csPushes an execution context whose ScriptOrModule is scriptOrModule until the returned scope is disposed: it is the active script or module (JsEngine.GetActiveScriptOrModule) of the code it runs, until code that has its own script or module runs (e.g. HostCallJobCallback restores the active script captured by HostMakeJobCallback, so that the code compiled by an eval called by a promise job resolves its imports against it).
public JsScriptContextScope EnterActiveScriptOrModule(JsScriptOrModule? scriptOrModule)Parameters
scriptOrModuleJsScriptOrModule?- The script or module, or null for an execution context without script or module.
Returns
EnterExecutionScope(JsExecutionLimits?)
JsEngine.Execution.csStarts an execution scope: the calls made until the returned scope is disposed are one entry into JavaScript, and limits apply to them as a whole, in addition to the limits of JsEngineOptions (which apply to the scope as a whole as well: the calls in the scope do not restart them). It bounds a sequence of calls (e.g. a script and the jobs it enqueues: JsEngine.RunJobs runs each job in its own entry otherwise), or one call of an engine shared by several requests, without changing the options of the engine. The scope also makes the engine the engine of the current thread (JsEngine.Enter). A scope started while JavaScript runs (from a host function) adds its limits to the running entry until it is disposed.
public JsExecutionScope EnterExecutionScope(JsExecutionLimits? limits = null)Parameters
limitsJsExecutionLimits?- The limits of the scope, or null for the limits of the options only.
Returns
Exceptions
JsTerminationException- The execution is canceled, or the running entry was terminated.
EnterNestedJobQueue()
JsEngine.Public.csMakes the jobs enqueued from now on go to a new queue, which JsEngine.RunJobs runs, until the returned scope is disposed (e.g. the microtasks of a nested event loop). The jobs left in the nested queue then go to the outer queue.
public IDisposable EnterNestedJobQueue()Returns
GetActiveScriptOrModule()
JsEngine.Public.csGetActiveScriptOrModule(): the script or the module of the innermost running code that has one, or null.
public JsScriptOrModule? GetActiveScriptOrModule()Returns
GetCurrentLocation()
JsEngine.Public.csGets the position of the running JavaScript code (the call of the running .NET callback), or null when no script runs.
public JsSourceLocation? GetCurrentLocation()Returns
GetRegisteredSymbol(string)
JsEngine.Symbols.csGets the symbol of the global symbol registry of the engine whose key is key, creating it when needed: the symbol that Symbol.for(key) returns in all the realms of the engine. Another engine has its own registry, so the same key gives another symbol there.
IsArray(JsValue)
JsEngine.Public.csPost(Action, JsRealm?)
JsEngine.Async.csPosts work to run on the thread of the engine. It can be called from any thread (e.g. the continuation of an I/O operation). The work runs from JsEngine.RunJobs as a task of the event loop: after the promise jobs already in the queue, in the order it was posted, and followed by the promise jobs it enqueues. A JsException thrown by the work goes to JsHost.ReportJobException; another exception comes out of JsEngine.RunJobs. A host whose JsHost.EnqueueGenericJob is overridden runs the work in its own event loop.
RunInRealm<T>(JsRealm, Func<T>)
JsEngine.Public.csRunJobs()
JsEngine.Jobs.csRuns the jobs until the queue is empty: the promise jobs first (in the order they were enqueued), then the generic jobs and the timeout jobs whose delay has elapsed, each followed by the promise jobs it enqueued. The timeout jobs whose delay has not elapsed stay in the queue.
public void RunJobs()Exceptions
JsException- A job threw an exception, and the host does not handle the job errors (the other jobs stay in the queue).
JsTerminationException- A job was terminated, or the execution is canceled (the other jobs stay in the queue).
Remarks
Each job is an entry into JavaScript: the limits of JsEngineOptions apply to each job, not to the whole drain, so jobs that keep enqueuing jobs can run forever. Run the jobs in an execution scope (JsEngine.EnterExecutionScope) to bound the drain as a whole: the jobs are then part of the entry of the scope. The jobs do not run once the execution is canceled. Once the queue is empty, it raises JsEngine.UnhandledRejection for the promises still rejected without a handler.
RunUntilSettledAsync(JsValue, CancellationToken)
JsEngine.Async.csRuns the event loop of the engine until the promise settles: runs the jobs (JsEngine.RunJobs), and waits for posted work and timeout jobs (JsEngine.WaitForJobsAsync) while the promise is pending. The engine is free between two runs of the jobs: the work of the host (e.g. the continuations of its tasks) reaches it with JsEngine.Post.
net10.0
public Task<JsValue> RunUntilSettledAsync(JsValue promise, CancellationToken cancellationToken = default)net11.0
public Task<JsValue> RunUntilSettledAsync(JsValue promise, CancellationToken cancellationToken = default)Parameters
promiseJsValuecancellationTokenCancellationToken
Returns
Task<JsValue> The value of the fulfilled promise.
Exceptions
JsException- The promise is rejected, or a job threw an exception that the host does not handle.
ObjectDisposedException- The engine is disposed.
OperationCanceledExceptioncancellationTokenis canceled.
SameValue(JsValue, JsValue)
JsEngine.Public.csToBigInt(JsValue)
JsEngine.Public.csToBigInt(value) (https://tc39.es/ecma262/#sec-tobigint).
public BigInteger ToBigInt(JsValue value)ToBoolean(JsValue)
JsEngine.Public.csToDotNet overloads
ToDotNet(JsValue)
JsMarshalling.csConverts a JavaScript value to a .NET value: undefined and null are null; a boolean, a number, a string and a BigInt are a Boolean, a Double, a String and a BigInteger; a Date is a DateTimeOffset (null for an invalid date); an array is a List<T> of the converted elements; another object is a Dictionary<TKey, TValue> of its own enumerable properties whose key is a string (read with [[Get]], so the getters run).
Parameters
valueJsValue
Returns
Exceptions
NotSupportedException- The value is, or contains, a symbol or a function.
InvalidOperationException- The value contains a cycle.
ToDotNet<T>(JsValue)
JsMarshalling.csConverts a JavaScript value to a .NET value of type T:
JsValue: the value;JsObject: the object, or null for undefined and null;String: ToString (null for undefined and null);Boolean: ToBoolean;BigInteger: ToBigInt;DoubleandSingle: ToNumber; the integer types: ToNumber, which must be an integer in the range of the type;DateTimeOffsetandDateTime(UTC): a valid Date;Object:JsEngine.ToDotNet;- a nullable value type: null for undefined and null, the conversion of the underlying type otherwise.
undefined and null cannot be converted to a value type that is not nullable, except Boolean.
public T ToDotNet<T>(JsValue value)Type parameters
T
Parameters
valueJsValue
Returns
T
Exceptions
JsException- The value cannot be converted (a TypeError or a RangeError), or a conversion of JavaScript threw an exception.
NotSupportedExceptionTis not one of the supported types.
ToNumber(JsValue)
JsEngine.Public.csToObject(JsValue)
JsEngine.Public.csToPropertyKey(JsValue)
JsEngine.Public.csToPropertyKey(value) (https://tc39.es/ecma262/#sec-topropertykey); it may run code.
public JsPropertyKey ToPropertyKey(JsValue value)ToString(JsValue)
JsEngine.Public.csToTask(JsValue)
JsEngine.Async.csGets a task that completes when the promise settles: its result is the value of a fulfilled promise, and the JsException of the rejection reason for a rejected promise. A value that is not a promise is resolved as Promise.resolve does. The promise settles while the engine runs its jobs (JsEngine.RunJobs, or JsEngine.RunUntilSettledAsync), and the continuations of the task run on the thread pool, after the job. The task is canceled when the engine is disposed first.
Parameters
promiseJsValue
Returns
Exceptions
InvalidOperationException- The promise belongs to another engine, or the engine has no realm to resolve a value that is not a promise.
WaitForJobsAsync(CancellationToken)
JsEngine.Async.csWaits until a job is ready to run: a promise job, work posted by JsEngine.Post, a generic job, or a timeout job whose delay has elapsed. It completes at once when one is already queued. A host calls it between two calls to JsEngine.RunJobs, while the engine does not run, to implement its event loop.
net10.0
public Task WaitForJobsAsync(CancellationToken cancellationToken = default)net11.0
public Task WaitForJobsAsync(CancellationToken cancellationToken = default)Parameters
cancellationTokenCancellationToken
Returns
Exceptions
ObjectDisposedException- The engine is disposed.
OperationCanceledExceptioncancellationTokenis canceled.
Events
| Name | Description |
|---|---|
| RejectionHandled | Occurs when a handler is attached to a promise that JsEngine.UnhandledRejection reported. |
| UnhandledRejection | Occurs when a promise is rejected and has no handler at the end of JsEngine.RunJobs (once the job queue is empty: a handler attached by a job of the same JsEngine.RunJobs call, or by the script before the call, prevents it). It is raised on the thread of the engine. A promise rejected by a script that runs without a call to JsEngine.RunJobs is reported by the next call. |
RejectionHandled
Occurs when a handler is attached to a promise that JsEngine.UnhandledRejection reported.
public event EventHandler<JsPromiseRejectionEventArgs>? RejectionHandledUnhandledRejection
Occurs when a promise is rejected and has no handler at the end of JsEngine.RunJobs (once the job queue is empty: a handler attached by a job of the same JsEngine.RunJobs call, or by the script before the call, prevents it). It is raised on the thread of the engine. A promise rejected by a script that runs without a call to JsEngine.RunJobs is reported by the next call.
public event EventHandler<JsPromiseRejectionEventArgs>? UnhandledRejection