From bf29544079be7fa749539ff54ee349c66eda1936 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 15 Feb 2017 13:00:21 -0800 Subject: [PATCH 1/3] lib: refactor internal/util * Use the more efficient module.exports = {} approach * Eliminate some uses of arguments --- lib/internal/util.js | 114 ++++++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 40 deletions(-) diff --git a/lib/internal/util.js b/lib/internal/util.js index 0a5d4d1f18dac9..3771b712b59978 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -5,19 +5,43 @@ const signals = process.binding('constants').os.signals; const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol']; const kDecoratedPrivateSymbolIndex = binding['decorated_private_symbol']; +const noCrypto = !process.versions.openssl; -// The `buffer` module uses this. Defining it here instead of in the public -// `util` module makes it accessible without having to `require('util')` there. -exports.customInspectSymbol = Symbol('util.inspect.custom'); +/* + * Implementation of ToInteger as per ECMAScript Specification + * Refer: http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger + */ +function toInteger(argument) { + const number = +argument; + return Number.isNaN(number) ? 0 : Math.trunc(number); +} -// Mark that a method should not be used. -// Returns a modified function which warns once by default. -// If --no-deprecation is set, then it is a no-op. -exports.deprecate = function deprecate(fn, msg, code) { +/* + * Implementation of ToLength as per ECMAScript Specification + * Refer: http://www.ecma-international.org/ecma-262/6.0/#sec-tolength + */ +function toLength(argument) { + const len = toInteger(argument); + return len <= 0 ? 0 : Math.min(len, Number.MAX_SAFE_INTEGER); +} + +function isError(e) { + return objectToString(e) === '[object Error]' || e instanceof Error; +} + + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + // Mark that a method should not be used. + // Returns a modified function which warns once by default. + // If --no-deprecation is set, then it is a no-op. +function deprecate(fn, msg, code) { // Allow for deprecating things in the process of starting up. if (global.process === undefined) { - return function() { - return exports.deprecate(fn, msg, code).apply(this, arguments); + return function(...args) { + return deprecate(fn, msg).apply(this, args); }; } @@ -29,7 +53,7 @@ exports.deprecate = function deprecate(fn, msg, code) { throw new TypeError('`code` argument must be a string'); var warned = false; - function deprecated() { + function deprecated(...args) { if (!warned) { warned = true; if (code !== undefined) { @@ -39,9 +63,9 @@ exports.deprecate = function deprecate(fn, msg, code) { } } if (new.target) { - return Reflect.construct(fn, arguments, new.target); + return Reflect.construct(fn, args, new.target); } - return fn.apply(this, arguments); + return fn.apply(this, args); } // The wrapper will keep the same prototype as fn to maintain prototype chain @@ -54,10 +78,10 @@ exports.deprecate = function deprecate(fn, msg, code) { } return deprecated; -}; +} -exports.decorateErrorStack = function decorateErrorStack(err) { - if (!(exports.isError(err) && err.stack) || +function decorateErrorStack(err) { + if (!(isError(err) && err.stack) || binding.getHiddenValue(err, kDecoratedPrivateSymbolIndex) === true) return; @@ -67,30 +91,19 @@ exports.decorateErrorStack = function decorateErrorStack(err) { err.stack = arrow + err.stack; binding.setHiddenValue(err, kDecoratedPrivateSymbolIndex, true); } -}; - -exports.isError = function isError(e) { - return exports.objectToString(e) === '[object Error]' || e instanceof Error; -}; - -exports.objectToString = function objectToString(o) { - return Object.prototype.toString.call(o); -}; +} -const noCrypto = !process.versions.openssl; -exports.assertCrypto = function() { +function assertCrypto() { if (noCrypto) throw new Error('Node.js is not compiled with openssl crypto support'); -}; - -exports.kIsEncodingSymbol = Symbol('node.isEncoding'); +} // The loop should only run at most twice, retrying with lowercased enc // if there is no match in the first pass. // We use a loop instead of branching to retry with a helper // function in order to avoid the performance hit. // Return undefined if there is no match. -exports.normalizeEncoding = function normalizeEncoding(enc) { +function normalizeEncoding(enc) { if (!enc) return 'utf8'; var retried; while (true) { @@ -116,11 +129,9 @@ exports.normalizeEncoding = function normalizeEncoding(enc) { retried = true; } } -}; +} -// Filters duplicate strings. Used to support functions in crypto and tls -// modules. Implemented specifically to maintain existing behaviors in each. -exports.filterDuplicateStrings = function filterDuplicateStrings(items, low) { +function filterDuplicateStrings(items, low) { const map = new Map(); for (var i = 0; i < items.length; i++) { const item = items[i]; @@ -132,16 +143,16 @@ exports.filterDuplicateStrings = function filterDuplicateStrings(items, low) { } } return Array.from(map.values()).sort(); -}; +} -exports.cachedResult = function cachedResult(fn) { +function cachedResult(fn) { var result; return () => { if (result === undefined) result = fn(); return result.slice(); }; -}; +} // Useful for Wrapping an ES6 Class with a constructor Function that // does not require the new keyword. For instance: @@ -149,7 +160,7 @@ exports.cachedResult = function cachedResult(fn) { // const B = createClassWrapper(A); // B() instanceof A // true // B() instanceof B // true -exports.createClassWrapper = function createClassWrapper(type) { +function createClassWrapper(type) { const fn = function(...args) { return Reflect.construct(type, args, new.target || type); }; @@ -161,7 +172,7 @@ exports.createClassWrapper = function createClassWrapper(type) { Object.setPrototypeOf(fn, type); fn.prototype = type.prototype; return fn; -}; +} let signalsToNamesMapping; function getSignalsToNamesMapping() { @@ -176,7 +187,7 @@ function getSignalsToNamesMapping() { return signalsToNamesMapping; } -exports.convertToValidSignal = function convertToValidSignal(signal) { +function convertToValidSignal(signal) { if (typeof signal === 'number' && getSignalsToNamesMapping()[signal]) return signal; @@ -186,4 +197,27 @@ exports.convertToValidSignal = function convertToValidSignal(signal) { } throw new Error('Unknown signal: ' + signal); +} + +module.exports = { + assertCrypto, + cachedResult, + convertToValidSignal, + createClassWrapper, + decorateErrorStack, + deprecate, + filterDuplicateStrings, + isError, + normalizeEncoding, + objectToString, + toInteger, + toLength, + + // Symbol used to provide a custom inspect function for an object as an + // alternative to using 'inspect' + customInspectSymbol: Symbol('util.inspect.custom'), + + // Used by the buffer module to capture an internal reference to the + // default isEncoding implementation, just in case userland overrides it. + kIsEncodingSymbol: Symbol('node.isEncoding') }; From 4b013e8d862395e1181788ed5b133ea5ee54b3a8 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 20 Apr 2017 11:40:55 -0700 Subject: [PATCH 2/3] Address nits --- lib/internal/util.js | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/lib/internal/util.js b/lib/internal/util.js index 3771b712b59978..983bab5a1c5978 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -7,29 +7,10 @@ const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol']; const kDecoratedPrivateSymbolIndex = binding['decorated_private_symbol']; const noCrypto = !process.versions.openssl; -/* - * Implementation of ToInteger as per ECMAScript Specification - * Refer: http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger - */ -function toInteger(argument) { - const number = +argument; - return Number.isNaN(number) ? 0 : Math.trunc(number); -} - -/* - * Implementation of ToLength as per ECMAScript Specification - * Refer: http://www.ecma-international.org/ecma-262/6.0/#sec-tolength - */ -function toLength(argument) { - const len = toInteger(argument); - return len <= 0 ? 0 : Math.min(len, Number.MAX_SAFE_INTEGER); -} - function isError(e) { return objectToString(e) === '[object Error]' || e instanceof Error; } - function objectToString(o) { return Object.prototype.toString.call(o); } @@ -210,8 +191,6 @@ module.exports = { isError, normalizeEncoding, objectToString, - toInteger, - toLength, // Symbol used to provide a custom inspect function for an object as an // alternative to using 'inspect' From 3a6954a22f119d9b0e54a4cf88e10a5e3807039d Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 20 Apr 2017 11:47:28 -0700 Subject: [PATCH 3/3] Address nits --- lib/internal/util.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/internal/util.js b/lib/internal/util.js index 983bab5a1c5978..48036148b973cb 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -15,9 +15,9 @@ function objectToString(o) { return Object.prototype.toString.call(o); } - // Mark that a method should not be used. - // Returns a modified function which warns once by default. - // If --no-deprecation is set, then it is a no-op. +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. function deprecate(fn, msg, code) { // Allow for deprecating things in the process of starting up. if (global.process === undefined) { @@ -180,7 +180,7 @@ function convertToValidSignal(signal) { throw new Error('Unknown signal: ' + signal); } -module.exports = { +module.exports = exports = { assertCrypto, cachedResult, convertToValidSignal,