Skip to content

Commit 2fece54

Browse files
jasnelltargos
authored andcommitted
buffer: add Buffer.copyBytesFrom(...)
Fixes: #43862 PR-URL: #46500 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent e11f08e commit 2fece54

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed

doc/api/buffer.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,28 @@ console.log(bufA.length);
10581058
`Buffer.concat()` may also use the internal `Buffer` pool like
10591059
[`Buffer.allocUnsafe()`][] does.
10601060

1061+
### Static method: `Buffer.copyBytesFrom(view[, offset[, length]])`
1062+
1063+
<!-- YAML
1064+
added: REPLACEME
1065+
-->
1066+
1067+
* `view` {TypedArray} The {TypedArray} to copy.
1068+
* `offset` {integer} The starting offset within `view`. **Default:**: `0`.
1069+
* `length` {integer} The number of elements from `view` to copy.
1070+
**Default:** `view.length - offset`.
1071+
1072+
Copies the underlying memory of `view` into a new `Buffer`.
1073+
1074+
```js
1075+
const u16 = new Uint16Array([0, 0xffff]);
1076+
const buf = Buffer.copyBytesFrom(u16, 0, 1);
1077+
u16[1] = 0;
1078+
console.log(buf.length); // 2
1079+
console.log(buf[0]); // 255
1080+
console.log(buf[1]); // 255
1081+
```
1082+
10611083
### Static method: `Buffer.from(array)`
10621084

10631085
<!-- YAML

lib/buffer.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ const {
4343
StringPrototypeTrim,
4444
SymbolSpecies,
4545
SymbolToPrimitive,
46+
TypedArrayPrototypeGetBuffer,
4647
TypedArrayPrototypeGetByteLength,
48+
TypedArrayPrototypeGetByteOffset,
4749
TypedArrayPrototypeFill,
50+
TypedArrayPrototypeGetLength,
4851
TypedArrayPrototypeSet,
52+
TypedArrayPrototypeSlice,
4953
Uint8Array,
5054
Uint8ArrayPrototype,
5155
} = primordials;
@@ -330,6 +334,48 @@ Buffer.from = function from(value, encodingOrOffset, length) {
330334
);
331335
};
332336

337+
/**
338+
* Creates the Buffer as a copy of the underlying ArrayBuffer of the view
339+
* rather than the contents of the view.
340+
* @param {TypedArray} view
341+
* @param {number} [offset]
342+
* @param {number} [length]
343+
* @returns {Buffer}
344+
*/
345+
Buffer.copyBytesFrom = function copyBytesFrom(view, offset, length) {
346+
if (!isTypedArray(view)) {
347+
throw new ERR_INVALID_ARG_TYPE('view', [ 'TypedArray' ], view);
348+
}
349+
350+
const viewLength = TypedArrayPrototypeGetLength(view);
351+
if (viewLength === 0) {
352+
return Buffer.alloc(0);
353+
}
354+
355+
if (offset !== undefined || length !== undefined) {
356+
if (offset !== undefined) {
357+
validateInteger(offset, 'offset', 0);
358+
if (offset >= viewLength) return Buffer.alloc(0);
359+
} else {
360+
offset = 0;
361+
}
362+
let end;
363+
if (length !== undefined) {
364+
validateInteger(length, 'length', 0);
365+
end = offset + length;
366+
} else {
367+
end = viewLength;
368+
}
369+
370+
view = TypedArrayPrototypeSlice(view, offset, end);
371+
}
372+
373+
return fromArrayLike(new Uint8Array(
374+
TypedArrayPrototypeGetBuffer(view),
375+
TypedArrayPrototypeGetByteOffset(view),
376+
TypedArrayPrototypeGetByteLength(view)));
377+
};
378+
333379
// Identical to the built-in %TypedArray%.of(), but avoids using the deprecated
334380
// Buffer() constructor. Must use arrow function syntax to avoid automatically
335381
// adding a `prototype` property and making the function a constructor.

test/parallel/test-buffer-from.js

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
const common = require('../common');
4-
const { deepStrictEqual, throws } = require('assert');
4+
const { deepStrictEqual, strictEqual, throws } = require('assert');
55
const { runInNewContext } = require('vm');
66

77
const checkString = 'test';
@@ -62,3 +62,80 @@ deepStrictEqual(
6262

6363
Buffer.allocUnsafe(10); // Should not throw.
6464
Buffer.from('deadbeaf', 'hex'); // Should not throw.
65+
66+
67+
{
68+
const u16 = new Uint16Array([0xffff]);
69+
const b16 = Buffer.copyBytesFrom(u16);
70+
u16[0] = 0;
71+
strictEqual(b16.length, 2);
72+
strictEqual(b16[0], 255);
73+
strictEqual(b16[1], 255);
74+
}
75+
76+
{
77+
const u16 = new Uint16Array([0, 0xffff]);
78+
const b16 = Buffer.copyBytesFrom(u16, 1, 5);
79+
u16[0] = 0xffff;
80+
u16[1] = 0;
81+
strictEqual(b16.length, 2);
82+
strictEqual(b16[0], 255);
83+
strictEqual(b16[1], 255);
84+
}
85+
86+
{
87+
const u32 = new Uint32Array([0xffffffff]);
88+
const b32 = Buffer.copyBytesFrom(u32);
89+
u32[0] = 0;
90+
strictEqual(b32.length, 4);
91+
strictEqual(b32[0], 255);
92+
strictEqual(b32[1], 255);
93+
strictEqual(b32[2], 255);
94+
strictEqual(b32[3], 255);
95+
}
96+
97+
throws(() => {
98+
Buffer.copyBytesFrom();
99+
}, {
100+
code: 'ERR_INVALID_ARG_TYPE',
101+
});
102+
103+
['', Symbol(), true, false, {}, [], () => {}, 1, 1n, null, undefined].forEach(
104+
(notTypedArray) => throws(() => {
105+
Buffer.copyBytesFrom('nope');
106+
}, {
107+
code: 'ERR_INVALID_ARG_TYPE',
108+
})
109+
);
110+
111+
['', Symbol(), true, false, {}, [], () => {}, 1n].forEach((notANumber) =>
112+
throws(() => {
113+
Buffer.copyBytesFrom(new Uint8Array(1), notANumber);
114+
}, {
115+
code: 'ERR_INVALID_ARG_TYPE',
116+
})
117+
);
118+
119+
[-1, NaN, 1.1, -Infinity].forEach((outOfRange) =>
120+
throws(() => {
121+
Buffer.copyBytesFrom(new Uint8Array(1), outOfRange);
122+
}, {
123+
code: 'ERR_OUT_OF_RANGE',
124+
})
125+
);
126+
127+
['', Symbol(), true, false, {}, [], () => {}, 1n].forEach((notANumber) =>
128+
throws(() => {
129+
Buffer.copyBytesFrom(new Uint8Array(1), 0, notANumber);
130+
}, {
131+
code: 'ERR_INVALID_ARG_TYPE',
132+
})
133+
);
134+
135+
[-1, NaN, 1.1, -Infinity].forEach((outOfRange) =>
136+
throws(() => {
137+
Buffer.copyBytesFrom(new Uint8Array(1), 0, outOfRange);
138+
}, {
139+
code: 'ERR_OUT_OF_RANGE',
140+
})
141+
);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy