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 <me@gus.host>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
This commit is contained in:
Ruben Bridgewater 2018-12-12 05:42:11 +01:00
parent d0c240f1be
commit 9752fce34d
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762

View File

@ -78,45 +78,32 @@ function format(...args) {
return formatWithOptions(emptyOptions, ...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) { function formatWithOptions(inspectOptions, ...args) {
const first = args[0]; const first = args[0];
const parts = []; let a = 0;
let str = '';
let join = '';
const firstIsString = typeof first === 'string'; if (typeof first === 'string') {
if (args.length === 1) {
if (firstIsString && args.length === 1) {
return first; return first;
} }
let tempStr;
if (firstIsString && /%[sjdOoif%]/.test(first)) {
let i, tempStr;
let str = '';
let a = 1;
let lastPos = 0; 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) { // '%' if (first.charCodeAt(i) === 37) { // '%'
const nextChar = first.charCodeAt(++i); const nextChar = first.charCodeAt(++i);
if (a !== args.length) { if (a + 1 !== args.length) {
switch (nextChar) { switch (nextChar) {
case 115: // 's' case 115: // 's'
tempStr = String(args[a++]); tempStr = String(args[++a]);
break; break;
case 106: // 'j' case 106: // 'j'
tempStr = tryStringify(args[a++]); tempStr = tryStringify(args[++a]);
break; break;
case 100: // 'd' case 100: // 'd'
const tempNum = args[a++]; const tempNum = args[++a];
// eslint-disable-next-line valid-typeof // eslint-disable-next-line valid-typeof
if (typeof tempNum === 'bigint') { if (typeof tempNum === 'bigint') {
tempStr = `${tempNum}n`; tempStr = `${tempNum}n`;
@ -127,20 +114,20 @@ function formatWithOptions(inspectOptions, ...args) {
} }
break; break;
case 79: // 'O' case 79: // 'O'
tempStr = inspect(args[a++], inspectOptions); tempStr = inspect(args[++a], inspectOptions);
break; break;
case 111: // 'o' case 111: // 'o'
{ {
const opts = Object.assign({}, inspectOptions, { tempStr = inspect(args[++a], {
...inspectOptions,
showHidden: true, showHidden: true,
showProxy: true, showProxy: true,
depth: 4 depth: 4
}); });
tempStr = inspect(args[a++], opts);
break; break;
} }
case 105: // 'i' case 105: // 'i'
const tempInteger = args[a++]; const tempInteger = args[++a];
// eslint-disable-next-line valid-typeof // eslint-disable-next-line valid-typeof
if (typeof tempInteger === 'bigint') { if (typeof tempInteger === 'bigint') {
tempStr = `${tempInteger}n`; tempStr = `${tempInteger}n`;
@ -151,7 +138,7 @@ function formatWithOptions(inspectOptions, ...args) {
} }
break; break;
case 102: // 'f' case 102: // 'f'
const tempFloat = args[a++]; const tempFloat = args[++a];
if (typeof tempFloat === 'symbol') { if (typeof tempFloat === 'symbol') {
tempStr = 'NaN'; tempStr = 'NaN';
} else { } else {
@ -176,24 +163,32 @@ function formatWithOptions(inspectOptions, ...args) {
} }
} }
} }
if (lastPos === 0) { if (lastPos !== 0) {
str = first; a++;
} else if (lastPos < first.length) { join = ' ';
if (lastPos < first.length) {
str += first.slice(lastPos); str += first.slice(lastPos);
} }
}
}
parts.push(str);
while (a < args.length) { while (a < args.length) {
parts.push(formatValue(args[a], inspectOptions)); 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++; a++;
} }
} else { return str;
for (const arg of args) {
parts.push(formatValue(arg, inspectOptions));
}
}
return parts.join(' ');
} }
const debugs = {}; const debugs = {};