mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
lib: faster type checks for some types
PR-URL: https://github.com/nodejs/node/pull/15663 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
1 parent
34dbc9e4e8
commit
7907534a8d
20 files changed
+140
-30
No files matched your search
+2
-1
@@ -22,6 +22,7 @@
|
||||
'use strict';
|
||||
|
||||
const { parseCertString } = require('internal/tls');
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
const tls = require('tls');
|
||||
const errors = require('internal/errors');
|
||||
|
||||
@@ -55,7 +56,7 @@ function SecureContext(secureProtocol, secureOptions, context) {
|
||||
}
|
||||
|
||||
function validateKeyCert(value, type) {
|
||||
if (typeof value !== 'string' && !ArrayBuffer.isView(value))
|
||||
if (typeof value !== 'string' && !isArrayBufferView(value))
|
||||
throw new errors.TypeError(
|
||||
'ERR_INVALID_ARG_TYPE', type,
|
||||
['string', 'Buffer', 'TypedArray', 'DataView']
|
||||
|
||||
+3
-2
@@ -23,6 +23,7 @@
|
||||
const { compare } = process.binding('buffer');
|
||||
const { isSet, isMap, isDate, isRegExp } = process.binding('util');
|
||||
const { objectToString } = require('internal/util');
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
const errors = require('internal/errors');
|
||||
const { propertyIsEnumerable } = Object.prototype;
|
||||
|
||||
@@ -209,7 +210,7 @@ function strictDeepEqual(actual, expected, memos) {
|
||||
if (actual.message !== expected.message) {
|
||||
return false;
|
||||
}
|
||||
} else if (ArrayBuffer.isView(actual)) {
|
||||
} else if (isArrayBufferView(actual)) {
|
||||
if (!areSimilarTypedArrays(actual, expected,
|
||||
isFloatTypedArrayTag(actualTag) ? 0 : 300)) {
|
||||
return false;
|
||||
@@ -262,7 +263,7 @@ function looseDeepEqual(actual, expected, memos) {
|
||||
const actualTag = objectToString(actual);
|
||||
const expectedTag = objectToString(expected);
|
||||
if (actualTag === expectedTag) {
|
||||
if (!isObjectOrArrayTag(actualTag) && ArrayBuffer.isView(actual)) {
|
||||
if (!isObjectOrArrayTag(actualTag) && isArrayBufferView(actual)) {
|
||||
return areSimilarTypedArrays(actual, expected,
|
||||
isFloatTypedArrayTag(actualTag) ?
|
||||
Infinity : 300);
|
||||
|
||||
+6
-5
@@ -46,15 +46,16 @@ const {
|
||||
kMaxLength,
|
||||
kStringMaxLength
|
||||
} = process.binding('buffer');
|
||||
const {
|
||||
isAnyArrayBuffer,
|
||||
isUint8Array
|
||||
} = process.binding('util');
|
||||
const { isAnyArrayBuffer } = process.binding('util');
|
||||
const {
|
||||
customInspectSymbol,
|
||||
normalizeEncoding,
|
||||
kIsEncodingSymbol
|
||||
} = require('internal/util');
|
||||
const {
|
||||
isArrayBufferView,
|
||||
isUint8Array
|
||||
} = require('internal/util/types');
|
||||
const {
|
||||
pendingDeprecation
|
||||
} = process.binding('config');
|
||||
@@ -501,7 +502,7 @@ function base64ByteLength(str, bytes) {
|
||||
|
||||
function byteLength(string, encoding) {
|
||||
if (typeof string !== 'string') {
|
||||
if (ArrayBuffer.isView(string) || isAnyArrayBuffer(string)) {
|
||||
if (isArrayBufferView(string) || isAnyArrayBuffer(string)) {
|
||||
return string.byteLength;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
|
||||
const util = require('util');
|
||||
const { deprecate, convertToValidSignal } = require('internal/util');
|
||||
const { isUint8Array } = require('internal/util/types');
|
||||
const { createPromise,
|
||||
promiseResolve, promiseReject } = process.binding('util');
|
||||
const debug = util.debuglog('child_process');
|
||||
|
||||
const Buffer = require('buffer').Buffer;
|
||||
const Pipe = process.binding('pipe_wrap').Pipe;
|
||||
const { isUint8Array } = process.binding('util');
|
||||
const { errname } = process.binding('uv');
|
||||
const child_process = require('internal/child_process');
|
||||
|
||||
|
||||
+1
-1
@@ -26,6 +26,7 @@ const errors = require('internal/errors');
|
||||
const Buffer = require('buffer').Buffer;
|
||||
const dns = require('dns');
|
||||
const util = require('util');
|
||||
const { isUint8Array } = require('internal/util/types');
|
||||
const EventEmitter = require('events');
|
||||
const setInitTriggerId = require('async_hooks').setInitTriggerId;
|
||||
const UV_UDP_REUSEADDR = process.binding('constants').os.UV_UDP_REUSEADDR;
|
||||
@@ -34,7 +35,6 @@ const nextTick = require('internal/process/next_tick').nextTick;
|
||||
|
||||
const UDP = process.binding('udp_wrap').UDP;
|
||||
const SendWrap = process.binding('udp_wrap').SendWrap;
|
||||
const { isUint8Array } = process.binding('util');
|
||||
|
||||
const BIND_STATE_UNBOUND = 0;
|
||||
const BIND_STATE_BINDING = 1;
|
||||
|
||||
@@ -28,7 +28,8 @@ const constants = process.binding('constants').fs;
|
||||
const { S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK } = constants;
|
||||
const util = require('util');
|
||||
const pathModule = require('path');
|
||||
const { isUint8Array, createPromise, promiseResolve } = process.binding('util');
|
||||
const { isUint8Array } = require('internal/util/types');
|
||||
const { createPromise, promiseResolve } = process.binding('util');
|
||||
|
||||
const binding = process.binding('fs');
|
||||
const fs = exports;
|
||||
|
||||
@@ -15,8 +15,8 @@ const TTY = process.binding('tty_wrap').TTY;
|
||||
const TCP = process.binding('tcp_wrap').TCP;
|
||||
const UDP = process.binding('udp_wrap').UDP;
|
||||
const SocketList = require('internal/socket_list');
|
||||
const { isUint8Array } = process.binding('util');
|
||||
const { convertToValidSignal } = require('internal/util');
|
||||
const { isUint8Array } = require('internal/util/types');
|
||||
const spawn_sync = process.binding('spawn_sync');
|
||||
|
||||
const {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
const { Buffer } = require('buffer');
|
||||
const errors = require('internal/errors');
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
const {
|
||||
getDefaultEncoding,
|
||||
toBuf
|
||||
@@ -25,7 +26,7 @@ function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
|
||||
|
||||
if (typeof sizeOrKey !== 'number' &&
|
||||
typeof sizeOrKey !== 'string' &&
|
||||
!ArrayBuffer.isView(sizeOrKey)) {
|
||||
!isArrayBufferView(sizeOrKey)) {
|
||||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'sizeOrKey',
|
||||
['number', 'string', 'Buffer', 'TypedArray',
|
||||
'DataView']);
|
||||
|
||||
@@ -10,15 +10,12 @@ const {
|
||||
toBuf
|
||||
} = require('internal/crypto/util');
|
||||
|
||||
const {
|
||||
isArrayBufferView
|
||||
} = process.binding('util');
|
||||
|
||||
const { Buffer } = require('buffer');
|
||||
|
||||
const errors = require('internal/errors');
|
||||
const { inherits } = require('util');
|
||||
const { normalizeEncoding } = require('internal/util');
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
const LazyTransform = require('internal/streams/lazy_transform');
|
||||
const kState = Symbol('state');
|
||||
const kFinalized = Symbol('finalized');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const errors = require('internal/errors');
|
||||
const { isArrayBufferView } = process.binding('util');
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
const {
|
||||
randomBytes,
|
||||
randomFill: _randomFill
|
||||
|
||||
@@ -20,6 +20,8 @@ const {
|
||||
customInspectSymbol: inspect
|
||||
} = require('internal/util');
|
||||
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
|
||||
const {
|
||||
isArrayBuffer
|
||||
} = process.binding('util');
|
||||
@@ -386,7 +388,7 @@ function makeTextDecoderICU() {
|
||||
throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder');
|
||||
if (isArrayBuffer(input)) {
|
||||
input = lazyBuffer().from(input);
|
||||
} else if (!ArrayBuffer.isView(input)) {
|
||||
} else if (!isArrayBufferView(input)) {
|
||||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'input',
|
||||
['ArrayBuffer', 'ArrayBufferView']);
|
||||
}
|
||||
@@ -462,7 +464,7 @@ function makeTextDecoderJS() {
|
||||
throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder');
|
||||
if (isArrayBuffer(input)) {
|
||||
input = lazyBuffer().from(input);
|
||||
} else if (ArrayBuffer.isView(input)) {
|
||||
} else if (isArrayBufferView(input)) {
|
||||
input = lazyBuffer().from(input.buffer, input.byteOffset,
|
||||
input.byteLength);
|
||||
} else {
|
||||
|
||||
@@ -21,8 +21,9 @@ const { onServerStream,
|
||||
} = require('internal/http2/compat');
|
||||
const { utcDate } = require('internal/http');
|
||||
const { promisify } = require('internal/util');
|
||||
const { isUint8Array } = require('internal/util/types');
|
||||
const { _connectionListener: httpConnectionListener } = require('http');
|
||||
const { isUint8Array, createPromise, promiseResolve } = process.binding('util');
|
||||
const { createPromise, promiseResolve } = process.binding('util');
|
||||
const debug = util.debuglog('http2');
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
const ReflectApply = Reflect.apply;
|
||||
|
||||
// This function is borrowed from the function with the same name on V8 Extras'
|
||||
// `utils` object. V8 implements Reflect.apply very efficiently in conjunction
|
||||
// with the spread syntax, such that no additional special case is needed for
|
||||
// function calls w/o arguments.
|
||||
// Refs: https://github.com/v8/v8/blob/d6ead37d265d7215cf9c5f768f279e21bd170212/src/js/prologue.js#L152-L156
|
||||
function uncurryThis(func) {
|
||||
return (thisArg, ...args) => ReflectApply(func, thisArg, args);
|
||||
}
|
||||
|
||||
const TypedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype);
|
||||
|
||||
const TypedArrayProto_toStringTag =
|
||||
uncurryThis(
|
||||
Object.getOwnPropertyDescriptor(TypedArrayPrototype,
|
||||
Symbol.toStringTag).get);
|
||||
|
||||
// Cached to make sure no userland code can tamper with it.
|
||||
const isArrayBufferView = ArrayBuffer.isView;
|
||||
|
||||
function isTypedArray(value) {
|
||||
return TypedArrayProto_toStringTag(value) !== undefined;
|
||||
}
|
||||
|
||||
function isUint8Array(value) {
|
||||
return TypedArrayProto_toStringTag(value) === 'Uint8Array';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isArrayBufferView,
|
||||
isTypedArray,
|
||||
isUint8Array
|
||||
};
|
||||
+2
-1
@@ -44,6 +44,7 @@
|
||||
|
||||
const internalModule = require('internal/module');
|
||||
const internalUtil = require('internal/util');
|
||||
const { isTypedArray } = require('internal/util/types');
|
||||
const util = require('util');
|
||||
const utilBinding = process.binding('util');
|
||||
const inherits = util.inherits;
|
||||
@@ -726,7 +727,7 @@ const ARRAY_LENGTH_THRESHOLD = 1e6;
|
||||
function mayBeLargeObject(obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.length > ARRAY_LENGTH_THRESHOLD ? ['length'] : null;
|
||||
} else if (utilBinding.isTypedArray(obj)) {
|
||||
} else if (isTypedArray(obj)) {
|
||||
return obj.length > ARRAY_LENGTH_THRESHOLD ? [] : null;
|
||||
}
|
||||
|
||||
|
||||
+9
-3
@@ -38,10 +38,16 @@ Stream.Stream = Stream;
|
||||
|
||||
// Internal utilities
|
||||
try {
|
||||
Stream._isUint8Array = process.binding('util').isUint8Array;
|
||||
Stream._isUint8Array = require('internal/util/types').isUint8Array;
|
||||
} catch (e) {
|
||||
// This throws for Node < 4.2.0 because there’s no util binding and
|
||||
// returns undefined for Node < 7.4.0.
|
||||
// Throws for code outside of Node.js core.
|
||||
|
||||
try {
|
||||
Stream._isUint8Array = process.binding('util').isUint8Array;
|
||||
} catch (e) {
|
||||
// This throws for Node < 4.2.0 because there’s no util binding and
|
||||
// returns undefined for Node < 7.4.0.
|
||||
}
|
||||
}
|
||||
|
||||
if (!Stream._isUint8Array) {
|
||||
|
||||
+1
-1
@@ -25,12 +25,12 @@ const errors = require('internal/errors');
|
||||
const internalUtil = require('internal/util');
|
||||
const internalTLS = require('internal/tls');
|
||||
internalUtil.assertCrypto();
|
||||
const { isUint8Array } = require('internal/util/types');
|
||||
|
||||
const net = require('net');
|
||||
const url = require('url');
|
||||
const binding = process.binding('crypto');
|
||||
const Buffer = require('buffer').Buffer;
|
||||
const { isUint8Array } = process.binding('util');
|
||||
|
||||
// Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations
|
||||
// every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more
|
||||
|
||||
+4
-1
@@ -38,13 +38,16 @@ const {
|
||||
isPromise,
|
||||
isSet,
|
||||
isSetIterator,
|
||||
isTypedArray,
|
||||
isRegExp,
|
||||
isDate,
|
||||
kPending,
|
||||
kRejected,
|
||||
} = process.binding('util');
|
||||
|
||||
const {
|
||||
isTypedArray
|
||||
} = require('internal/util/types');
|
||||
|
||||
const {
|
||||
customInspectSymbol,
|
||||
deprecate,
|
||||
|
||||
+4
-3
@@ -24,6 +24,7 @@
|
||||
const Buffer = require('buffer').Buffer;
|
||||
const Transform = require('_stream_transform');
|
||||
const { _extend } = require('util');
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
const binding = process.binding('zlib');
|
||||
const assert = require('assert').ok;
|
||||
const kMaxLength = require('buffer').kMaxLength;
|
||||
@@ -62,7 +63,7 @@ for (var ck = 0; ck < ckeys.length; ck++) {
|
||||
function zlibBuffer(engine, buffer, callback) {
|
||||
// Streams do not support non-Buffer ArrayBufferViews yet. Convert it to a
|
||||
// Buffer without copying.
|
||||
if (ArrayBuffer.isView(buffer) &&
|
||||
if (isArrayBufferView(buffer) &&
|
||||
Object.getPrototypeOf(buffer) !== Buffer.prototype) {
|
||||
buffer = Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
}
|
||||
@@ -109,7 +110,7 @@ function zlibBufferOnEnd() {
|
||||
function zlibBufferSync(engine, buffer) {
|
||||
if (typeof buffer === 'string') {
|
||||
buffer = Buffer.from(buffer);
|
||||
} else if (!ArrayBuffer.isView(buffer)) {
|
||||
} else if (!isArrayBufferView(buffer)) {
|
||||
throw new TypeError('"buffer" argument must be a string, Buffer, ' +
|
||||
'TypedArray, or DataView');
|
||||
}
|
||||
@@ -226,7 +227,7 @@ function Zlib(opts, mode) {
|
||||
}
|
||||
|
||||
dictionary = opts.dictionary;
|
||||
if (dictionary !== undefined && !ArrayBuffer.isView(dictionary)) {
|
||||
if (dictionary !== undefined && !isArrayBufferView(dictionary)) {
|
||||
throw new TypeError(
|
||||
'Invalid dictionary: it should be a Buffer, TypedArray, or DataView');
|
||||
}
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
'lib/internal/tls.js',
|
||||
'lib/internal/url.js',
|
||||
'lib/internal/util.js',
|
||||
'lib/internal/util/types.js',
|
||||
'lib/internal/http2/core.js',
|
||||
'lib/internal/http2/compat.js',
|
||||
'lib/internal/http2/util.js',
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
// Flags: --expose-internals
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const types = require('internal/util/types');
|
||||
|
||||
const primitive = true;
|
||||
const arrayBuffer = new ArrayBuffer();
|
||||
const dataView = new DataView(arrayBuffer);
|
||||
const int32Array = new Int32Array(arrayBuffer);
|
||||
const uint8Array = new Uint8Array(arrayBuffer);
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
|
||||
const fakeDataView = Object.create(DataView.prototype);
|
||||
const fakeInt32Array = Object.create(Int32Array.prototype);
|
||||
const fakeUint8Array = Object.create(Uint8Array.prototype);
|
||||
const fakeBuffer = Object.create(Buffer.prototype);
|
||||
|
||||
const stealthyDataView =
|
||||
Object.setPrototypeOf(new DataView(arrayBuffer), Uint8Array.prototype);
|
||||
const stealthyInt32Array =
|
||||
Object.setPrototypeOf(new Int32Array(arrayBuffer), uint8Array);
|
||||
const stealthyUint8Array =
|
||||
Object.setPrototypeOf(new Uint8Array(arrayBuffer), ArrayBuffer.prototype);
|
||||
|
||||
const all = [
|
||||
primitive, arrayBuffer, dataView, int32Array, uint8Array, buffer,
|
||||
fakeDataView, fakeInt32Array, fakeUint8Array, fakeBuffer,
|
||||
stealthyDataView, stealthyInt32Array, stealthyUint8Array
|
||||
];
|
||||
|
||||
const expected = {
|
||||
isArrayBufferView: [
|
||||
dataView, int32Array, uint8Array, buffer,
|
||||
stealthyDataView, stealthyInt32Array, stealthyUint8Array
|
||||
],
|
||||
isTypedArray: [
|
||||
int32Array, uint8Array, buffer, stealthyInt32Array, stealthyUint8Array
|
||||
],
|
||||
isUint8Array: [
|
||||
uint8Array, buffer, stealthyUint8Array
|
||||
]
|
||||
};
|
||||
|
||||
for (const testedFunc of Object.keys(expected)) {
|
||||
const func = types[testedFunc];
|
||||
const yup = [];
|
||||
for (const value of all) {
|
||||
if (func(value)) {
|
||||
yup.push(value);
|
||||
}
|
||||
}
|
||||
console.log('Testing', testedFunc);
|
||||
assert.deepStrictEqual(yup, expected[testedFunc]);
|
||||
}
|
||||
Reference in new issue
Block a user