Skip to content

Commit 82ef078

Browse files
committed
v8: serialize BigInt64Array and BigUint64Array
Teach the serializer about BigInt64Array and BigUint64Array. I open-coded the type-to-index mapper to stay compatible with the current wire format without undue code gymnastics.
1 parent 3507b3f commit 82ef078

File tree

2 files changed

+54
-31
lines changed

2 files changed

+54
-31
lines changed

lib/v8.js

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ const {
1919
ArrayBuffer,
2020
ArrayPrototypeForEach,
2121
ArrayPrototypePush,
22+
BigInt64Array,
23+
BigUint64Array,
2224
DataView,
2325
Error,
2426
Float32Array,
@@ -27,7 +29,6 @@ const {
2729
Int32Array,
2830
Int8Array,
2931
ObjectPrototypeToString,
30-
SafeMap,
3132
Uint16Array,
3233
Uint32Array,
3334
Uint8Array,
@@ -247,29 +248,40 @@ Deserializer.prototype.readRawBytes = function readRawBytes(length) {
247248
length);
248249
};
249250

250-
/* Keep track of how to handle different ArrayBufferViews.
251-
* The default Serializer for Node does not use the V8 methods for serializing
252-
* those objects because Node's `Buffer` objects use pooled allocation in many
253-
* cases, and their underlying `ArrayBuffer`s would show up in the
254-
* serialization. Because a) those may contain sensitive data and the user
255-
* may not be aware of that and b) they are often much larger than the `Buffer`
256-
* itself, custom serialization is applied. */
257-
const arrayBufferViewTypes = [Int8Array, Uint8Array, Uint8ClampedArray,
258-
Int16Array, Uint16Array, Int32Array, Uint32Array,
259-
Float32Array, Float64Array, DataView];
260-
261-
const arrayBufferViewTypeToIndex = new SafeMap();
262-
263-
{
264-
const dummy = new ArrayBuffer();
265-
ArrayPrototypeForEach(arrayBufferViewTypes, (ctor, i) => {
266-
const tag = ObjectPrototypeToString(new ctor(dummy));
267-
arrayBufferViewTypeToIndex.set(tag, i);
268-
});
251+
function arrayBufferViewTypeToIndex(abView) {
252+
const type = ObjectPrototypeToString(abView);
253+
if (type === '[object Int8Array]') return 0;
254+
if (type === '[object Uint8Array]') return 1;
255+
if (type === '[object Uint8ClampedArray]') return 2;
256+
if (type === '[object Int16Array]') return 3;
257+
if (type === '[object Uint16Array]') return 4;
258+
if (type === '[object Int32Array]') return 5;
259+
if (type === '[object Uint32Array]') return 6;
260+
if (type === '[object Float32Array]') return 7;
261+
if (type === '[object Float64Array]') return 8;
262+
if (type === '[object DataView]') return 9;
263+
// Index 10 is FastBuffer.
264+
if (type === '[object BigInt64Array]') return 11;
265+
if (type === '[object BigUint64Array]') return 12;
266+
return -1;
269267
}
270268

271-
const bufferConstructorIndex =
272-
ArrayPrototypePush(arrayBufferViewTypes, FastBuffer) - 1;
269+
function arrayBufferViewIndexToType(index) {
270+
if (index === 0) return Int8Array;
271+
if (index === 1) return Uint8Array;
272+
if (index === 2) return Uint8ClampedArray;
273+
if (index === 3) return Int16Array;
274+
if (index === 4) return Uint16Array;
275+
if (index === 5) return Int32Array;
276+
if (index === 6) return Uint32Array;
277+
if (index === 7) return Float32Array;
278+
if (index === 8) return Float64Array;
279+
if (index === 9) return DataView;
280+
if (index === 10) return FastBuffer;
281+
if (index === 11) return BigInt64Array;
282+
if (index === 12) return BigUint64Array;
283+
return undefined;
284+
}
273285

274286
class DefaultSerializer extends Serializer {
275287
constructor() {
@@ -285,14 +297,17 @@ class DefaultSerializer extends Serializer {
285297
* @returns {void}
286298
*/
287299
_writeHostObject(abView) {
288-
let i = 0;
289-
if (abView.constructor === Buffer) {
290-
i = bufferConstructorIndex;
291-
} else {
292-
const tag = ObjectPrototypeToString(abView);
293-
i = arrayBufferViewTypeToIndex.get(tag);
294-
295-
if (i === undefined) {
300+
// Keep track of how to handle different ArrayBufferViews. The default
301+
// Serializer for Node does not use the V8 methods for serializing those
302+
// objects because Node's `Buffer` objects use pooled allocation in many
303+
// cases, and their underlying `ArrayBuffer`s would show up in the
304+
// serialization. Because a) those may contain sensitive data and the user
305+
// may not be aware of that and b) they are often much larger than the
306+
// `Buffer` itself, custom serialization is applied.
307+
let i = 10; // FastBuffer
308+
if (abView.constructor !== Buffer) {
309+
i = arrayBufferViewTypeToIndex(abView);
310+
if (i === -1) {
296311
throw new this._getDataCloneError(
297312
`Unserializable host object: ${inspect(abView)}`);
298313
}
@@ -313,7 +328,7 @@ class DefaultDeserializer extends Deserializer {
313328
*/
314329
_readHostObject() {
315330
const typeIndex = this.readUint32();
316-
const ctor = arrayBufferViewTypes[typeIndex];
331+
const ctor = arrayBufferViewIndexToType(typeIndex);
317332
const byteLength = this.readUint32();
318333
const byteOffset = this._readRawBytes(byteLength);
319334
const BYTES_PER_ELEMENT = ctor.BYTES_PER_ELEMENT || 1;

test/parallel/test-v8-serdes.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,18 @@ circular.circular = circular;
1414
const objects = [
1515
{ foo: 'bar' },
1616
{ bar: 'baz' },
17+
new Int8Array([1, 2, 3, 4]),
1718
new Uint8Array([1, 2, 3, 4]),
19+
new Int16Array([1, 2, 3, 4]),
20+
new Uint16Array([1, 2, 3, 4]),
21+
new Int32Array([1, 2, 3, 4]),
1822
new Uint32Array([1, 2, 3, 4]),
23+
new Float32Array([1, 2, 3, 4]),
24+
new Float64Array([1, 2, 3, 4]),
1925
new DataView(new ArrayBuffer(42)),
2026
Buffer.from([1, 2, 3, 4]),
27+
new BigInt64Array([42n]),
28+
new BigUint64Array([42n]),
2129
undefined,
2230
null,
2331
42,

0 commit comments

Comments
 (0)