Halt the promise chain or stop the runInNewContext returning promise chain

452 Views Asked by At

I am facing an issue with the vm while executing the code using runInNewContext.

The custom code can return a promise which might be nested and can have nested call stacks. The code looks like follow

 function executeInSandbox(code, sandbox){
  return Async((code, _sandbox) => {
    let fn = `"use strict";
              this.result = async(() => {
                  ${code}
              })();`;
    var script = new vm.Script(fn);
    return Await(
      script.runInNewContext(_sandbox, {
        displayErrors: true,
        timeout: 30000
      })
    );
  })(code, sandbox);
};
result = Await(executeInSandbox(code, sandbox))

Now the problem is I want to halt the processing of the promise if it takes more than 20seconds.

If the code is recursive and with nested promises, it get stacked and in 20Sec but now tries to execute the call stacks now which takes more than minutes and is not stoppable and at last, gives stack overflow issue.

I tried with following adding the Promise.race

let timeout = new Promise((resolve, reject) => {
let id = setTimeout(() => {
  clearTimeout(id);
  reject('Timed out in '+ 2000 + 'ms.')
}, 2000);
});
let fn = `"use strict";
        this.result = async(() => {
            ${code}
        })();`;
var script = new vm.Script(fn);
let codePromise = script.runInNewContext(_sandbox, {
displayErrors: true,
timeout: 30000
});
return Await(
Promise.race([
  codePromise,
  timeout
])
);
})(code, sandbox);

It kind of works as leaves the control out of the function but, the promise chain keeps executing.

Is there a way to halt the codePromise? or timeout in the Await ?

2

There are 2 best solutions below

0
On

You need to think of the 20 second timeout as a primary function of your code. All promises MUST either resolve or reject. If a function needs to timeout it must do so by either resolving or rejecting. Don't assume you can force this externally.

0
On

Solved using code injection via babel's transformFromAst for now.

Just throw error if execution time exceeds the specified timespan at the begining of each function declaration and function expression.