node/test/parallel/test-buffer-from.js
Ali Hassan 9e0dc8b472
buffer: improve performance of multiple Buffer operations
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions

PR-URL: https://github.com/nodejs/node/pull/61871
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-03-27 21:50:58 +00:00

183 lines
4.3 KiB
JavaScript

'use strict';
const common = require('../common');
const assert = require('assert');
const { runInNewContext } = require('vm');
const checkString = 'test';
const check = Buffer.from(checkString);
class MyString extends String {
constructor() {
super(checkString);
}
}
class MyPrimitive {
[Symbol.toPrimitive]() {
return checkString;
}
}
class MyBadPrimitive {
[Symbol.toPrimitive]() {
return 1;
}
}
assert.deepStrictEqual(Buffer.from(new String(checkString)), check);
assert.deepStrictEqual(Buffer.from(new MyString()), check);
assert.deepStrictEqual(Buffer.from(new MyPrimitive()), check);
assert.deepStrictEqual(
Buffer.from(runInNewContext('new String(checkString)', { checkString })),
check
);
[
{},
new Boolean(true),
{ valueOf() { return null; } },
{ valueOf() { return undefined; } },
{ valueOf: null },
{ __proto__: null },
new Number(true),
new MyBadPrimitive(),
Symbol(),
5n,
(one, two, three) => {},
undefined,
null,
].forEach((input) => {
const errObj = {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The first argument must be of type string or an instance of ' +
'Buffer, ArrayBuffer, or Array or an Array-like Object.' +
common.invalidArgTypeHelper(input)
};
assert.throws(() => Buffer.from(input), errObj);
assert.throws(() => Buffer.from(input, 'hex'), errObj);
});
Buffer.allocUnsafe(10); // Should not throw.
Buffer.from('deadbeaf', 'hex'); // Should not throw.
{
const u16 = new Uint16Array([0xffff]);
const b16 = Buffer.copyBytesFrom(u16);
u16[0] = 0;
assert.strictEqual(b16.length, 2);
assert.strictEqual(b16[0], 255);
assert.strictEqual(b16[1], 255);
}
{
const u16 = new Uint16Array([0, 0xffff]);
const b16 = Buffer.copyBytesFrom(u16, 1, 5);
u16[0] = 0xffff;
u16[1] = 0;
assert.strictEqual(b16.length, 2);
assert.strictEqual(b16[0], 255);
assert.strictEqual(b16[1], 255);
}
{
const u32 = new Uint32Array([0xffffffff]);
const b32 = Buffer.copyBytesFrom(u32);
u32[0] = 0;
assert.strictEqual(b32.length, 4);
assert.strictEqual(b32[0], 255);
assert.strictEqual(b32[1], 255);
assert.strictEqual(b32[2], 255);
assert.strictEqual(b32[3], 255);
}
assert.throws(() => {
Buffer.copyBytesFrom();
}, {
code: 'ERR_INVALID_ARG_TYPE',
});
['', Symbol(), true, false, {}, [], () => {}, 1, 1n, null, undefined].forEach(
(notTypedArray) => assert.throws(() => {
Buffer.copyBytesFrom('nope');
}, {
code: 'ERR_INVALID_ARG_TYPE',
})
);
['', Symbol(), true, false, {}, [], () => {}, 1n].forEach((notANumber) =>
assert.throws(() => {
Buffer.copyBytesFrom(new Uint8Array(1), notANumber);
}, {
code: 'ERR_INVALID_ARG_TYPE',
})
);
[-1, NaN, 1.1, -Infinity].forEach((outOfRange) =>
assert.throws(() => {
Buffer.copyBytesFrom(new Uint8Array(1), outOfRange);
}, {
code: 'ERR_OUT_OF_RANGE',
})
);
['', Symbol(), true, false, {}, [], () => {}, 1n].forEach((notANumber) =>
assert.throws(() => {
Buffer.copyBytesFrom(new Uint8Array(1), 0, notANumber);
}, {
code: 'ERR_INVALID_ARG_TYPE',
})
);
[-1, NaN, 1.1, -Infinity].forEach((outOfRange) =>
assert.throws(() => {
Buffer.copyBytesFrom(new Uint8Array(1), 0, outOfRange);
}, {
code: 'ERR_OUT_OF_RANGE',
})
);
// copyBytesFrom: length exceeds view (should clamp, not throw)
{
const u8 = new Uint8Array([1, 2, 3, 4, 5]);
const b = Buffer.copyBytesFrom(u8, 2, 100);
assert.strictEqual(b.length, 3);
assert.deepStrictEqual([...b], [3, 4, 5]);
}
// copyBytesFrom: length 0 returns empty buffer
{
const u8 = new Uint8Array([1, 2, 3]);
const b = Buffer.copyBytesFrom(u8, 1, 0);
assert.strictEqual(b.length, 0);
}
// copyBytesFrom: offset past end returns empty buffer
{
const u8 = new Uint8Array([1, 2, 3]);
const b = Buffer.copyBytesFrom(u8, 10);
assert.strictEqual(b.length, 0);
}
// copyBytesFrom: Float64Array with offset and length
{
const f64 = new Float64Array([1.0, 2.0, 3.0, 4.0]);
const b = Buffer.copyBytesFrom(f64, 1, 2);
assert.strictEqual(b.length, 16);
const view = new Float64Array(b.buffer, b.byteOffset, 2);
assert.strictEqual(view[0], 2.0);
assert.strictEqual(view[1], 3.0);
}
// copyBytesFrom: empty typed array returns empty buffer
{
const empty = new Uint8Array(0);
const b = Buffer.copyBytesFrom(empty);
assert.strictEqual(b.length, 0);
}
// Invalid encoding is allowed
Buffer.from('asd', 1);