Skip to content

Commit 49cbed6

Browse files
bnoordhuistargos
authored andcommitted
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. PR-URL: #43571 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 3a32f0e commit 49cbed6

File tree

2 files changed

+54
-34
lines changed

2 files changed

+54
-34
lines changed

lib/v8.js

+46-34
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@
1616

1717
const {
1818
Array,
19-
ArrayBuffer,
20-
ArrayPrototypeForEach,
21-
ArrayPrototypePush,
19+
BigInt64Array,
20+
BigUint64Array,
2221
DataView,
2322
Error,
2423
Float32Array,
@@ -27,7 +26,6 @@ const {
2726
Int32Array,
2827
Int8Array,
2928
ObjectPrototypeToString,
30-
SafeMap,
3129
Uint16Array,
3230
Uint32Array,
3331
Uint8Array,
@@ -244,29 +242,40 @@ Deserializer.prototype.readRawBytes = function readRawBytes(length) {
244242
length);
245243
};
246244

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

268-
const bufferConstructorIndex =
269-
ArrayPrototypePush(arrayBufferViewTypes, FastBuffer) - 1;
263+
function arrayBufferViewIndexToType(index) {
264+
if (index === 0) return Int8Array;
265+
if (index === 1) return Uint8Array;
266+
if (index === 2) return Uint8ClampedArray;
267+
if (index === 3) return Int16Array;
268+
if (index === 4) return Uint16Array;
269+
if (index === 5) return Int32Array;
270+
if (index === 6) return Uint32Array;
271+
if (index === 7) return Float32Array;
272+
if (index === 8) return Float64Array;
273+
if (index === 9) return DataView;
274+
if (index === 10) return FastBuffer;
275+
if (index === 11) return BigInt64Array;
276+
if (index === 12) return BigUint64Array;
277+
return undefined;
278+
}
270279

271280
class DefaultSerializer extends Serializer {
272281
constructor() {
@@ -282,14 +291,17 @@ class DefaultSerializer extends Serializer {
282291
* @returns {void}
283292
*/
284293
_writeHostObject(abView) {
285-
let i = 0;
286-
if (abView.constructor === Buffer) {
287-
i = bufferConstructorIndex;
288-
} else {
289-
const tag = ObjectPrototypeToString(abView);
290-
i = arrayBufferViewTypeToIndex.get(tag);
291-
292-
if (i === undefined) {
294+
// Keep track of how to handle different ArrayBufferViews. The default
295+
// Serializer for Node does not use the V8 methods for serializing those
296+
// objects because Node's `Buffer` objects use pooled allocation in many
297+
// cases, and their underlying `ArrayBuffer`s would show up in the
298+
// serialization. Because a) those may contain sensitive data and the user
299+
// may not be aware of that and b) they are often much larger than the
300+
// `Buffer` itself, custom serialization is applied.
301+
let i = 10; // FastBuffer
302+
if (abView.constructor !== Buffer) {
303+
i = arrayBufferViewTypeToIndex(abView);
304+
if (i === -1) {
293305
throw new this._getDataCloneError(
294306
`Unserializable host object: ${inspect(abView)}`);
295307
}
@@ -310,7 +322,7 @@ class DefaultDeserializer extends Deserializer {
310322
*/
311323
_readHostObject() {
312324
const typeIndex = this.readUint32();
313-
const ctor = arrayBufferViewTypes[typeIndex];
325+
const ctor = arrayBufferViewIndexToType(typeIndex);
314326
const byteLength = this.readUint32();
315327
const byteOffset = this._readRawBytes(byteLength);
316328
const BYTES_PER_ELEMENT = ctor.BYTES_PER_ELEMENT || 1;

test/parallel/test-v8-serdes.js

+8
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)