From 9752fce34d50400f8f4b5cbafbce2161b6e07a45 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 12 Dec 2018 05:42:11 +0100 Subject: [PATCH] util: improve format performance This simplifies the `format()` code and significantly improves the performance. PR-URL: https://github.com/nodejs/node/pull/24981 Reviewed-By: Gus Caplan Reviewed-By: Matteo Collina Reviewed-By: Jeremiah Senkpiel Reviewed-By: Roman Reiss --- lib/util.js | 85 +++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/lib/util.js b/lib/util.js index 389d4544689f40..ef28427cd87bc8 100644 --- a/lib/util.js +++ b/lib/util.js @@ -78,45 +78,32 @@ function format(...args) { return formatWithOptions(emptyOptions, ...args); } -function formatValue(val, inspectOptions) { - const inspectTypes = ['object', 'symbol', 'function', 'number']; - - if (inspectTypes.includes(typeof val)) { - return inspect(val, inspectOptions); - } else { - return String(val); - } -} - function formatWithOptions(inspectOptions, ...args) { const first = args[0]; - const parts = []; + let a = 0; + let str = ''; + let join = ''; - const firstIsString = typeof first === 'string'; - - if (firstIsString && args.length === 1) { - return first; - } - - if (firstIsString && /%[sjdOoif%]/.test(first)) { - let i, tempStr; - let str = ''; - let a = 1; + if (typeof first === 'string') { + if (args.length === 1) { + return first; + } + let tempStr; let lastPos = 0; - for (i = 0; i < first.length - 1; i++) { + for (var i = 0; i < first.length - 1; i++) { if (first.charCodeAt(i) === 37) { // '%' const nextChar = first.charCodeAt(++i); - if (a !== args.length) { + if (a + 1 !== args.length) { switch (nextChar) { case 115: // 's' - tempStr = String(args[a++]); + tempStr = String(args[++a]); break; case 106: // 'j' - tempStr = tryStringify(args[a++]); + tempStr = tryStringify(args[++a]); break; case 100: // 'd' - const tempNum = args[a++]; + const tempNum = args[++a]; // eslint-disable-next-line valid-typeof if (typeof tempNum === 'bigint') { tempStr = `${tempNum}n`; @@ -127,20 +114,20 @@ function formatWithOptions(inspectOptions, ...args) { } break; case 79: // 'O' - tempStr = inspect(args[a++], inspectOptions); + tempStr = inspect(args[++a], inspectOptions); break; case 111: // 'o' { - const opts = Object.assign({}, inspectOptions, { + tempStr = inspect(args[++a], { + ...inspectOptions, showHidden: true, showProxy: true, depth: 4 }); - tempStr = inspect(args[a++], opts); break; } case 105: // 'i' - const tempInteger = args[a++]; + const tempInteger = args[++a]; // eslint-disable-next-line valid-typeof if (typeof tempInteger === 'bigint') { tempStr = `${tempInteger}n`; @@ -151,7 +138,7 @@ function formatWithOptions(inspectOptions, ...args) { } break; case 102: // 'f' - const tempFloat = args[a++]; + const tempFloat = args[++a]; if (typeof tempFloat === 'symbol') { tempStr = 'NaN'; } else { @@ -176,24 +163,32 @@ function formatWithOptions(inspectOptions, ...args) { } } } - if (lastPos === 0) { - str = first; - } else if (lastPos < first.length) { - str += first.slice(lastPos); - } - - parts.push(str); - while (a < args.length) { - parts.push(formatValue(args[a], inspectOptions)); + if (lastPos !== 0) { a++; - } - } else { - for (const arg of args) { - parts.push(formatValue(arg, inspectOptions)); + join = ' '; + if (lastPos < first.length) { + str += first.slice(lastPos); + } } } - return parts.join(' '); + while (a < args.length) { + const value = args[a]; + // TODO(BridgeAR): This should apply for all besides strings. Especially + // BigInt should be properly inspected. + str += join; + if (typeof value !== 'string' && + typeof value !== 'boolean' && + // eslint-disable-next-line valid-typeof + typeof value !== 'bigint') { + str += inspect(value, inspectOptions); + } else { + str += value; + } + join = ' '; + a++; + } + return str; } const debugs = {};