laverdet / isolated-vm

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

Bubble up errors #405

Closed devtronic closed 1 year ago

devtronic commented 1 year ago

Hi,

first of all: Thanks for this wonderful project!

In some cases I need to handle specific errors on the "host" (=the code that creates isolates). For this I've built error classes which extend error and have additionally a type field and other fields (not relevant for reproducing).

I faced the problem that isolated-vm doesn't bubble up the error as is. Minimal reproduction code:

class MyCustomError extends Error {
    public readonly type: string = 'custom-error';
    constructor(message?: string) {
        super(message);
    }
}

let isolate = new ivm.Isolate();
let context = isolate.createContextSync();
let jail = context.global;

try {
    jail.setSync('throwOnHost', new ivm.Callback(() => {
        throw new MyCustomError();
    }));
    const script = isolate.compileScriptSync('throwOnHost()');
    script.runSync(context);
} catch (e: any) {
    console.assert(e.type == 'custom-error', 'e.type == custom-error');
}

Output:

Assertion failed: e.type == custom-error

Is it possible to bubble up the exception or throw it directly on the host?

Thanks :-)

laverdet commented 1 year ago

It's not possible because the error is thrown through the child isolate. If you wrap throwOnHost() in a try/catch block you'll see that the caught error isn't an instance of the custom error, because the error is defined in another isolate. So what happens is the host throws the error, which is serialized into the isolate, which throws the error back out, and is serialized again. You can of course rig up your own callback shims which return any metadata you want.

devtronic commented 1 year ago

Thanks for the explanation. I added a global try-catch statement inside the isolate. The try block executes the code that may throw exceptions. The catch block writes the error in an error object which is serializable and accessible from the host. It's not perfect but it fits my needs.