summaryrefslogtreecommitdiff
path: root/lib/buffer.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/buffer.js')
-rw-r--r--lib/buffer.js138
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');
}