Skip to content

Commit e476412

Browse files
committed
fix: improve ArrayBuffer brand check in ensureBuffer
`instanceof` is notoriously unreliable in JS, because it can be fooled by prototype manipulation and breaks down entirely for cross-realm brand checks. Using `Object.prototype.toString` is generally a better choice for this. This also adds `SharedArrayBuffer` as an alternative, as both should be treated the same under most circumstances.
1 parent f60c404 commit e476412

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/ensure_buffer.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ export function ensureBuffer(potentialBuffer: Buffer | ArrayBufferView | ArrayBu
1818
return Buffer.from(potentialBuffer.buffer);
1919
}
2020

21-
if (potentialBuffer instanceof ArrayBuffer) {
21+
if ([
22+
'[object ArrayBuffer]', '[object SharedArrayBuffer]'
23+
].includes(Object.prototype.toString.call(potentialBuffer))) {
2224
return Buffer.from(potentialBuffer);
2325
}
2426

test/node/ensure_buffer_test.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe('ensureBuffer tests', function () {
1919
expect(bufferOut).to.equal(bufferIn);
2020
});
2121

22-
it('should wrap a UInt8Array with a buffer', function () {
22+
it('should wrap a Uint8Array with a buffer', function () {
2323
const arrayIn = Uint8Array.from([1, 2, 3]);
2424
let bufferOut;
2525

@@ -31,6 +31,34 @@ describe('ensureBuffer tests', function () {
3131
expect(bufferOut.buffer).to.equal(arrayIn.buffer);
3232
});
3333

34+
it('should wrap a ArrayBuffer with a buffer', function () {
35+
const arrayBufferIn = Uint8Array.from([1, 2, 3]).buffer;
36+
let bufferOut;
37+
38+
expect(function () {
39+
bufferOut = ensureBuffer(arrayBufferIn);
40+
}).to.not.throw(Error);
41+
42+
expect(bufferOut).to.be.an.instanceOf(Buffer);
43+
expect(bufferOut.buffer).to.equal(arrayBufferIn);
44+
});
45+
46+
it('should wrap a SharedArrayBuffer with a buffer', function () {
47+
if (typeof SharedArrayBuffer === 'undefined') {
48+
this.skip();
49+
return;
50+
}
51+
const arrayBufferIn = new SharedArrayBuffer(3);
52+
let bufferOut;
53+
54+
expect(function () {
55+
bufferOut = ensureBuffer(arrayBufferIn);
56+
}).to.not.throw(Error);
57+
58+
expect(bufferOut).to.be.an.instanceOf(Buffer);
59+
expect(bufferOut.buffer).to.equal(arrayBufferIn);
60+
});
61+
3462
[0, 12, -1, '', 'foo', null, undefined, ['list'], {}, /x/].forEach(function (item) {
3563
it(`should throw if input is ${typeof item}: ${item}`, function () {
3664
expect(function () {

0 commit comments

Comments
 (0)