laverdet / isolated-vm

Secure & isolated JS environments for nodejs
ISC License
2.19k stars 154 forks source link

evalSync doesn't wait for the async code inside context to complete #385

Closed RAJAGOPALAN-GANGADHARAN closed 1 year ago

RAJAGOPALAN-GANGADHARAN commented 1 year ago

Hi @laverdet , I'm trying to pass some async methods to the context. The method would just return an array or object which would then be used in the context to do some operations. Is there a better way to do this?

Here is what I have so far:

test('Test3', ()=>{
        console.log("Test 3")
        const isolate = new ivm.Isolate();
        const context = isolate.createContextSync();
        const sandbox = context.global;
        sandbox.setSync('log', function(...args: any[]) {
            console.log(...args);
        })
        sandbox.setSync(
            'tester',
            new ivm.Reference(async function () {
                const res = await axios.get('https://www.google.com');
                const v = res.data;
                console.log(v); 
                return new ivm.ExternalCopy(v).copyInto({release: true});
            })
        )

        const res = context.evalSync(`
        const result = tester.applySync();

        log(result);
        `)
        console.log(res);
    })

When this test is executed I can see the axios response getting printed because of the console.log statement inside the setSync. This prompts jest to throw error stating that logs attempted to print after end of test.

What is the best way to achieve this transfer of function but the execution should happen outside the context, the inside will be more interested in result.

Please take a look and help me out, much appreciated. Thanks!

RAJAGOPALAN-GANGADHARAN commented 1 year ago

Looks like the applySync doesn't wait for the reference function to return back the value. Could you help me out how to make result wait for the response from "tester" function. Thanks!

RAJAGOPALAN-GANGADHARAN commented 1 year ago

I'm unable to use applySyncPromise as it throws "Error: This function may not be called from the default thread"

laverdet commented 1 year ago

The Sync* family of functions use the same thread. If you want to use applySyncPromise then you need to enter the isolate via an async function. So context.evalSync(...) would be await context.eval(...).

RAJAGOPALAN-GANGADHARAN commented 1 year ago

Thanks for your input @laverdet.