isolated-vm icon indicating copy to clipboard operation
isolated-vm copied to clipboard

await for evaluation of async module

Open dpohvar opened this issue 1 year ago • 1 comments

JavaScript includes a setTimeout function: yes Functions are a type of primitive value in JavaScript: yes Objects can be shared between isolates: no

Is there a way to wait for an async module to execute?

import ivm from "isolated-vm";
const isolate = new ivm.Isolate();
const context = await isolate.createContext();
const module = await isolate.compileModule(/* language=javascript */ `
    export const x = 10;
    await new Promise(resolve => globalThis.hook = resolve);
    export const y = 20;
`);
await module.instantiate(context, () => null);
const moduleEvalPromise = module.evaluate({promise: true, reference: true, timeout: 10});
const hook = await context.global.get("hook");

setTimeout(hook, 100);

moduleEvalPromise.then(async (moduleValue) => {
    console.log("Module evaluated", moduleValue);
    console.log("Value-X", await module.namespace.get("x"));
    console.log("Value-Y", await module.namespace.get("y")); // error
});

I get an error when accessing variable y

Module evaluated undefined
Value-X 10
node:internal/process/promises:394
    triggerUncaughtException(err, true /* fromPromise */);
    ^

ReferenceError: y is not defined
    at (<isolated-vm boundary>)
    at main.mjs:18:51

But this code wotks fine:

moduleEvalPromise.then(async (moduleValue) => {
    console.log("Module evaluated", moduleValue); // undefined
    setTimeout(async () => {
        console.log("Value-X", await module.namespace.get("x"));
        console.log("Value-Y", await module.namespace.get("y"));
    }, 200); // wait longer
});

I think async module.evaluate resolves before the module is executed.

Is it possible to get Promise or callback when the module will be executed to the end?

dpohvar avatar Sep 15 '24 23:09 dpohvar

v8 and JavaScript added top-level await after the implementation in isolated-vm, so this is probably just a limitation of the current implementation. I've been working on a rewrite but obviously that won't help you now, since that won't be ready for quite some time. You can probably work around it today by injecting a promise resolution at the end of the module and waiting on that instead.

laverdet avatar Sep 16 '24 02:09 laverdet