diff --git a/benchmark/vm/run-in-context.js b/benchmark/vm/run-in-context.js new file mode 100644 index 00000000000000..62ebe29146e705 --- /dev/null +++ b/benchmark/vm/run-in-context.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + n: [1], + breakOnSigint: [0, 1], + withSigintListener: [0, 1] +}); + +const vm = require('vm'); + +function main(conf) { + const n = +conf.n; + const options = conf.breakOnSigint ? {breakOnSigint: true} : {}; + const withSigintListener = !!conf.withSigintListener; + + process.removeAllListeners('SIGINT'); + if (withSigintListener) + process.on('SIGINT', () => {}); + + var i = 0; + + const contextifiedSandbox = vm.createContext(); + + common.v8ForceOptimization(vm.runInContext, + '0', contextifiedSandbox, options); + bench.start(); + for (; i < n; i++) + vm.runInContext('0', contextifiedSandbox, options); + bench.end(n); +} diff --git a/benchmark/vm/run-in-this-context.js b/benchmark/vm/run-in-this-context.js new file mode 100644 index 00000000000000..f66fd31a1a949e --- /dev/null +++ b/benchmark/vm/run-in-this-context.js @@ -0,0 +1,29 @@ +'use strict'; + +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + n: [1], + breakOnSigint: [0, 1], + withSigintListener: [0, 1] +}); + +const vm = require('vm'); + +function main(conf) { + const n = +conf.n; + const options = conf.breakOnSigint ? {breakOnSigint: true} : {}; + const withSigintListener = !!conf.withSigintListener; + + process.removeAllListeners('SIGINT'); + if (withSigintListener) + process.on('SIGINT', () => {}); + + var i = 0; + + common.v8ForceOptimization(vm.runInThisContext, '0', options); + bench.start(); + for (; i < n; i++) + vm.runInThisContext('0', options); + bench.end(n); +} diff --git a/lib/vm.js b/lib/vm.js index 4869d368807665..cf672fbbc14871 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -17,22 +17,17 @@ const realRunInThisContext = Script.prototype.runInThisContext; const realRunInContext = Script.prototype.runInContext; Script.prototype.runInThisContext = function(options) { - if (options && options.breakOnSigint) { - const realRunInThisContextScript = () => { - return realRunInThisContext.call(this, options); - }; - return sigintHandlersWrap(realRunInThisContextScript); + if (options && options.breakOnSigint && process._events.SIGINT) { + return sigintHandlersWrap(realRunInThisContext, this, [options]); } else { return realRunInThisContext.call(this, options); } }; Script.prototype.runInContext = function(contextifiedSandbox, options) { - if (options && options.breakOnSigint) { - const realRunInContextScript = () => { - return realRunInContext.call(this, contextifiedSandbox, options); - }; - return sigintHandlersWrap(realRunInContextScript); + if (options && options.breakOnSigint && process._events.SIGINT) { + return sigintHandlersWrap(realRunInContext, this, + [contextifiedSandbox, options]); } else { return realRunInContext.call(this, contextifiedSandbox, options); } @@ -83,19 +78,20 @@ exports.isContext = binding.isContext; // Remove all SIGINT listeners and re-attach them after the wrapped function // has executed, so that caught SIGINT are handled by the listeners again. -function sigintHandlersWrap(fn) { +function sigintHandlersWrap(fn, thisArg, argsArray) { // Using the internal list here to make sure `.once()` wrappers are used, // not the original ones. let sigintListeners = process._events.SIGINT; - if (!Array.isArray(sigintListeners)) - sigintListeners = sigintListeners ? [sigintListeners] : []; - else + + if (Array.isArray(sigintListeners)) sigintListeners = sigintListeners.slice(); + else + sigintListeners = [sigintListeners]; process.removeAllListeners('SIGINT'); try { - return fn(); + return fn.apply(thisArg, argsArray); } finally { // Add using the public methods so that the `newListener` handler of // process can re-attach the listeners.