From b55ab01b456645bcd7fce5c394f2722112080c6b Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 11 Jul 2017 09:23:38 -0400 Subject: [PATCH] lib: improve lazy requires * internal/errors - assert should already be in place when calling any of the message generating functions. * No lazy load if not necessary. * Replace function calls with `if`s. PR-URL: https://github.com/nodejs/node/pull/14167 Reviewed-By: Refael Ackermann Reviewed-By: Timothy Gu --- lib/dgram.js | 7 ++---- lib/internal/errors.js | 44 +++++++++++---------------------- lib/internal/process.js | 17 ++++--------- lib/internal/process/stdio.js | 18 +++----------- lib/internal/process/warning.js | 26 +++++++------------ lib/net.js | 17 ++++--------- lib/readline.js | 6 ++--- 7 files changed, 42 insertions(+), 93 deletions(-) diff --git a/lib/dgram.js b/lib/dgram.js index 3204ad87cd5cd9..0b2d9e5ebd4d7e 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -24,6 +24,7 @@ const assert = require('assert'); const errors = require('internal/errors'); const Buffer = require('buffer').Buffer; +const dns = require('dns'); const util = require('util'); const EventEmitter = require('events'); const setInitTriggerId = require('async_hooks').setInitTriggerId; @@ -39,17 +40,13 @@ const BIND_STATE_UNBOUND = 0; const BIND_STATE_BINDING = 1; const BIND_STATE_BOUND = 2; -// lazily loaded +// Lazily loaded var cluster = null; -var dns = null; const errnoException = util._errnoException; const exceptionWithHostPort = util._exceptionWithHostPort; function lookup(address, family, callback) { - if (!dns) - dns = require('dns'); - return dns.lookup(address, family, callback); } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 0ab125328f0b52..31c8fa945aeb64 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -9,19 +9,9 @@ const kCode = Symbol('code'); const messages = new Map(); -var util; -function lazyUtil() { - if (!util) - util = require('util'); - return util; -} - -var assert; -function lazyAssert() { - if (!assert) - assert = require('assert'); - return assert; -} +// Lazily loaded +var assert = null; +var util = null; function makeNodeError(Base) { return class NodeError extends Base { @@ -45,13 +35,14 @@ class AssertionError extends Error { if (typeof options !== 'object' || options === null) { throw new exports.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'object'); } - const util = lazyUtil(); - const message = options.message || - `${util.inspect(options.actual).slice(0, 128)} ` + - `${options.operator} ` + - util.inspect(options.expected).slice(0, 128); + if (options.message) { + super(options.message); + } else { + if (util === null) util = require('util'); + super(`${util.inspect(options.actual).slice(0, 128)} ` + + `${options.operator} ${util.inspect(options.expected).slice(0, 128)}`); + } - super(message); this.generatedMessage = !options.message; this.name = 'AssertionError [ERR_ASSERTION]'; this.code = 'ERR_ASSERTION'; @@ -63,15 +54,16 @@ class AssertionError extends Error { } function message(key, args) { - const assert = lazyAssert(); + if (assert === null) assert = require('assert'); assert.strictEqual(typeof key, 'string'); - const util = lazyUtil(); const msg = messages.get(key); assert(msg, `An invalid error message key was used: ${key}.`); - let fmt = util.format; + let fmt; if (typeof msg === 'function') { fmt = msg; } else { + if (util === null) util = require('util'); + fmt = util.format; if (args === undefined || args.length === 0) return msg; args.unshift(msg); @@ -123,7 +115,6 @@ E('ERR_INDEX_OUT_OF_RANGE', 'Index out of range'); E('ERR_INVALID_ARG_TYPE', invalidArgType); E('ERR_INVALID_ARRAY_LENGTH', (name, length, actual) => { - const assert = lazyAssert(); assert.strictEqual(typeof actual, 'number'); return `The "${name}" array must have a length of ${ length}. Received length ${actual}`; @@ -152,10 +143,7 @@ E('ERR_INVALID_THIS', 'Value of "this" must be of type %s'); E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple'); E('ERR_INVALID_URL', 'Invalid URL: %s'); E('ERR_INVALID_URL_SCHEME', - (expected) => { - lazyAssert(); - return `The URL must be ${oneOf(expected, 'scheme')}`; - }); + (expected) => `The URL must be ${oneOf(expected, 'scheme')}`); E('ERR_IPC_CHANNEL_CLOSED', 'Channel closed'); E('ERR_IPC_DISCONNECTED', 'IPC channel is already disconnected'); E('ERR_IPC_ONE_PIPE', 'Child process can have only one IPC pipe'); @@ -191,7 +179,6 @@ E('ERR_V8BREAKITERATOR', 'Full ICU data not installed. ' + // Add new errors from here... function invalidArgType(name, expected, actual) { - const assert = lazyAssert(); assert(name, 'name is required'); // determiner: 'must be' or 'must not be' @@ -223,7 +210,6 @@ function invalidArgType(name, expected, actual) { } function missingArgs(...args) { - const assert = lazyAssert(); assert(args.length > 0, 'At least one arg needs to be specified'); let msg = 'The '; const len = args.length; diff --git a/lib/internal/process.js b/lib/internal/process.js index bb9117ea09de50..31c502756682bc 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -1,14 +1,7 @@ 'use strict'; const errors = require('internal/errors'); -var _lazyConstants = null; - -function lazyConstants() { - if (!_lazyConstants) { - _lazyConstants = process.binding('constants').os.signals; - } - return _lazyConstants; -} +const constants = process.binding('constants').os.signals; const assert = process.assert = function(x, msg) { if (!x) throw new errors.Error('ERR_ASSERTION', msg || 'assertion error'); @@ -178,8 +171,8 @@ function setupKillAndExit() { err = process._kill(pid, 0); } else { sig = sig || 'SIGTERM'; - if (lazyConstants()[sig]) { - err = process._kill(pid, lazyConstants()[sig]); + if (constants[sig]) { + err = process._kill(pid, constants[sig]); } else { throw new errors.TypeError('ERR_UNKNOWN_SIGNAL', sig); } @@ -201,7 +194,7 @@ function setupSignalHandlers() { const signalWraps = {}; function isSignal(event) { - return typeof event === 'string' && lazyConstants()[event] !== undefined; + return typeof event === 'string' && constants[event] !== undefined; } // Detect presence of a listener for the special signal types @@ -215,7 +208,7 @@ function setupSignalHandlers() { wrap.onsignal = function() { process.emit(type); }; - const signum = lazyConstants()[type]; + const signum = constants[type]; const err = wrap.start(signum); if (err) { wrap.close(); diff --git a/lib/internal/process/stdio.js b/lib/internal/process/stdio.js index db544b15337142..45568ae631698b 100644 --- a/lib/internal/process/stdio.js +++ b/lib/internal/process/stdio.js @@ -1,14 +1,8 @@ 'use strict'; -exports.setup = setupStdio; - -var errors; +const errors = require('internal/errors'); -function lazyErrors() { - if (!errors) - errors = require('internal/errors'); - return errors; -} +exports.setup = setupStdio; function setupStdio() { var stdin; @@ -20,8 +14,7 @@ function setupStdio() { stdout = createWritableStdioStream(1); stdout.destroySoon = stdout.destroy; stdout._destroy = function(er, cb) { - // avoid errors if we already emitted - const errors = lazyErrors(); + // Avoid errors if we already emitted er = er || new errors.Error('ERR_STDOUT_CLOSE'); cb(er); }; @@ -36,8 +29,7 @@ function setupStdio() { stderr = createWritableStdioStream(2); stderr.destroySoon = stderr.destroy; stderr._destroy = function(er, cb) { - // avoid errors if we already emitted - const errors = lazyErrors(); + // Avoid errors if we already emitted er = er || new errors.Error('ERR_STDERR_CLOSE'); cb(er); }; @@ -95,7 +87,6 @@ function setupStdio() { default: // Probably an error on in uv_guess_handle() - const errors = lazyErrors(); throw new errors.Error('ERR_UNKNOWN_STDIN_TYPE'); } @@ -180,7 +171,6 @@ function createWritableStdioStream(fd) { default: // Probably an error on in uv_guess_handle() - const errors = lazyErrors(); throw new errors.Error('ERR_UNKNOWN_STREAM_TYPE'); } diff --git a/lib/internal/process/warning.js b/lib/internal/process/warning.js index 3208fb098d0a97..67a3113f2330f4 100644 --- a/lib/internal/process/warning.js +++ b/lib/internal/process/warning.js @@ -2,26 +2,16 @@ const config = process.binding('config'); const prefix = `(${process.release.name}:${process.pid}) `; +const errors = require('internal/errors'); exports.setup = setupProcessWarnings; -var errors; -var fs; var cachedFd; var acquiringFd = false; function nop() {} -function lazyErrors() { - if (!errors) - errors = require('internal/errors'); - return errors; -} - -function lazyFs() { - if (!fs) - fs = require('fs'); - return fs; -} +// Lazily loaded +var fs = null; function writeOut(message) { if (console && typeof console.error === 'function') @@ -31,7 +21,8 @@ function writeOut(message) { function onClose(fd) { return function() { - lazyFs().close(fd, nop); + if (fs === null) fs = require('fs'); + fs.close(fd, nop); }; } @@ -53,14 +44,16 @@ function onAcquired(message) { return function(err, fd) { if (err) return writeOut(message); - lazyFs().appendFile(fd, `${message}\n`, nop); + if (fs === null) fs = require('fs'); + fs.appendFile(fd, `${message}\n`, nop); }; } function acquireFd(cb) { if (cachedFd === undefined && !acquiringFd) { acquiringFd = true; - lazyFs().open(config.warningFile, 'a', onOpen(cb)); + if (fs === null) fs = require('fs'); + fs.open(config.warningFile, 'a', onOpen(cb)); } else if (cachedFd !== undefined && !acquiringFd) { cb(null, cachedFd); } else { @@ -112,7 +105,6 @@ function setupProcessWarnings() { // process.emitWarning(str[, type[, code]][, ctor]) // process.emitWarning(str[, options]) process.emitWarning = function(warning, type, code, ctor, now) { - const errors = lazyErrors(); var detail; if (type !== null && typeof type === 'object' && !Array.isArray(type)) { ctor = type.ctor; diff --git a/lib/net.js b/lib/net.js index 27df6253f16145..a22754eb302c24 100644 --- a/lib/net.js +++ b/lib/net.js @@ -43,9 +43,11 @@ const async_id_symbol = process.binding('async_wrap').async_id_symbol; const { newUid, setInitTriggerId } = require('async_hooks'); const nextTick = require('internal/process/next_tick').nextTick; const errors = require('internal/errors'); +const dns = require('dns'); -var cluster; -var dns; +// `cluster` is only used by `listenInCluster` so for startup performance +// reasons it's lazy loaded. +var cluster = null; const errnoException = util._errnoException; const exceptionWithHostPort = util._exceptionWithHostPort; @@ -999,7 +1001,6 @@ Socket.prototype.connect = function() { function lookupAndConnect(self, options) { - const dns = lazyDns(); var host = options.host || 'localhost'; var port = options.port; var localAddress = options.localAddress; @@ -1347,18 +1348,11 @@ function emitListeningNT(self) { } -function lazyDns() { - if (dns === undefined) - dns = require('dns'); - return dns; -} - - function listenInCluster(server, address, port, addressType, backlog, fd, exclusive) { exclusive = !!exclusive; - if (!cluster) cluster = require('cluster'); + if (cluster === null) cluster = require('cluster'); if (cluster.isMaster || exclusive) { // Will create a new handle @@ -1484,7 +1478,6 @@ Server.prototype.listen = function() { }; function lookupAndListen(self, port, address, backlog, exclusive) { - const dns = lazyDns(); dns.lookup(address, function doListen(err, ip, addressType) { if (err) { self.emit('error', err); diff --git a/lib/readline.js b/lib/readline.js index 036a36249588cf..4998b0678d746d 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -29,8 +29,9 @@ const errors = require('internal/errors'); const { debug, inherits } = require('util'); -const Buffer = require('buffer').Buffer; +const { Buffer } = require('buffer'); const EventEmitter = require('events'); +const { StringDecoder } = require('string_decoder'); const { CSI, emitKeys, @@ -59,7 +60,6 @@ const ESCAPE_DECODER = Symbol('escape-decoder'); // GNU readline library - keyseq-timeout is 500ms (default) const ESCAPE_CODE_TIMEOUT = 500; - function createInterface(input, output, completer, terminal) { return new Interface(input, output, completer, terminal); } @@ -181,7 +181,6 @@ function Interface(input, output, completer, terminal) { input.removeListener('data', ondata); input.removeListener('end', onend); }); - var StringDecoder = require('string_decoder').StringDecoder; // lazy load this._decoder = new StringDecoder('utf8'); } else { @@ -989,7 +988,6 @@ Interface.prototype._ttyWrite = function(s, key) { function emitKeypressEvents(stream, iface) { if (stream[KEYPRESS_DECODER]) return; - var StringDecoder = require('string_decoder').StringDecoder; // lazy load stream[KEYPRESS_DECODER] = new StringDecoder('utf8'); stream[ESCAPE_DECODER] = emitKeys(stream);