buffer: allow Uint8Array input to methods

Allow all methods on `buffer` and `Buffer` to take `Uint8Array`
arguments where it makes sense. On the native side, there is
effectively no difference, and as a bonus the `isUint8Array`
check is faster than `instanceof Buffer`.

PR-URL: https://github.com/nodejs/node/pull/10236
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com>
This commit is contained in:
Anna Henningsen 2016-12-10 22:28:37 +01:00
parent 6cb33c0764
commit beca3244e2
No known key found for this signature in database
GPG key ID: D8B9F5AEAE84E4CF
10 changed files with 81 additions and 45 deletions

View file

@ -2,7 +2,8 @@
'use strict';
const binding = process.binding('buffer');
const { isArrayBuffer, isSharedArrayBuffer } = process.binding('util');
const { isArrayBuffer, isSharedArrayBuffer, isUint8Array } =
process.binding('util');
const bindingObj = {};
const internalUtil = require('internal/util');
@ -251,13 +252,13 @@ function fromArrayBuffer(obj, byteOffset, length) {
}
function fromObject(obj) {
if (obj instanceof Buffer) {
if (isUint8Array(obj)) {
const b = allocate(obj.length);
if (b.length === 0)
return b;
obj.copy(b, 0, 0, obj.length);
binding.copy(obj, b, 0, 0, obj.length);
return b;
}
@ -287,9 +288,8 @@ Buffer.isBuffer = function isBuffer(b) {
Buffer.compare = function compare(a, b) {
if (!(a instanceof Buffer) ||
!(b instanceof Buffer)) {
throw new TypeError('Arguments must be Buffers');
if (!isUint8Array(a) || !isUint8Array(b)) {
throw new TypeError('Arguments must be Buffers or Uint8Arrays');
}
if (a === b) {
@ -306,10 +306,13 @@ Buffer.isEncoding = function(encoding) {
};
Buffer[internalUtil.kIsEncodingSymbol] = Buffer.isEncoding;
const kConcatErrMsg = '"list" argument must be an Array ' +
'of Buffer or Uint8Array instances';
Buffer.concat = function(list, length) {
var i;
if (!Array.isArray(list))
throw new TypeError('"list" argument must be an Array of Buffers');
throw new TypeError(kConcatErrMsg);
if (list.length === 0)
return new FastBuffer();
@ -326,9 +329,9 @@ Buffer.concat = function(list, length) {
var pos = 0;
for (i = 0; i < list.length; i++) {
var buf = list[i];
if (!Buffer.isBuffer(buf))
throw new TypeError('"list" argument must be an Array of Buffers');
buf.copy(buffer, pos);
if (!isUint8Array(buf))
throw new TypeError(kConcatErrMsg);
binding.copy(buf, buffer, pos);
pos += buf.length;
}
@ -495,6 +498,9 @@ function slowToString(encoding, start, end) {
}
}
Buffer.prototype.copy = function(target, targetStart, sourceStart, sourceEnd) {
return binding.copy(this, target, targetStart, sourceStart, sourceEnd);
};
Buffer.prototype.toString = function() {
let result;
@ -510,8 +516,8 @@ Buffer.prototype.toString = function() {
Buffer.prototype.equals = function equals(b) {
if (!(b instanceof Buffer))
throw new TypeError('Argument must be a Buffer');
if (!isUint8Array(b))
throw new TypeError('Argument must be a Buffer or Uint8Array');
if (this === b)
return true;
@ -539,8 +545,8 @@ Buffer.prototype.compare = function compare(target,
thisStart,
thisEnd) {
if (!(target instanceof Buffer))
throw new TypeError('Argument must be a Buffer');
if (!isUint8Array(target))
throw new TypeError('Argument must be a Buffer or Uint8Array');
if (start === undefined)
start = 0;
@ -604,13 +610,14 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
return binding.indexOfString(buffer, val, byteOffset, encoding, dir);
}
return slowIndexOf(buffer, val, byteOffset, encoding, dir);
} else if (val instanceof Buffer) {
} else if (isUint8Array(val)) {
return binding.indexOfBuffer(buffer, val, byteOffset, encoding, dir);
} else if (typeof val === 'number') {
return binding.indexOfNumber(buffer, val, byteOffset, dir);
}
throw new TypeError('"val" argument must be string, number or Buffer');
throw new TypeError('"val" argument must be string, number, Buffer ' +
'or Uint8Array');
}
@ -1037,8 +1044,8 @@ Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) {
function checkInt(buffer, value, offset, ext, max, min) {
if (!(buffer instanceof Buffer))
throw new TypeError('"buffer" argument must be a Buffer instance');
if (!isUint8Array(buffer))
throw new TypeError('"buffer" argument must be a Buffer or Uint8Array');
if (value > max || value < min)
throw new TypeError('"value" argument is out of bounds');
if (offset + ext > buffer.length)