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 ?
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.