From 293fd0453591ef0d87437a265ff515916d35d715 Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Tue, 16 Feb 2016 11:08:49 +0800 Subject: [PATCH] buffer: make byteLength work with ArrayBuffer & DataView Convert anything to string, but Buffer, TypedArray and ArrayBuffer ``` var uint8 = new Uint8Array([0xf0, 0x9f, 0x90]); Buffer.byteLength(uint8); // should be 3, but returns 11 Buffer.byteLength(uint8.buffer); // should be 3, but return 20 ``` PR-URL: https://github.com/nodejs/node/pull/5255 Reviewed-By: Ben Noordhuis Reviewed-By: Trevor Norris Reviewed-By: James M Snell --- doc/api/buffer.markdown | 9 ++++++- lib/buffer.js | 7 ++--- test/parallel/test-buffer-bytelength.js | 34 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/doc/api/buffer.markdown b/doc/api/buffer.markdown index a2462e1bc4cb2f..21ebf8df157a15 100644 --- a/doc/api/buffer.markdown +++ b/doc/api/buffer.markdown @@ -468,7 +468,7 @@ additional performance that `Buffer.allocUnsafe(size)` provides. ### Class Method: Buffer.byteLength(string[, encoding]) -* `string` {String} +* `string` {String | Buffer | TypedArray | DataView | ArrayBuffer} * `encoding` {String} Default: `'utf8'` * Return: {Number} @@ -487,6 +487,11 @@ console.log(`${str}: ${str.length} characters, ` + // ½ + ¼ = ¾: 9 characters, 12 bytes ``` +When `string` is a `Buffer`/[`DataView`][]/[`TypedArray`][]/`ArrayBuffer`, +returns the actual byte length. + +Otherwise, converts to `String` and returns the byte length of string. + ### Class Method: Buffer.compare(buf1, buf2) * `buf1` {Buffer} @@ -1765,3 +1770,5 @@ console.log(buf); [buffer_allocunsafe]: #buffer_class_method_buffer_allocraw_size [buffer_alloc]: #buffer_class_method_buffer_alloc_size_fill_encoding [`TypedArray.from()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/from +[`DataView`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView +[`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray diff --git a/lib/buffer.js b/lib/buffer.js index a83361cc9b1d9b..7150debf357dac 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -364,11 +364,12 @@ function base64ByteLength(str, bytes) { function byteLength(string, encoding) { - if (string instanceof Buffer) - return string.length; + if (typeof string !== 'string') { + if (ArrayBuffer.isView(string) || string instanceof ArrayBuffer) + return string.byteLength; - if (typeof string !== 'string') string = '' + string; + } var len = string.length; if (len === 0) diff --git a/test/parallel/test-buffer-bytelength.js b/test/parallel/test-buffer-bytelength.js index aaffc36bd2eff1..01bf12e544908e 100644 --- a/test/parallel/test-buffer-bytelength.js +++ b/test/parallel/test-buffer-bytelength.js @@ -3,6 +3,7 @@ require('../common'); var assert = require('assert'); var Buffer = require('buffer').Buffer; +var SlowBuffer = require('buffer').SlowBuffer; // coerce values to string assert.equal(Buffer.byteLength(32, 'binary'), 2); @@ -10,12 +11,45 @@ assert.equal(Buffer.byteLength(NaN, 'utf8'), 3); assert.equal(Buffer.byteLength({}, 'binary'), 15); assert.equal(Buffer.byteLength(), 9); +var buff = new Buffer(10); +assert(ArrayBuffer.isView(buff)); +var slowbuff = new SlowBuffer(10); +assert(ArrayBuffer.isView(slowbuff)); + // buffer var incomplete = Buffer.from([0xe4, 0xb8, 0xad, 0xe6, 0x96]); assert.equal(Buffer.byteLength(incomplete), 5); var ascii = Buffer.from('abc'); assert.equal(Buffer.byteLength(ascii), 3); +// ArrayBuffer +var buffer = new ArrayBuffer(8); +assert.equal(Buffer.byteLength(buffer), 8); + +// TypedArray +var int8 = new Int8Array(8); +assert.equal(Buffer.byteLength(int8), 8); +var uint8 = new Uint8Array(8); +assert.equal(Buffer.byteLength(uint8), 8); +var uintc8 = new Uint8ClampedArray(2); +assert.equal(Buffer.byteLength(uintc8), 2); +var int16 = new Int16Array(8); +assert.equal(Buffer.byteLength(int16), 16); +var uint16 = new Uint16Array(8); +assert.equal(Buffer.byteLength(uint16), 16); +var int32 = new Int32Array(8); +assert.equal(Buffer.byteLength(int32), 32); +var uint32 = new Uint32Array(8); +assert.equal(Buffer.byteLength(uint32), 32); +var float32 = new Float32Array(8); +assert.equal(Buffer.byteLength(float32), 32); +var float64 = new Float64Array(8); +assert.equal(Buffer.byteLength(float64), 64); + +// DataView +var dv = new DataView(new ArrayBuffer(2)); +assert.equal(Buffer.byteLength(dv), 2); + // special case: zero length string assert.equal(Buffer.byteLength('', 'ascii'), 0); assert.equal(Buffer.byteLength('', 'HeX'), 0);