summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTimothy Gu <timothygu99@gmail.com>2017-09-28 00:16:41 -0700
committerRuben Bridgewater <ruben@bridgewater.de>2017-10-01 23:58:59 -0300
commit7907534a8d867132957b823db8603a418d763e42 (patch)
treed3e5d17179fc7cca5364b2a25e193b28b0234b3e /lib
parent34dbc9e4e8725d5ff28be918a2cb608ff0668e16 (diff)
downloadandroid-node-v8-7907534a8d867132957b823db8603a418d763e42.tar.gz
android-node-v8-7907534a8d867132957b823db8603a418d763e42.tar.bz2
android-node-v8-7907534a8d867132957b823db8603a418d763e42.zip
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>
Diffstat (limited to 'lib')
-rw-r--r--lib/_tls_common.js3
-rw-r--r--lib/assert.js5
-rw-r--r--lib/buffer.js11
-rw-r--r--lib/child_process.js2
-rw-r--r--lib/dgram.js2
-rw-r--r--lib/fs.js3
-rw-r--r--lib/internal/child_process.js2
-rw-r--r--lib/internal/crypto/diffiehellman.js3
-rw-r--r--lib/internal/crypto/hash.js5
-rw-r--r--lib/internal/crypto/random.js2
-rw-r--r--lib/internal/encoding.js6
-rw-r--r--lib/internal/http2/core.js3
-rw-r--r--lib/internal/util/types.js36
-rw-r--r--lib/repl.js3
-rw-r--r--lib/stream.js12
-rw-r--r--lib/tls.js2
-rw-r--r--lib/util.js5
-rw-r--r--lib/zlib.js7
18 files changed, 82 insertions, 30 deletions
diff --git a/lib/_tls_common.js b/lib/_tls_common.js
index fa31fd7de6..54b27a7bca 100644
--- a/lib/_tls_common.js
+++ b/lib/_tls_common.js
@@ -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']
diff --git a/lib/assert.js b/lib/assert.js
index 2aaf80eecc..a29408f47e 100644
--- a/lib/assert.js
+++ b/lib/assert.js
@@ -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);
diff --git a/lib/buffer.js b/lib/buffer.js
index 7a44ca0f26..6a176756c0 100644
--- a/lib/buffer.js
+++ b/lib/buffer.js
@@ -46,16 +46,17 @@ 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');
const errors = require('internal/errors');
@@ -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;
}
diff --git a/lib/child_process.js b/lib/child_process.js
index b2679c5f50..a3cdadd0bc 100644
--- a/lib/child_process.js
+++ b/lib/child_process.js
@@ -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');
diff --git a/lib/dgram.js b/lib/dgram.js
index 85e5f909c0..f33e872e64 100644
--- a/lib/dgram.js
+++ b/lib/dgram.js
@@ -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;
diff --git a/lib/fs.js b/lib/fs.js
index 24af0e58a3..5521094431 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -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;
diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js
index 6613c72a5c..28ab13cd54 100644
--- a/lib/internal/child_process.js
+++ b/lib/internal/child_process.js
@@ -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 {
diff --git a/lib/internal/crypto/diffiehellman.js b/lib/internal/crypto/diffiehellman.js
index 8466df2f79..95b689df94 100644
--- a/lib/internal/crypto/diffiehellman.js
+++ b/lib/internal/crypto/diffiehellman.js
@@ -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']);
diff --git a/lib/internal/crypto/hash.js b/lib/internal/crypto/hash.js
index 12b3e1e78e..952cc34d21 100644
--- a/lib/internal/crypto/hash.js
+++ b/lib/internal/crypto/hash.js
@@ -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');
diff --git a/lib/internal/crypto/random.js b/lib/internal/crypto/random.js
index 81025289d5..ee510ddf06 100644
--- a/lib/internal/crypto/random.js
+++ b/lib/internal/crypto/random.js
@@ -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
diff --git a/lib/internal/encoding.js b/lib/internal/encoding.js
index de4ebcf196..5c2e207258 100644
--- a/lib/internal/encoding.js
+++ b/lib/internal/encoding.js
@@ -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 {
diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js
index 78a4896ab7..56b99cd701 100644
--- a/lib/internal/http2/core.js
+++ b/lib/internal/http2/core.js
@@ -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');
diff --git a/lib/internal/util/types.js b/lib/internal/util/types.js
new file mode 100644
index 0000000000..c990bea6db
--- /dev/null
+++ b/lib/internal/util/types.js
@@ -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
+};
diff --git a/lib/repl.js b/lib/repl.js
index bc9b17de72..b032521993 100644
--- a/lib/repl.js
+++ b/lib/repl.js
@@ -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;
}
diff --git a/lib/stream.js b/lib/stream.js
index 9c1ba986d0..0dd44e3a61 100644
--- a/lib/stream.js
+++ b/lib/stream.js
@@ -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) {
diff --git a/lib/tls.js b/lib/tls.js
index 6c6e4b0918..2d1c539532 100644
--- a/lib/tls.js
+++ b/lib/tls.js
@@ -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
diff --git a/lib/util.js b/lib/util.js
index 590a3b4903..365a15fc9c 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -38,7 +38,6 @@ const {
isPromise,
isSet,
isSetIterator,
- isTypedArray,
isRegExp,
isDate,
kPending,
@@ -46,6 +45,10 @@ const {
} = process.binding('util');
const {
+ isTypedArray
+} = require('internal/util/types');
+
+const {
customInspectSymbol,
deprecate,
getConstructorOf,
diff --git a/lib/zlib.js b/lib/zlib.js
index 35d998df26..49cf8f0315 100644
--- a/lib/zlib.js
+++ b/lib/zlib.js
@@ -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');
}