diff --git a/lib/buffer.js b/lib/buffer.js index ca4fedf517..3378dcebfc 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -30,7 +30,7 @@ SlowBuffer.prototype.__proto__ = Buffer.prototype; function clamp(index, len, defaultValue) { - if (typeof index === 'undefined') return defaultValue; + if (typeof index !== 'number') return defaultValue; index = ~~index; // Coerce to integer. if (index >= len) return len; if (index >= 0) return index; @@ -49,7 +49,7 @@ function toHex(n) { SlowBuffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); start = +start || 0; - if (typeof end == 'undefined') end = this.length; + if (typeof end !== 'number') end = this.length; // Fastpath empty strings if (+end == start) { @@ -150,15 +150,6 @@ SlowBuffer.prototype.slice = function(start, end) { }; -function coerce(length) { - // Coerce length to a number (possibly NaN), round up - // in case it's fractional (e.g. 123.456). Since NaN - // comparisons are always false, use to return zero. - length = Math.ceil(+length); - return length > 0 ? length : 0; -} - - var zeroBuffer = new SlowBuffer(0); // Buffer @@ -175,22 +166,22 @@ function Buffer(subject, encoding, offset) { throw new TypeError('First argument must be a Buffer when slicing'); } - this.length = coerce(encoding); + this.length = +encoding > 0 ? Math.ceil(encoding) : 0; this.parent = subject.parent ? subject.parent : subject; this.offset = offset; } else { // Find the length switch (type = typeof subject) { case 'number': - this.length = coerce(subject); + this.length = +subject > 0 ? Math.ceil(subject) : 0; break; case 'string': this.length = Buffer.byteLength(subject, encoding); break; - case 'object': // Assume object is an array - this.length = coerce(subject.length); + case 'object': // Assume object is array-ish + this.length = +subject.length > 0 ? Math.ceil(subject.length) : 0; break; default: @@ -217,14 +208,24 @@ function Buffer(subject, encoding, offset) { this.offset = 0; } - // Treat array-ish objects as a byte array. - if (isArrayIsh(subject)) { - for (var i = 0; i < this.length; i++) { - this.parent[i + this.offset] = subject[i]; + // optimize by branching logic for new allocations + if (typeof subject !== 'number') { + if (type === 'string') { + // We are a string + this.length = this.write(subject, 0, encoding); + // if subject is buffer then use built-in copy method + } else if (Buffer.isBuffer(subject)) { + if (subject.parent) + subject.parent.copy(this.parent, + this.offset, + subject.offset, + this.length + subject.offset); + else + subject.copy(this.parent, this.offset, 0, this.length); + } else if (isArrayIsh(subject)) { + for (var i = 0; i < this.length; i++) + this.parent[i + this.offset] = subject[i]; } - } else if (type == 'string') { - // We are a string - this.length = this.write(subject, 0, encoding); } } @@ -232,7 +233,7 @@ function Buffer(subject, encoding, offset) { } function isArrayIsh(subject) { - return Array.isArray(subject) || Buffer.isBuffer(subject) || + return Array.isArray(subject) || subject && typeof subject === 'object' && typeof subject.length === 'number'; } @@ -388,13 +389,13 @@ Buffer.prototype.toJSON = function() { Buffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); - if (typeof start == 'undefined' || start < 0) { + if (typeof start !== 'number' || start < 0) { start = 0; } else if (start > this.length) { start = this.length; } - if (typeof end == 'undefined' || end > this.length) { + if (typeof end !== 'number' || end > this.length) { end = this.length; } else if (end < 0) { end = 0; @@ -445,7 +446,7 @@ Buffer.prototype.fill = function fill(value, start, end) { if (typeof value === 'string') { value = value.charCodeAt(0); } - if (!(typeof value === 'number') || isNaN(value)) { + if (typeof value !== 'number' || isNaN(value)) { throw new TypeError('value is not a number'); }