Skip to content

Commit

Permalink
buffer: add Buffer.fromTypedArray(...)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell committed Feb 4, 2023
1 parent 03854f6 commit c2a8d6f
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
21 changes: 21 additions & 0 deletions doc/api/buffer.md
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,27 @@ console.log(buf1.toString('latin1'));
A `TypeError` will be thrown if `string` is not a string or another type
appropriate for `Buffer.from()` variants.

### Static method: `Buffer.fromTypedArray(typedArray[, offset[, length]])`

<!-- YAML
added: REPLACEME
-->

* `typedArray` {TypedArray} The {TypedArray} to copy
* `offset` {integer} The starting offset within `typedArray`
* `length` {integer} The number of elements from `typedArray` to copy.

Copies the underlying memory of `typedArray` into a new `Buffer`.

```js
const u16 = new Uint16Array([0, 0xffff]);
const buf = Buffer.fromTypedArray(u16, 0, 1);
u16[1] = 0;
console.log(buf.length); // 2
console.log(buf[0]); // 255
console.log(buf[1]); // 255
```

### Static method: `Buffer.isBuffer(obj)`

<!-- YAML
Expand Down
27 changes: 27 additions & 0 deletions lib/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const {
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeFill,
TypedArrayPrototypeSet,
TypedArrayPrototypeSlice,
Uint8Array,
Uint8ArrayPrototype,
} = primordials;
Expand Down Expand Up @@ -330,6 +331,32 @@ Buffer.from = function from(value, encodingOrOffset, length) {
);
};

/**
* Creates the Buffer as a copy of the underlying ArrayBuffer of the TypedArray
* rather than the contents of the TypedArray.
* @param {ArrayBufferView} typedArray
* @param {number} [offset]
* @param {number} [length]
*/
Buffer.fromTypedArray = function fromTypedArray(typedArray, offset, length) {
if (!isArrayBufferView(typedArray)) {
throw new ERR_INVALID_ARG_TYPE('typedArray', 'TypedArray', typedArray);
}
offset ??= 0;
length ??= typedArray.length;

validateInteger(offset, 'offset', 0);
validateInteger(length, 'length', 0);

offset = MathMin(offset, typedArray.length);
length = MathMin(length, typedArray.length);

typedArray = TypedArrayPrototypeSlice(typedArray, offset, offset + length);

return fromArrayLike(
new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength));
};

// Identical to the built-in %TypedArray%.of(), but avoids using the deprecated
// Buffer() constructor. Must use arrow function syntax to avoid automatically
// adding a `prototype` property and making the function a constructor.
Expand Down
45 changes: 44 additions & 1 deletion test/parallel/test-buffer-from.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const common = require('../common');
const { deepStrictEqual, throws } = require('assert');
const { deepStrictEqual, strictEqual, throws } = require('assert');
const { runInNewContext } = require('vm');

const checkString = 'test';
Expand Down Expand Up @@ -62,3 +62,46 @@ deepStrictEqual(

Buffer.allocUnsafe(10); // Should not throw.
Buffer.from('deadbeaf', 'hex'); // Should not throw.


{
const u16 = new Uint16Array([0xffff]);
const b16 = Buffer.fromTypedArray(u16);
u16[0] = 0;
strictEqual(b16.length, 2);
strictEqual(b16[0], 255);
strictEqual(b16[1], 255);
}

{
const u16 = new Uint16Array([0, 0xffff]);
const b16 = Buffer.fromTypedArray(u16, 1, 5);
u16[0] = 0xffff;
u16[1] = 0;
strictEqual(b16.length, 2);
strictEqual(b16[0], 255);
strictEqual(b16[1], 255);
}

{
const u32 = new Uint32Array([0xffffffff]);
const b32 = Buffer.fromTypedArray(u32);
u32[0] = 0;
strictEqual(b32.length, 4);
strictEqual(b32[0], 255);
strictEqual(b32[1], 255);
strictEqual(b32[2], 255);
strictEqual(b32[3], 255);
}

throws(() => {
Buffer.fromTypedArray('nope');
}, {
code: 'ERR_INVALID_ARG_TYPE',
});

throws(() => {
Buffer.fromTypedArray(new Uint8Array(1), 'a');
}, {
code: 'ERR_INVALID_ARG_TYPE',
});

0 comments on commit c2a8d6f

Please sign in to comment.