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);
}
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 = {};