microsoft / ClearScript

A library for adding scripting to .NET applications. Supports V8 (Windows, Linux, macOS) and JScript/VBScript (Windows).
https://microsoft.github.io/ClearScript/
MIT License
1.74k stars 148 forks source link

ScriptObject, how to know if this is an async function? #425

Closed CrosRoad95 closed 1 year ago

CrosRoad95 commented 1 year ago

as in title, how can i check if scriptobject is awaitable? maybe i just care to much?

but if i make scriptObject non async and i'm using "ToAsync" to await it, it throws exception

ClearScriptLib commented 1 year ago

Hi @CrosRoad95,

as in title

The title refers to determining whether an object is an async function. You can do something simple, like this:

private static bool IsAsyncFunc(dynamic obj) => obj.constructor.name == "AsyncFunction";

That's a bit fragile, though. A more robust approach is to use instanceof. Oddly, JavaScript doesn't expose AsyncFunction as a global property, but it's easy to find:

dynamic isAsyncFunc = engine.Evaluate("const ctor = (async() => {}).constructor; x => x instanceof ctor");
Console.WriteLine(isAsyncFunc(engine.Evaluate("async() => {}")));  // output: "True"
Console.WriteLine(isAsyncFunc(engine.Evaluate("() => {}")));       // output: "False"

how can i check if scriptobject is awaitable?

That's a different question. Async functions aren't awaitable. They return promises, which are awaitable, but only in async JavaScript code. However, you can await a promise in .NET code by converting it to a task:

engine.AddHostType(typeof(Console));
engine.Execute("async function foo() { Console.WriteLine('Hello!'); }");
object promise = engine.Script.foo();
await promise.ToTask();

You can also use an engine flag to make this conversion automatic:

using (var engine = new V8ScriptEngine(V8ScriptEngineFlags.EnableTaskPromiseConversion)) {
    engine.AddHostType(typeof(Console));
    engine.Execute("async function foo() { Console.WriteLine('Hello!'); }");
    await engine.Script.foo();
}

Good luck!

ClearScriptLib commented 1 year ago

Please reopen this issue if you have additional questions about this topic. Thank you!