Browse Source

child_process: fix deoptimizing use of arguments

Removed or fixed use of arguments in execFile(),
normalizeExecArgs(), and normalizeSpawnArguments().

Refs: https://github.com/nodejs/node/issues/10323
Refs: https://bugs.chromium.org/p/v8/issues/detail?id=6010

Backport-Of: https://github.com/nodejs/node/pull/11535
PR-URL: https://github.com/nodejs/node/pull/11748
Reviewed-By: James M Snell <jasnell@gmail.com>
v7.x
Vse Mozhet Byt 8 years ago
committed by James M Snell
parent
commit
5b1d61ce09
  1. 146
      benchmark/child_process/child-process-params.js
  2. 32
      lib/child_process.js

146
benchmark/child_process/child-process-params.js

@ -0,0 +1,146 @@
'use strict';
const common = require('../common.js');
const cp = require('child_process');
const command = 'echo';
const args = ['hello'];
const options = {};
const cb = () => {};
const configs = {
n: [1e3],
methodName: [
'exec', 'execSync',
'execFile', 'execFileSync',
'spawn', 'spawnSync',
],
params: [1, 2, 3, 4],
};
const bench = common.createBenchmark(main, configs);
function main(conf) {
const n = +conf.n;
const methodName = conf.methodName;
const params = +conf.params;
const method = cp[methodName];
switch (methodName) {
case 'exec':
switch (params) {
case 1:
bench.start();
for (let i = 0; i < n; i++) method(command).kill();
bench.end(n);
break;
case 2:
bench.start();
for (let i = 0; i < n; i++) method(command, options).kill();
bench.end(n);
break;
case 3:
bench.start();
for (let i = 0; i < n; i++) method(command, options, cb).kill();
bench.end(n);
break;
}
break;
case 'execSync':
switch (params) {
case 1:
bench.start();
for (let i = 0; i < n; i++) method(command);
bench.end(n);
break;
case 2:
bench.start();
for (let i = 0; i < n; i++) method(command, options);
bench.end(n);
break;
}
break;
case 'execFile':
switch (params) {
case 1:
bench.start();
for (let i = 0; i < n; i++) method(command).kill();
bench.end(n);
break;
case 2:
bench.start();
for (let i = 0; i < n; i++) method(command, args).kill();
bench.end(n);
break;
case 3:
bench.start();
for (let i = 0; i < n; i++) method(command, args, options).kill();
bench.end(n);
break;
case 4:
bench.start();
for (let i = 0; i < n; i++) method(command, args, options, cb).kill();
bench.end(n);
break;
}
break;
case 'execFileSync':
switch (params) {
case 1:
bench.start();
for (let i = 0; i < n; i++) method(command);
bench.end(n);
break;
case 2:
bench.start();
for (let i = 0; i < n; i++) method(command, args);
bench.end(n);
break;
case 3:
bench.start();
for (let i = 0; i < n; i++) method(command, args, options);
bench.end(n);
break;
}
break;
case 'spawn':
switch (params) {
case 1:
bench.start();
for (let i = 0; i < n; i++) method(command).kill();
bench.end(n);
break;
case 2:
bench.start();
for (let i = 0; i < n; i++) method(command, args).kill();
bench.end(n);
break;
case 3:
bench.start();
for (let i = 0; i < n; i++) method(command, args, options).kill();
bench.end(n);
break;
}
break;
case 'spawnSync':
switch (params) {
case 1:
bench.start();
for (let i = 0; i < n; i++) method(command);
bench.end(n);
break;
case 2:
bench.start();
for (let i = 0; i < n; i++) method(command, args);
bench.end(n);
break;
case 3:
bench.start();
for (let i = 0; i < n; i++) method(command, args, options);
bench.end(n);
break;
}
break;
}
}

32
lib/child_process.js

@ -79,16 +79,10 @@ exports._forkChild = function(fd) {
}; };
function normalizeExecArgs(command /*, options, callback*/) { function normalizeExecArgs(command, options, callback) {
let options; if (typeof options === 'function') {
let callback; callback = options;
if (typeof arguments[1] === 'function') {
options = undefined; options = undefined;
callback = arguments[1];
} else {
options = arguments[1];
callback = arguments[2];
} }
// Make a shallow copy so we don't clobber the user's options object. // Make a shallow copy so we don't clobber the user's options object.
@ -142,7 +136,7 @@ exports.execFile = function(file /*, args, options, callback*/) {
callback = arguments[pos++]; callback = arguments[pos++];
} }
if (!callback && arguments[pos] != null) { if (!callback && pos < arguments.length && arguments[pos] != null) {
throw new TypeError('Incorrect value of args option'); throw new TypeError('Incorrect value of args option');
} }
@ -175,6 +169,8 @@ exports.execFile = function(file /*, args, options, callback*/) {
var ex = null; var ex = null;
var cmd = file;
function exithandler(code, signal) { function exithandler(code, signal) {
if (exited) return; if (exited) return;
exited = true; exited = true;
@ -202,7 +198,6 @@ exports.execFile = function(file /*, args, options, callback*/) {
return; return;
} }
var cmd = file;
if (args.length !== 0) if (args.length !== 0)
cmd += ' ' + args.join(' '); cmd += ' ' + args.join(' ');
@ -311,18 +306,15 @@ function _convertCustomFds(options) {
} }
} }
function normalizeSpawnArguments(file /*, args, options*/) { function normalizeSpawnArguments(file, args, options) {
var args, options; if (Array.isArray(args)) {
args = args.slice(0);
if (Array.isArray(arguments[1])) { } else if (args !== undefined &&
args = arguments[1].slice(0); (args === null || typeof args !== 'object')) {
options = arguments[2];
} else if (arguments[1] !== undefined &&
(arguments[1] === null || typeof arguments[1] !== 'object')) {
throw new TypeError('Incorrect value of args option'); throw new TypeError('Incorrect value of args option');
} else { } else {
options = args;
args = []; args = [];
options = arguments[1];
} }
if (options === undefined) if (options === undefined)

Loading…
Cancel
Save