mirror of
https://github.com/nodejs/node.git
synced 2025-04-29 14:25:18 +00:00
errors: improve performance of determine-specific-type
PR-URL: https://github.com/nodejs/node/pull/49696 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
This commit is contained in:
parent
b903a710f4
commit
0ee9c83ffc
58
benchmark/error/determine-specific-type.js
Normal file
58
benchmark/error/determine-specific-type.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e6],
|
||||||
|
v: [
|
||||||
|
'() => 1n',
|
||||||
|
'() => true',
|
||||||
|
'() => false',
|
||||||
|
'() => 2',
|
||||||
|
'() => +0',
|
||||||
|
'() => -0',
|
||||||
|
'() => NaN',
|
||||||
|
'() => Infinity',
|
||||||
|
'() => ""',
|
||||||
|
'() => "\'"',
|
||||||
|
'() => Symbol("foo")',
|
||||||
|
'() => function foo() {}',
|
||||||
|
'() => null',
|
||||||
|
'() => undefined',
|
||||||
|
'() => new Array()',
|
||||||
|
'() => new BigInt64Array()',
|
||||||
|
'() => new BigUint64Array()',
|
||||||
|
'() => new Int8Array()',
|
||||||
|
'() => new Int16Array()',
|
||||||
|
'() => new Int32Array()',
|
||||||
|
'() => new Float32Array()',
|
||||||
|
'() => new Float64Array()',
|
||||||
|
'() => new Uint8Array()',
|
||||||
|
'() => new Uint8ClampedArray()',
|
||||||
|
'() => new Uint16Array()',
|
||||||
|
'() => new Uint32Array()',
|
||||||
|
'() => new Date()',
|
||||||
|
'() => new Map()',
|
||||||
|
'() => new WeakMap()',
|
||||||
|
'() => new Object()',
|
||||||
|
'() => Promise.resolve("foo")',
|
||||||
|
'() => new Set()',
|
||||||
|
'() => new WeakSet()',
|
||||||
|
'() => ({ __proto__: null })',
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
flags: ['--expose-internals'],
|
||||||
|
});
|
||||||
|
|
||||||
|
function main({ n, v }) {
|
||||||
|
const {
|
||||||
|
determineSpecificType,
|
||||||
|
} = require('internal/errors');
|
||||||
|
|
||||||
|
const value = eval(v)();
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
for (let i = 0; i < n; ++i)
|
||||||
|
determineSpecificType(value);
|
||||||
|
bench.end(n);
|
||||||
|
}
|
@ -48,6 +48,7 @@ const {
|
|||||||
String,
|
String,
|
||||||
StringPrototypeEndsWith,
|
StringPrototypeEndsWith,
|
||||||
StringPrototypeIncludes,
|
StringPrototypeIncludes,
|
||||||
|
StringPrototypeIndexOf,
|
||||||
StringPrototypeSlice,
|
StringPrototypeSlice,
|
||||||
StringPrototypeSplit,
|
StringPrototypeSplit,
|
||||||
StringPrototypeStartsWith,
|
StringPrototypeStartsWith,
|
||||||
@ -939,23 +940,53 @@ const genericNodeError = hideStackFrames(function genericNodeError(message, erro
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function determineSpecificType(value) {
|
function determineSpecificType(value) {
|
||||||
if (value == null) {
|
if (value === null) {
|
||||||
return '' + value;
|
return 'null';
|
||||||
|
} else if (value === undefined) {
|
||||||
|
return 'undefined';
|
||||||
}
|
}
|
||||||
if (typeof value === 'function' && value.name) {
|
|
||||||
return `function ${value.name}`;
|
|
||||||
}
|
|
||||||
if (typeof value === 'object') {
|
|
||||||
if (value.constructor?.name) {
|
|
||||||
return `an instance of ${value.constructor.name}`;
|
|
||||||
}
|
|
||||||
return `${lazyInternalUtilInspect().inspect(value, { depth: -1 })}`;
|
|
||||||
}
|
|
||||||
let inspected = lazyInternalUtilInspect()
|
|
||||||
.inspect(value, { colors: false });
|
|
||||||
if (inspected.length > 28) { inspected = `${StringPrototypeSlice(inspected, 0, 25)}...`; }
|
|
||||||
|
|
||||||
return `type ${typeof value} (${inspected})`;
|
const type = typeof value;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'bigint':
|
||||||
|
return `type bigint (${value}n)`;
|
||||||
|
case 'number':
|
||||||
|
if (value === 0) {
|
||||||
|
return 1 / value === -Infinity ? 'type number (-0)' : 'type number (0)';
|
||||||
|
} else if (value !== value) { // eslint-disable-line no-self-compare
|
||||||
|
return 'type number (NaN)';
|
||||||
|
} else if (value === Infinity) {
|
||||||
|
return 'type number (Infinity)';
|
||||||
|
} else if (value === -Infinity) {
|
||||||
|
return 'type number (-Infinity)';
|
||||||
|
}
|
||||||
|
return `type number (${value})`;
|
||||||
|
case 'boolean':
|
||||||
|
return value ? 'type boolean (true)' : 'type boolean (false)';
|
||||||
|
case 'symbol':
|
||||||
|
return `type symbol (${String(value)})`;
|
||||||
|
case 'function':
|
||||||
|
return `function ${value.name}`;
|
||||||
|
case 'object':
|
||||||
|
if (value.constructor && 'name' in value.constructor) {
|
||||||
|
return `an instance of ${value.constructor.name}`;
|
||||||
|
}
|
||||||
|
return `${lazyInternalUtilInspect().inspect(value, { depth: -1 })}`;
|
||||||
|
case 'string':
|
||||||
|
value.length > 28 && (value = `${StringPrototypeSlice(value, 0, 25)}...`);
|
||||||
|
if (StringPrototypeIndexOf(value, "'") === -1) {
|
||||||
|
return `type string ('${value}')`;
|
||||||
|
}
|
||||||
|
return `type string (${JSONStringify(value)})`;
|
||||||
|
default:
|
||||||
|
value = lazyInternalUtilInspect().inspect(value, { colors: false });
|
||||||
|
if (value.length > 28) {
|
||||||
|
value = `${StringPrototypeSlice(value, 0, 25)}...`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `type ${type} (${value})`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -816,7 +816,7 @@ function invalidArgTypeHelper(input) {
|
|||||||
if (input == null) {
|
if (input == null) {
|
||||||
return ` Received ${input}`;
|
return ` Received ${input}`;
|
||||||
}
|
}
|
||||||
if (typeof input === 'function' && input.name) {
|
if (typeof input === 'function') {
|
||||||
return ` Received function ${input.name}`;
|
return ` Received function ${input.name}`;
|
||||||
}
|
}
|
||||||
if (typeof input === 'object') {
|
if (typeof input === 'object') {
|
||||||
|
@ -12,6 +12,10 @@ strictEqual(
|
|||||||
'type bigint (1n)',
|
'type bigint (1n)',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType(true),
|
||||||
|
'type boolean (true)',
|
||||||
|
);
|
||||||
strictEqual(
|
strictEqual(
|
||||||
determineSpecificType(false),
|
determineSpecificType(false),
|
||||||
'type boolean (false)',
|
'type boolean (false)',
|
||||||
@ -42,6 +46,27 @@ strictEqual(
|
|||||||
"type string ('')",
|
"type string ('')",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType(''),
|
||||||
|
"type string ('')",
|
||||||
|
);
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType("''"),
|
||||||
|
"type string (\"''\")",
|
||||||
|
);
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor'),
|
||||||
|
"type string ('Lorem ipsum dolor sit ame...')",
|
||||||
|
);
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor'"),
|
||||||
|
"type string ('Lorem ipsum dolor sit ame...')",
|
||||||
|
);
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType("Lorem' ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor"),
|
||||||
|
"type string (\"Lorem' ipsum dolor sit am...\")",
|
||||||
|
);
|
||||||
|
|
||||||
strictEqual(
|
strictEqual(
|
||||||
determineSpecificType(Symbol('foo')),
|
determineSpecificType(Symbol('foo')),
|
||||||
'type symbol (Symbol(foo))',
|
'type symbol (Symbol(foo))',
|
||||||
@ -52,6 +77,38 @@ strictEqual(
|
|||||||
'function foo',
|
'function foo',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const implicitlyNamed = function() {}; // eslint-disable-line func-style
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType(implicitlyNamed),
|
||||||
|
'function implicitlyNamed',
|
||||||
|
);
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType(() => {}),
|
||||||
|
'function ',
|
||||||
|
);
|
||||||
|
function noName() {}
|
||||||
|
delete noName.name;
|
||||||
|
strictEqual(
|
||||||
|
noName.name,
|
||||||
|
'',
|
||||||
|
);
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType(noName),
|
||||||
|
'function ',
|
||||||
|
);
|
||||||
|
|
||||||
|
function * generatorFn() {}
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType(generatorFn),
|
||||||
|
'function generatorFn',
|
||||||
|
);
|
||||||
|
|
||||||
|
async function asyncFn() {}
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType(asyncFn),
|
||||||
|
'function asyncFn',
|
||||||
|
);
|
||||||
|
|
||||||
strictEqual(
|
strictEqual(
|
||||||
determineSpecificType(null),
|
determineSpecificType(null),
|
||||||
'null',
|
'null',
|
||||||
@ -134,6 +191,10 @@ strictEqual(
|
|||||||
determineSpecificType({}),
|
determineSpecificType({}),
|
||||||
'an instance of Object',
|
'an instance of Object',
|
||||||
);
|
);
|
||||||
|
strictEqual(
|
||||||
|
determineSpecificType(new Object()),
|
||||||
|
'an instance of Object',
|
||||||
|
);
|
||||||
|
|
||||||
strictEqual(
|
strictEqual(
|
||||||
determineSpecificType(Promise.resolve('foo')),
|
determineSpecificType(Promise.resolve('foo')),
|
||||||
|
@ -61,7 +61,7 @@ assert.throws(
|
|||||||
{
|
{
|
||||||
code: 'ERR_INVALID_ARG_TYPE',
|
code: 'ERR_INVALID_ARG_TYPE',
|
||||||
message: 'The "path" argument must be of type string or an instance of ' +
|
message: 'The "path" argument must be of type string or an instance of ' +
|
||||||
'Buffer or URL. Received type function ([Function (anonymous)])',
|
'Buffer or URL. Received function ',
|
||||||
name: 'TypeError'
|
name: 'TypeError'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user