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:
parent
d0c240f1be
commit
9752fce34d
77
lib/util.js
77
lib/util.js
@ -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 = {};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user