laverdet / isolated-vm

Secure & isolated JS environments for nodejs
ISC License
2.15k stars 152 forks source link

Asynclocalstorage context is undefined when its been called second time #485

Closed rakeshar3796 closed 3 months ago

rakeshar3796 commented 3 months ago

Is Your Question Already Answered?

Personal Diagnostics

Please answer the following questions:

JavaScript includes a setTimeout function:

Functions are a type of primitive value in JavaScript:

Objects can be shared between isolates:

The Code

import ivm from "isolated-vm";
import { AsyncLocalStorage } from "node:async_hooks";

const ctx = new AsyncLocalStorage();

function main() {
  const code = `
    async function execute() {
      await __host_call();
      await __host_call();
      return { result: "success" };
    }
    execute();
  `;

  function delay() {
    return new Promise((resolve) => {
      setTimeout(resolve, 1000);
    });
  }

  async function callHost() {
    console.log("INSIDE HOST::", ctx.getStore());
    await delay();
  }

  async function runScriptInIsolate() {
    const isolate = new ivm.Isolate({ memoryLimit: 128 });
    const context = await isolate.createContext();

    context.evalClosureSync(
      `globalThis.__host_call = (...args) => $0.applySync(null, args, { arguments: {  copy:true }, result: { promise:true } })`,
      [new ivm.Reference(callHost)]
    );

    // Execute the script in the isolate
    const script = await isolate.compileScriptSync(code);
    const result = await script.runSync(context, {
      promise: true,
      reference: true,
    });

    // Return the result
    return result;
  }

  runScriptInIsolate()
    .then((result) => {
      console.log("Result:", result.copySync());
    })
    .catch((err) => {
      console.error("Error:", err);
    });
}

ctx.run({ credit: "isolated-vm is awesome" }, () => {
  main();
});

If i execute this code am able to see the context store value for the first time but on the second function call its returning undefined.

INSIDE HOST:: { credit: 'isolated-vm is awesome' }
INSIDE HOST:: undefined
Result: { result: 'success' }

But if i try to make changes in my function callHost and comment invoking delay function its working as expected, but in my case i need a function similar to this say fetch.

So can anyone shed some light on what went wrong here?

laverdet commented 3 months ago

AsyncLocalHooks is a nodejs API and cannot track async invocation graphs outside nodejs. You need to manually track these graphs, probably with this API https://nodejs.org/api/async_context.html#class-asyncresource

rakeshar3796 commented 3 months ago

Thanks @laverdet for the assistance, i fixed it using AsyncResource.bind(myFunction)