Skip to content

Commit d7cfd0c

Browse files
bnoordhuisdanielleadams
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 0aa255a commit d7cfd0c

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,
@@ -247,29 +245,40 @@ Deserializer.prototype.readRawBytes = function readRawBytes(length) {
247245
length);
248246
};
249247

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-
});
248+
function arrayBufferViewTypeToIndex(abView) {
249+
const type = ObjectPrototypeToString(abView);
250+
if (type === '[object Int8Array]') return 0;
251+
if (type === '[object Uint8Array]') return 1;
252+
if (type === '[object Uint8ClampedArray]') return 2;
253+
if (type === '[object Int16Array]') return 3;
254+
if (type === '[object Uint16Array]') return 4;
255+
if (type === '[object Int32Array]') return 5;
256+
if (type === '[object Uint32Array]') return 6;
257+
if (type === '[object Float32Array]') return 7;
258+
if (type === '[object Float64Array]') return 8;
259+
if (type === '[object DataView]') return 9;
260+
// Index 10 is FastBuffer.
261+
if (type === '[object BigInt64Array]') return 11;
262+
if (type === '[object BigUint64Array]') return 12;
263+
return -1;
269264
}
270265

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

274283
class DefaultSerializer extends Serializer {
275284
constructor() {
@@ -285,14 +294,17 @@ class DefaultSerializer extends Serializer {
285294
* @returns {void}
286295
*/
287296
_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) {
297+
// Keep track of how to handle different ArrayBufferViews. The default
298+
// Serializer for Node does not use the V8 methods for serializing those
299+
// objects because Node's `Buffer` objects use pooled allocation in many
300+
// cases, and their underlying `ArrayBuffer`s would show up in the
301+
// serialization. Because a) those may contain sensitive data and the user
302+
// may not be aware of that and b) they are often much larger than the
303+
// `Buffer` itself, custom serialization is applied.
304+
let i = 10; // FastBuffer
305+
if (abView.constructor !== Buffer) {
306+
i = arrayBufferViewTypeToIndex(abView);
307+
if (i === -1) {
296308
throw new this._getDataCloneError(
297309
`Unserializable host object: ${inspect(abView)}`);
298310
}
@@ -313,7 +325,7 @@ class DefaultDeserializer extends Deserializer {
313325
*/
314326
_readHostObject() {
315327
const typeIndex = this.readUint32();
316-
const ctor = arrayBufferViewTypes[typeIndex];
328+
const ctor = arrayBufferViewIndexToType(typeIndex);
317329
const byteLength = this.readUint32();
318330
const byteOffset = this._readRawBytes(byteLength);
319331
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)