diff options
Diffstat (limited to 'lib/buffer.js')
-rw-r--r-- | lib/buffer.js | 138 |
1 files changed, 104 insertions, 34 deletions
diff --git a/lib/buffer.js b/lib/buffer.js index 766a82c2f2..01a8f303e1 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -9,6 +9,8 @@ exports.SlowBuffer = SlowBuffer; exports.INSPECT_MAX_BYTES = 50; exports.kMaxLength = binding.kMaxLength; +const kFromErrorMsg = 'First argument must be a string, Buffer, ' + + 'ArrayBuffer, Array, or array-like object.'; Buffer.poolSize = 8 * 1024; var poolSize, poolOffset, allocPool; @@ -42,34 +44,90 @@ function alignPool() { } } - -function Buffer(arg, encoding) { +/** + * The Buffer() construtor is "soft deprecated" ... that is, it is deprecated + * in the documentation and should not be used moving forward. Rather, + * developers should use one of the three new factory APIs: Buffer.from(), + * Buffer.allocUnsafe() or Buffer.alloc() based on their specific needs. There + * is no hard deprecation because of the extent to which the Buffer constructor + * is used in the ecosystem currently -- a hard deprecation would introduce too + * much breakage at this time. It's not likely that the Buffer constructors + * would ever actually be removed. + **/ +function Buffer(arg, encodingOrOffset, length) { // Common case. if (typeof arg === 'number') { - if (typeof encoding === 'string') { + if (typeof encodingOrOffset === 'string') { throw new Error( 'If encoding is specified then the first argument must be a string' ); } - // If less than zero, or NaN. - if (arg < 0 || arg !== arg) - arg = 0; - return allocate(arg); - } - - // Slightly less common case. - if (typeof arg === 'string') { - return fromString(arg, encoding); + return Buffer.allocUnsafe(arg); } - - // Unusual. - return fromObject(arg); + return Buffer.from(arg, encodingOrOffset, length); } +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function(value, encodingOrOffset, length) { + if (typeof value === 'number') + throw new TypeError('"value" argument must not be a number'); + + if (value instanceof ArrayBuffer) + return fromArrayBuffer(value, encodingOrOffset, length); + + if (typeof value === 'string') + return fromString(value, encodingOrOffset); + + return fromObject(value); +}; + Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype); Object.setPrototypeOf(Buffer, Uint8Array); +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function(size, fill, encoding) { + if (typeof size !== 'number') + throw new TypeError('"size" argument must be a number'); + if (size <= 0) + return createBuffer(size); + if (fill !== undefined) { + // Since we are filling anyway, don't zero fill initially. + flags[kNoZeroFill] = 1; + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' ? + createBuffer(size).fill(fill, encoding) : + createBuffer(size).fill(fill); + } + flags[kNoZeroFill] = 0; + return createBuffer(size); +}; + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer + * instance. If `--zero-fill-buffers` is set, will zero-fill the buffer. + **/ +Buffer.allocUnsafe = function(size) { + if (typeof size !== 'number') + throw new TypeError('"size" argument must be a number'); + if (size > 0) + flags[kNoZeroFill] = 1; + return allocate(size); +}; +// If --zero-fill-buffers command line argument is set, a zero-filled +// buffer is returned. function SlowBuffer(length) { if (+length != length) length = 0; @@ -108,6 +166,9 @@ function fromString(string, encoding) { if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'; + if (!Buffer.isEncoding(encoding)) + throw new TypeError('"encoding" must be a valid string encoding'); + var length = byteLength(string, encoding); if (length >= (Buffer.poolSize >>> 1)) return binding.createFromString(string, encoding); @@ -129,6 +190,16 @@ function fromArrayLike(obj) { return b; } +function fromArrayBuffer(obj, byteOffset, length) { + byteOffset >>>= 0; + + if (typeof length === 'undefined') + return binding.createFromArrayBuffer(obj, byteOffset); + + length >>>= 0; + return binding.createFromArrayBuffer(obj, byteOffset, length); +} + function fromObject(obj) { if (obj instanceof Buffer) { const b = allocate(obj.length); @@ -140,26 +211,20 @@ function fromObject(obj) { return b; } - if (obj == null) { - throw new TypeError('Must start with number, buffer, array or string'); - } - - if (obj instanceof ArrayBuffer) { - return binding.createFromArrayBuffer(obj); - } - - if (obj.buffer instanceof ArrayBuffer || 'length' in obj) { - if (typeof obj.length !== 'number' || obj.length !== obj.length) { - return allocate(0); + if (obj) { + if (obj.buffer instanceof ArrayBuffer || 'length' in obj) { + if (typeof obj.length !== 'number' || obj.length !== obj.length) { + return allocate(0); + } + return fromArrayLike(obj); } - return fromArrayLike(obj); - } - if (obj.type === 'Buffer' && Array.isArray(obj.data)) { - return fromArrayLike(obj.data); + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data); + } } - throw new TypeError('Must start with number, buffer, array or string'); + throw new TypeError(kFromErrorMsg); } @@ -215,7 +280,7 @@ Buffer.concat = function(list, length) { throw new TypeError('"list" argument must be an Array of Buffers'); if (list.length === 0) - return new Buffer(0); + return Buffer.alloc(0); if (length === undefined) { length = 0; @@ -225,7 +290,7 @@ Buffer.concat = function(list, length) { length = length >>> 0; } - var buffer = new Buffer(length); + var buffer = Buffer.allocUnsafe(length); var pos = 0; for (let i = 0; i < list.length; i++) { var buf = list[i]; @@ -454,7 +519,7 @@ function slowIndexOf(buffer, val, byteOffset, encoding) { case 'ascii': case 'hex': return binding.indexOfBuffer( - buffer, Buffer(val, encoding), byteOffset, encoding); + buffer, Buffer.from(val, encoding), byteOffset, encoding); default: if (loweredCase) { @@ -518,6 +583,11 @@ Buffer.prototype.fill = function fill(val, start, end, encoding) { if (code < 256) val = code; } + if (val.length === 0) { + // Previously, if val === '', the Buffer would not fill, + // which is rather surprising. + val = 0; + } if (encoding !== undefined && typeof encoding !== 'string') { throw new TypeError('encoding must be a string'); } |