From 9e9df738cec2226bab596d08f4ba8cb5292ce79e Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 18 Dec 2018 03:15:57 +0100 Subject: [PATCH 1/3] lib: remove internal `util._extends()` usage This removes all internal calls to the deprecated `_extends()` function. It is slower than `Object.assign()` and the object spread notation since V8 6.8 and using the spread notation often also results in shorter code. --- lib/_http_agent.js | 8 +++----- lib/_http_client.js | 7 +++---- lib/_http_server.js | 2 +- lib/_tls_wrap.js | 18 ++++++++--------- lib/child_process.js | 35 ++++++++++++++++++---------------- lib/domain.js | 8 +++----- lib/fs.js | 18 ++++++++--------- lib/https.js | 11 ++++++----- lib/internal/cluster/child.js | 10 +++++----- lib/internal/cluster/master.js | 29 ++++++++++++---------------- lib/internal/cluster/utils.js | 4 +--- lib/internal/fs/utils.js | 2 +- lib/internal/repl.js | 7 ++++--- lib/internal/url.js | 11 ++++++----- lib/net.js | 2 +- lib/tty.js | 11 +++++------ lib/zlib.js | 3 +-- 17 files changed, 88 insertions(+), 98 deletions(-) diff --git a/lib/_http_agent.js b/lib/_http_agent.js index 050e6318f33b09..6d8d598ddc4ac2 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -48,7 +48,7 @@ function Agent(options) { this.defaultPort = 80; this.protocol = 'http:'; - this.options = util._extend({}, options); + this.options = { ...options }; // Don't confuse net and make it think that we're connecting to a pipe this.options.path = null; @@ -146,8 +146,7 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */, }; } - options = util._extend({}, options); - util._extend(options, this.options); + options = { ...options, ...this.options }; if (options.socketPath) options.path = options.socketPath; @@ -194,8 +193,7 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */, }; Agent.prototype.createSocket = function createSocket(req, options, cb) { - options = util._extend({}, options); - util._extend(options, this.options); + options = { ...options, ...this.options }; if (options.socketPath) options.path = options.socketPath; diff --git a/lib/_http_client.js b/lib/_http_client.js index 46605dce0c5fd0..95488bc5e7049d 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -21,7 +21,6 @@ 'use strict'; -const util = require('util'); const net = require('net'); const url = require('url'); const assert = require('assert').ok; @@ -93,11 +92,11 @@ function ClientRequest(input, options, cb) { if (typeof options === 'function') { cb = options; - options = null; + options = input || {}; + } else { + options = Object.assign(input || {}, options); } - options = util._extend(input || {}, options || {}); - var agent = options.agent; var defaultAgent = options._defaultAgent || Agent.globalAgent; if (agent === false) { diff --git a/lib/_http_server.js b/lib/_http_server.js index 6aad3584c21834..8db7018cc98aba 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -282,7 +282,7 @@ function Server(options, requestListener) { requestListener = options; options = {}; } else if (options == null || typeof options === 'object') { - options = util._extend({}, options); + options = { ...options }; } else { throw new ERR_INVALID_ARG_TYPE('options', 'object', options); } diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 1d6ccbb8a9cbaf..5b4e7872956f4e 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -1109,9 +1109,9 @@ function SNICallback(servername, callback) { // // function normalizeConnectArgs(listArgs) { - var args = net._normalizeArgs(listArgs); - var options = args[0]; - var cb = args[1]; + const args = net._normalizeArgs(listArgs); + const options = args[0]; + const cb = args[1]; // If args[0] was options, then normalize dealt with it. // If args[0] is port, or args[0], args[1] is host, port, we need to @@ -1119,12 +1119,12 @@ function normalizeConnectArgs(listArgs) { // the host/port/path args that it knows about, not the tls options. // This means that options.host overrides a host arg. if (listArgs[1] !== null && typeof listArgs[1] === 'object') { - util._extend(options, listArgs[1]); + Object.assign(options, listArgs[1]); } else if (listArgs[2] !== null && typeof listArgs[2] === 'object') { - util._extend(options, listArgs[2]); + Object.assign(options, listArgs[2]); } - return (cb) ? [options, cb] : [options]; + return cb ? [options, cb] : [options]; } function onConnectSecure() { @@ -1205,14 +1205,14 @@ exports.connect = function connect(...args) { 'certificate verification.'); } - var defaults = { + options = { rejectUnauthorized: !allowUnauthorized, ciphers: tls.DEFAULT_CIPHERS, checkServerIdentity: tls.checkServerIdentity, - minDHSize: 1024 + minDHSize: 1024, + ...options }; - options = util._extend(defaults, options || {}); if (!options.keepAlive) options.singleUse = true; diff --git a/lib/child_process.js b/lib/child_process.js index 222df8aed7e8fd..050731a01bae94 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -79,7 +79,7 @@ exports.fork = function fork(modulePath /* , args, options */) { throw new ERR_INVALID_ARG_VALUE(`arguments[${pos}]`, arguments[pos]); } - options = util._extend({}, arguments[pos++]); + options = { ...arguments[pos++] }; } // Prepare arguments for fork: @@ -176,20 +176,12 @@ Object.defineProperty(exports.exec, util.promisify.custom, { }); exports.execFile = function execFile(file /* , args, options, callback */) { - var args = []; - var callback; - var options = { - encoding: 'utf8', - timeout: 0, - maxBuffer: 200 * 1024, - killSignal: 'SIGTERM', - cwd: null, - env: null, - shell: false - }; + let args = []; + let callback; + let options; // Parse the optional positional parameters. - var pos = 1; + let pos = 1; if (pos < arguments.length && Array.isArray(arguments[pos])) { args = arguments[pos++]; } else if (pos < arguments.length && arguments[pos] == null) { @@ -197,7 +189,7 @@ exports.execFile = function execFile(file /* , args, options, callback */) { } if (pos < arguments.length && typeof arguments[pos] === 'object') { - util._extend(options, arguments[pos++]); + options = arguments[pos++]; } else if (pos < arguments.length && arguments[pos] == null) { pos++; } @@ -210,6 +202,17 @@ exports.execFile = function execFile(file /* , args, options, callback */) { throw new ERR_INVALID_ARG_VALUE('args', arguments[pos]); } + options = { + encoding: 'utf8', + timeout: 0, + maxBuffer: 200 * 1024, + killSignal: 'SIGTERM', + cwd: null, + env: null, + shell: false, + ...options + }; + // Validate the timeout, if present. validateTimeout(options.timeout); @@ -580,7 +583,7 @@ function spawnSync(/* file, args, options */) { options.stdio = _validateStdio(options.stdio || 'pipe', true).stdio; if (options.input) { - var stdin = options.stdio[0] = util._extend({}, options.stdio[0]); + var stdin = options.stdio[0] = { ...options.stdio[0] }; stdin.input = options.input; } @@ -588,7 +591,7 @@ function spawnSync(/* file, args, options */) { for (var i = 0; i < options.stdio.length; i++) { var input = options.stdio[i] && options.stdio[i].input; if (input != null) { - var pipe = options.stdio[i] = util._extend({}, options.stdio[i]); + var pipe = options.stdio[i] = { ...options.stdio[i] }; if (isArrayBufferView(input)) { pipe.input = input; } else if (typeof input === 'string') { diff --git a/lib/domain.js b/lib/domain.js index da116e60b3d02e..8d966833125f9d 100644 --- a/lib/domain.js +++ b/lib/domain.js @@ -343,11 +343,9 @@ Domain.prototype.run = function(fn) { function intercepted(_this, self, cb, fnargs) { if (fnargs[0] && fnargs[0] instanceof Error) { var er = fnargs[0]; - util._extend(er, { - domainBound: cb, - domainThrown: false, - domain: self - }); + er.domainBound = cb; + er.domainThrown = false; + er.domain = self; self.emit('error', er); return; } diff --git a/lib/fs.js b/lib/fs.js index f992166d54492b..a5fadf6aeb45ea 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -39,7 +39,6 @@ const { O_SYMLINK } = constants; -const { _extend } = require('util'); const pathModule = require('path'); const { isArrayBufferView } = require('internal/util/types'); const binding = internalBinding('fs'); @@ -1325,21 +1324,20 @@ function watchFile(filename, options, listener) { filename = pathModule.resolve(filename); let stat; - const defaults = { + if (options === null || typeof options !== 'object') { + listener = options; + options = null; + } + + options = { // Poll interval in milliseconds. 5007 is what libev used to use. It's // a little on the slow side but let's stick with it for now to keep // behavioral changes to a minimum. interval: 5007, - persistent: true + persistent: true, + ...options }; - if (options !== null && typeof options === 'object') { - options = _extend(defaults, options); - } else { - listener = options; - options = defaults; - } - if (typeof listener !== 'function') { throw new ERR_INVALID_ARG_TYPE('listener', 'Function', listener); } diff --git a/lib/https.js b/lib/https.js index 4a83853d078d9e..72744d70ed0599 100644 --- a/lib/https.js +++ b/lib/https.js @@ -46,7 +46,7 @@ function Server(opts, requestListener) { requestListener = opts; opts = undefined; } - opts = util._extend({}, opts); + opts = { ...opts }; if (!opts.ALPNProtocols) { // http/1.0 is not defined as Protocol IDs in IANA @@ -110,9 +110,10 @@ function createConnection(port, host, options) { const session = this._getSession(options._agentKey); if (session) { debug('reuse session for %j', options._agentKey); - options = util._extend({ - session: session - }, options); + options = { + session: session, + ...options + }; } } @@ -292,7 +293,7 @@ function request(...args) { } if (args[0] && typeof args[0] !== 'function') { - options = util._extend(options, args.shift()); + options = Object.assign(options, args.shift()); } options._defaultAgent = globalAgent; diff --git a/lib/internal/cluster/child.js b/lib/internal/cluster/child.js index 13a22b0186fc28..272b0d2bd95008 100644 --- a/lib/internal/cluster/child.js +++ b/lib/internal/cluster/child.js @@ -1,6 +1,5 @@ 'use strict'; const assert = require('assert'); -const util = require('util'); const path = require('path'); const EventEmitter = require('events'); const { owner_symbol } = require('internal/async_hooks').symbols; @@ -71,11 +70,12 @@ cluster._getServer = function(obj, options, cb) { indexes.set(indexesKey, index); - const message = util._extend({ + const message = { act: 'queryServer', index, - data: null - }, options); + data: null, + ...options + }; message.address = address; @@ -151,7 +151,7 @@ function rr(message, indexesKey, cb) { function getsockname(out) { if (key) - util._extend(out, message.sockname); + Object.assign(out, message.sockname); return 0; } diff --git a/lib/internal/cluster/master.js b/lib/internal/cluster/master.js index 60083c6393e781..932b68165418f4 100644 --- a/lib/internal/cluster/master.js +++ b/lib/internal/cluster/master.js @@ -1,7 +1,6 @@ 'use strict'; const assert = require('assert'); const { fork } = require('child_process'); -const util = require('util'); const path = require('path'); const EventEmitter = require('events'); const RoundRobinHandle = require('internal/cluster/round_robin_handle'); @@ -47,14 +46,14 @@ if (schedulingPolicy === undefined) { cluster.schedulingPolicy = schedulingPolicy; cluster.setupMaster = function(options) { - var settings = { + const settings = { args: process.argv.slice(2), exec: process.argv[1], execArgv: process.execArgv, - silent: false + silent: false, + ...cluster.settings, + ...options }; - util._extend(settings, cluster.settings); - util._extend(settings, options || {}); // Tell V8 to write profile data for each process to a separate file. // Without --logfile=v8-%p.log, everything ends up in a single, unusable @@ -101,15 +100,12 @@ function setupSettingsNT(settings) { } function createWorkerProcess(id, env) { - const workerEnv = util._extend({}, process.env); + const workerEnv = { ...process.env, ...env, NODE_UNIQUE_ID: `${id}` }; const execArgv = cluster.settings.execArgv.slice(); const debugArgRegex = /--inspect(?:-brk|-port)?|--debug-port/; const nodeOptions = process.env.NODE_OPTIONS ? process.env.NODE_OPTIONS : ''; - util._extend(workerEnv, env); - workerEnv.NODE_UNIQUE_ID = '' + id; - if (execArgv.some((arg) => arg.match(debugArgRegex)) || nodeOptions.match(debugArgRegex)) { let inspectPort; @@ -315,17 +311,16 @@ function queryServer(worker, message) { // Set custom server data handle.add(worker, (errno, reply, handle) => { - reply = util._extend({ - errno: errno, - key: key, - ack: message.seq, - data: handles.get(key).data - }, reply); - if (errno) handles.delete(key); // Gives other workers a chance to retry. - send(worker, reply, handle); + send(worker, { + errno: errno, + key: key, + ack: message.seq, + data: handles.get(key).data, + ...reply + }, handle); }); } diff --git a/lib/internal/cluster/utils.js b/lib/internal/cluster/utils.js index 3fc5e408b76a5a..f20206c842be96 100644 --- a/lib/internal/cluster/utils.js +++ b/lib/internal/cluster/utils.js @@ -1,5 +1,4 @@ 'use strict'; -const util = require('util'); module.exports = { sendHelper, @@ -14,12 +13,11 @@ function sendHelper(proc, message, handle, cb) { return false; // Mark message as internal. See INTERNAL_PREFIX in lib/child_process.js - message = util._extend({ cmd: 'NODE_CLUSTER' }, message); + message = { cmd: 'NODE_CLUSTER', ...message, seq }; if (typeof cb === 'function') callbacks.set(seq, cb); - message.seq = seq; seq += 1; return proc.send(message, handle); } diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 4db4fb536c0b6a..0062bd435530d0 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -171,7 +171,7 @@ function getOptions(options, defaultOptions) { } if (typeof options === 'string') { - defaultOptions = util._extend({}, defaultOptions); + defaultOptions = { ...defaultOptions }; defaultOptions.encoding = options; options = defaultOptions; } else if (typeof options !== 'object') { diff --git a/lib/internal/repl.js b/lib/internal/repl.js index 4c4e3c8cb4e275..e58752e76eb890 100644 --- a/lib/internal/repl.js +++ b/lib/internal/repl.js @@ -24,12 +24,13 @@ function createRepl(env, opts, cb) { cb = opts; opts = null; } - opts = util._extend({ + opts = { ignoreUndefined: false, terminal: process.stdout.isTTY, useGlobal: true, - breakEvalOnSigint: true - }, opts); + breakEvalOnSigint: true, + ...opts + }; if (parseInt(env.NODE_NO_READLINE)) { opts.terminal = false; diff --git a/lib/internal/url.js b/lib/internal/url.js index 13063cb8f2f5a6..45ed236511ac9a 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -193,7 +193,7 @@ class URLSearchParams { return ctx.stylize('[Object]', 'special'); var separator = ', '; - var innerOpts = util._extend({}, ctx); + var innerOpts = { ...ctx }; if (recurseTimes !== null) { innerOpts.depth = recurseTimes - 1; } @@ -382,12 +382,13 @@ Object.defineProperties(URL.prototype, { value: function format(options) { if (options && typeof options !== 'object') throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); - options = util._extend({ + options = { fragment: true, unicode: false, search: true, - auth: true - }, options); + auth: true, + ...options + }; const ctx = this[context]; var ret = ctx.scheme; if (ctx.host !== null) { @@ -1202,7 +1203,7 @@ defineIDLClass(URLSearchParamsIteratorPrototype, 'URLSearchParams Iterator', { if (typeof recurseTimes === 'number' && recurseTimes < 0) return ctx.stylize('[Object]', 'special'); - const innerOpts = util._extend({}, ctx); + const innerOpts = { ...ctx }; if (recurseTimes !== null) { innerOpts.depth = recurseTimes - 1; } diff --git a/lib/net.js b/lib/net.js index 011ccb6a534605..af939754a5df64 100644 --- a/lib/net.js +++ b/lib/net.js @@ -245,7 +245,7 @@ function Socket(options) { if (typeof options === 'number') options = { fd: options }; // Legacy interface. else - options = util._extend({}, options); + options = { ...options }; options.readable = options.readable || false; options.writable = options.writable || false; diff --git a/lib/tty.js b/lib/tty.js index 62945a78eb1f0f..6efaac6e43215f 100644 --- a/lib/tty.js +++ b/lib/tty.js @@ -21,7 +21,7 @@ 'use strict'; -const { inherits, _extend } = require('util'); +const { inherits } = require('util'); const net = require('net'); const { TTY, isTTY } = internalBinding('tty_wrap'); const errors = require('internal/errors'); @@ -47,14 +47,13 @@ function ReadStream(fd, options) { throw new ERR_TTY_INIT_FAILED(ctx); } - options = _extend({ + net.Socket.call(this, { highWaterMark: 0, readable: true, writable: false, - handle: tty - }, options); - - net.Socket.call(this, options); + handle: tty, + ...options + }); this.isRaw = false; this.isTTY = true; diff --git a/lib/zlib.js b/lib/zlib.js index 183ff7bfcf4b5c..3254466d92b16e 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -30,7 +30,6 @@ const { const Transform = require('_stream_transform'); const { deprecate, - _extend, types: { isAnyArrayBuffer, isArrayBufferView @@ -283,7 +282,7 @@ function Zlib(opts, mode) { } if (opts.encoding || opts.objectMode || opts.writableObjectMode) { - opts = _extend({}, opts); + opts = { ...opts }; opts.encoding = null; opts.objectMode = false; opts.writableObjectMode = false; From 969a316633aff7c79aa7ddfd83bfc73121610d67 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 18 Dec 2018 03:38:46 +0100 Subject: [PATCH 2/3] fixup --- lib/https.js | 2 +- lib/internal/cluster/master.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/https.js b/lib/https.js index 72744d70ed0599..e6c2ff702b1d40 100644 --- a/lib/https.js +++ b/lib/https.js @@ -111,7 +111,7 @@ function createConnection(port, host, options) { if (session) { debug('reuse session for %j', options._agentKey); options = { - session: session, + session, ...options }; } diff --git a/lib/internal/cluster/master.js b/lib/internal/cluster/master.js index 932b68165418f4..c4f8e2b0efa299 100644 --- a/lib/internal/cluster/master.js +++ b/lib/internal/cluster/master.js @@ -311,14 +311,16 @@ function queryServer(worker, message) { // Set custom server data handle.add(worker, (errno, reply, handle) => { + const { data } = handles.get(key); + if (errno) handles.delete(key); // Gives other workers a chance to retry. send(worker, { - errno: errno, - key: key, + errno, + key, ack: message.seq, - data: handles.get(key).data, + data, ...reply }, handle); }); From 064041d199604e78ab7d0670895954716d524cf5 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 18 Dec 2018 10:51:48 +0100 Subject: [PATCH 3/3] fiixup: remove obsolete assignment --- lib/https.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/https.js b/lib/https.js index e6c2ff702b1d40..90f561ab507395 100644 --- a/lib/https.js +++ b/lib/https.js @@ -293,7 +293,7 @@ function request(...args) { } if (args[0] && typeof args[0] !== 'function') { - options = Object.assign(options, args.shift()); + Object.assign(options, args.shift()); } options._defaultAgent = globalAgent;