diff --git a/lib/buffer.js b/lib/buffer.js index 05b57275f03dca..1527e186e7cc8d 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -44,12 +44,7 @@ const { SymbolSpecies, SymbolToPrimitive, TypedArrayPrototypeFill, - TypedArrayPrototypeGetBuffer, - TypedArrayPrototypeGetByteLength, - TypedArrayPrototypeGetByteOffset, - TypedArrayPrototypeGetLength, TypedArrayPrototypeSet, - TypedArrayPrototypeSlice, Uint8Array, Uint8ArrayPrototype, } = primordials; @@ -93,7 +88,6 @@ const { isAnyArrayBuffer, isArrayBufferView, isUint8Array, - isTypedArray, } = require('internal/util/types'); const { inspect: utilInspect, @@ -133,6 +127,15 @@ FastBuffer.prototype.constructor = Buffer; Buffer.prototype = FastBuffer.prototype; addBufferPrototypeMethods(Buffer.prototype); +const BUFFER_NAMES = [ + 'ArrayBuffer', + 'Buffer', + 'TypedArray', + 'DataView', + 'ArrayBuffer', + 'SharedArrayBuffer', +]; + const constants = ObjectDefineProperties({}, { MAX_LENGTH: { __proto__: null, @@ -203,10 +206,13 @@ function toInteger(n, defaultVal) { } function copyImpl(source, target, targetStart, sourceStart, sourceEnd) { - if (!ArrayBufferIsView(source)) - throw new ERR_INVALID_ARG_TYPE('source', ['Buffer', 'Uint8Array'], source); - if (!ArrayBufferIsView(target)) - throw new ERR_INVALID_ARG_TYPE('target', ['Buffer', 'Uint8Array'], target); + if (isArrayBufferView(target)) { + // Do nothing.. + } else if (isAnyArrayBuffer(target)) { + target = new Uint8Array(target); + } else { + throw new ERR_INVALID_ARG_TYPE('target', BUFFER_NAMES, target); + } if (targetStart === undefined) { targetStart = 0; @@ -321,7 +327,7 @@ Buffer.from = function from(value, encodingOrOffset, length) { throw new ERR_INVALID_ARG_TYPE( 'first argument', - ['string', 'Buffer', 'ArrayBuffer', 'Array', 'Array-like Object'], + ['string', 'Array', 'Array-like Object', ...BUFFER_NAMES], value, ); }; @@ -329,17 +335,21 @@ Buffer.from = function from(value, encodingOrOffset, length) { /** * Creates the Buffer as a copy of the underlying ArrayBuffer of the view * rather than the contents of the view. - * @param {TypedArray} view + * @param {Buffer|TypedArray|DataView|ArrayBuffer|SharedArrayBuffer} view * @param {number} [offset] * @param {number} [length] * @returns {Buffer} */ Buffer.copyBytesFrom = function copyBytesFrom(view, offset, length) { - if (!isTypedArray(view)) { - throw new ERR_INVALID_ARG_TYPE('view', [ 'TypedArray' ], view); + if (isArrayBufferView(view)) { + // Do nothing.. + } else if (isAnyArrayBuffer(view)) { + view = new Uint8Array(view); + } else { + throw new ERR_INVALID_ARG_TYPE('view', BUFFER_NAMES, view); } - const viewLength = TypedArrayPrototypeGetLength(view); + const viewLength = view.byteLength; if (viewLength === 0) { return Buffer.alloc(0); } @@ -351,21 +361,17 @@ Buffer.copyBytesFrom = function copyBytesFrom(view, offset, length) { } else { offset = 0; } - let end; if (length !== undefined) { validateInteger(length, 'length', 0); - end = offset + length; } else { - end = viewLength; + length = viewLength - offset; } - - view = TypedArrayPrototypeSlice(view, offset, end); } return fromArrayLike(new Uint8Array( - TypedArrayPrototypeGetBuffer(view), - TypedArrayPrototypeGetByteOffset(view), - TypedArrayPrototypeGetByteLength(view))); + view.buffer, + view.byteOffset + offset, + length)); }; // Identical to the built-in %TypedArray%.of(), but avoids using the deprecated @@ -583,8 +589,8 @@ Buffer.concat = function concat(list, length) { if (length === undefined) { length = 0; for (let i = 0; i < list.length; i++) { - if (list[i].length) { - length += list[i].length; + if (list[i].byteLength) { + length += list[i].byteLength; } } } else { @@ -595,13 +601,13 @@ Buffer.concat = function concat(list, length) { let pos = 0; for (let i = 0; i < list.length; i++) { const buf = list[i]; - if (!isUint8Array(buf)) { + if (!isArrayBufferView(buf) && !isAnyArrayBuffer(buf)) { // TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE. // Instead, find the proper error code for this. throw new ERR_INVALID_ARG_TYPE( - `list[${i}]`, ['Buffer', 'Uint8Array'], list[i]); + `list[${i}]`, BUFFER_NAMES, list[i]); } - pos += _copyActual(buf, buffer, pos, 0, buf.length); + pos += _copyActual(buf, buffer, pos, 0, buf.byteLength); } // Note: `length` is always equal to `buffer.length` at this point @@ -772,10 +778,7 @@ function byteLength(string, encoding) { if (isArrayBufferView(string) || isAnyArrayBuffer(string)) { return string.byteLength; } - - throw new ERR_INVALID_ARG_TYPE( - 'string', ['string', 'Buffer', 'ArrayBuffer'], string, - ); + throw new ERR_INVALID_ARG_TYPE('string', ['string', ...BUFFER_NAMES], string); } const len = string.length; @@ -864,15 +867,18 @@ Buffer.prototype.toString = function toString(encoding, start, end) { }; Buffer.prototype.equals = function equals(otherBuffer) { - if (!isUint8Array(otherBuffer)) { - throw new ERR_INVALID_ARG_TYPE( - 'otherBuffer', ['Buffer', 'Uint8Array'], otherBuffer); + if (isArrayBufferView(otherBuffer)) { + // Do nothing.. + } else if (isAnyArrayBuffer(otherBuffer)) { + otherBuffer = new Uint8Array(otherBuffer); + } else { + throw new ERR_INVALID_ARG_TYPE('otherBuffer', BUFFER_NAMES, otherBuffer); } if (this === otherBuffer) return true; - const len = TypedArrayPrototypeGetByteLength(this); - if (len !== TypedArrayPrototypeGetByteLength(otherBuffer)) + const len = this.byteLength; + if (len !== otherBuffer.byteLength) return false; return len === 0 || _compare(this, otherBuffer) === 0; @@ -919,9 +925,14 @@ Buffer.prototype.compare = function compare(target, targetEnd, sourceStart, sourceEnd) { - if (!isUint8Array(target)) { - throw new ERR_INVALID_ARG_TYPE('target', ['Buffer', 'Uint8Array'], target); + if (isArrayBufferView(target)) { + // Do nothing.. + } else if (isAnyArrayBuffer(target)) { + target = new Uint8Array(target); + } else { + throw new ERR_INVALID_ARG_TYPE('target', BUFFER_NAMES, target); } + if (arguments.length === 1) return _compare(this, target); @@ -997,14 +1008,14 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { return ops.indexOf(buffer, val, byteOffset, dir); } - if (isUint8Array(val)) { + if (isArrayBufferView(val) || isAnyArrayBuffer(val)) { const encodingVal = (ops === undefined ? encodingsMap.utf8 : ops.encodingVal); return indexOfBuffer(buffer, val, byteOffset, encodingVal, dir); } throw new ERR_INVALID_ARG_TYPE( - 'value', ['number', 'string', 'Buffer', 'Uint8Array'], val, + 'value', ['number', 'string', ...BUFFER_NAMES], val, ); } @@ -1081,7 +1092,7 @@ function _fill(buf, value, offset, end, encoding) { if (typeof value === 'number') { // OOB check - const byteLen = TypedArrayPrototypeGetByteLength(buf); + const byteLen = buf.byteLength; const fillLength = end - offset; if (offset > end || fillLength + offset > byteLen) throw new ERR_BUFFER_OUT_OF_BOUNDS(); @@ -1247,9 +1258,8 @@ if (internalBinding('config').hasIntl) { // Transcodes the Buffer from one encoding to another, returning a new // Buffer instance. transcode = function transcode(source, fromEncoding, toEncoding) { - if (!isUint8Array(source)) { - throw new ERR_INVALID_ARG_TYPE('source', - ['Buffer', 'Uint8Array'], source); + if (!ArrayBufferIsView(source) && !isAnyArrayBuffer(source)) { + throw new ERR_INVALID_ARG_TYPE('source', BUFFER_NAMES, source); } if (source.length === 0) return Buffer.alloc(0); @@ -1305,19 +1315,19 @@ function atob(input) { } function isUtf8(input) { - if (isTypedArray(input) || isAnyArrayBuffer(input)) { + if (isArrayBufferView(input) || isAnyArrayBuffer(input)) { return bindingIsUtf8(input); } - throw new ERR_INVALID_ARG_TYPE('input', ['ArrayBuffer', 'Buffer', 'TypedArray'], input); + throw new ERR_INVALID_ARG_TYPE('input', BUFFER_NAMES, input); } function isAscii(input) { - if (isTypedArray(input) || isAnyArrayBuffer(input)) { + if (isArrayBufferView(input) || isAnyArrayBuffer(input)) { return bindingIsAscii(input); } - throw new ERR_INVALID_ARG_TYPE('input', ['ArrayBuffer', 'Buffer', 'TypedArray'], input); + throw new ERR_INVALID_ARG_TYPE('input', BUFFER_NAMES, input); } module.exports = {