microsoft / Chakra-Samples

Repository for Chakra JavaScript engine related samples.
MIT License
216 stars 84 forks source link

Need help with C# Native.JsRunScript and async #90

Closed kefniark closed 4 years ago

kefniark commented 4 years ago

Description

I'm trying to embed logic code in .ts (until now designed for electron), into a C# application. My first tests where successful and chakra is quite good at parsing even big piece of minified JS.

But starting the implementation, I run into an issue with some code generated by webpack. Doing more test I realize it was simply the await keyword which doesn't work at all with my current usage.

I'm probably doing something stupid or I really misunderstood the API.

Code

JS

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

host.echo("root");

async function init() {
    host.echo("before import");
    await timeout(5);
    host.echo("after import");
}
(async () => await init())();

C#

    void Start()
    {
        Debug.Log("Start !");
        InitChakra();
        Debug.Log("JS Code " + code);
        Debug.Log("Evaluate: " + Evaluate(code.text));
    }

    public void InitChakra()
    {
        Native.ThrowIfError(Native.JsCreateRuntime(JavaScriptRuntimeAttributes.DisableBackgroundWork, null, out runtime));
        Native.ThrowIfError(Native.JsEnableRuntimeExecution(runtime));
        // Create an execution context. 
        Native.ThrowIfError(Native.JsCreateContext(runtime, out context));

        // Now set the execution context as being the current one on this thread.
        Native.ThrowIfError(Native.JsSetCurrentContext(context));
        {
            JavaScriptValue v;
            Native.ThrowIfError(Native.JsGetGlobalObject(out v));
            Global = JSValue.Make(v);

            JavaScriptValue hostObject = JavaScriptValue.CreateObject();
            JavaScriptPropertyId hostPropertyId = JavaScriptPropertyId.FromString("host");
            v.SetProperty(hostPropertyId, hostObject, true);

            DefineHostCallback(hostObject, "echo", echoDelegate, IntPtr.Zero);
        }
    }

    public JSValue Evaluate(string js) {
        return Evaluate(js, "Evaluate");
    }

    public JSValue Evaluate(string js, string sourceName) {
        JavaScriptValue result;
        var err = Native.JsRunScript(js, currentSourceContext++, sourceName, out result);
        if (err == JavaScriptErrorCode.ScriptException || err == JavaScriptErrorCode.ScriptCompile || err == JavaScriptErrorCode.InExceptionState) {
            //ThrowError(err, sourceName);
        } else {
            Native.ThrowIfError(err);
        }
        return JSValue.Make(result);
    }

Result

image

Basically my .Evaluate() seems to stop execution at the first await occurrence and return an object promise.

I did lot of test but I couldn't find a way to resume execution or to tick the runtime. Does anyone know how to deal with this kind of issue?

In this case I dont even need the result, just the context to continue the execution.

P.S. the first issues were related to other async function, I just used setTimeout() here to have a simpler demo ^^