mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
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: https://github.com/nodejs/node/pull/43571 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
38f1e2793c
commit
1643b9ed19
80
lib/v8.js
80
lib/v8.js
@ -16,9 +16,8 @@
|
||||
|
||||
const {
|
||||
Array,
|
||||
ArrayBuffer,
|
||||
ArrayPrototypeForEach,
|
||||
ArrayPrototypePush,
|
||||
BigInt64Array,
|
||||
BigUint64Array,
|
||||
DataView,
|
||||
Error,
|
||||
Float32Array,
|
||||
@ -27,7 +26,6 @@ const {
|
||||
Int32Array,
|
||||
Int8Array,
|
||||
ObjectPrototypeToString,
|
||||
SafeMap,
|
||||
Uint16Array,
|
||||
Uint32Array,
|
||||
Uint8Array,
|
||||
@ -247,29 +245,40 @@ Deserializer.prototype.readRawBytes = function readRawBytes(length) {
|
||||
length);
|
||||
};
|
||||
|
||||
/* Keep track of how to handle different ArrayBufferViews.
|
||||
* The default Serializer for Node does not use the V8 methods for serializing
|
||||
* those objects because Node's `Buffer` objects use pooled allocation in many
|
||||
* cases, and their underlying `ArrayBuffer`s would show up in the
|
||||
* serialization. Because a) those may contain sensitive data and the user
|
||||
* may not be aware of that and b) they are often much larger than the `Buffer`
|
||||
* itself, custom serialization is applied. */
|
||||
const arrayBufferViewTypes = [Int8Array, Uint8Array, Uint8ClampedArray,
|
||||
Int16Array, Uint16Array, Int32Array, Uint32Array,
|
||||
Float32Array, Float64Array, DataView];
|
||||
|
||||
const arrayBufferViewTypeToIndex = new SafeMap();
|
||||
|
||||
{
|
||||
const dummy = new ArrayBuffer();
|
||||
ArrayPrototypeForEach(arrayBufferViewTypes, (ctor, i) => {
|
||||
const tag = ObjectPrototypeToString(new ctor(dummy));
|
||||
arrayBufferViewTypeToIndex.set(tag, i);
|
||||
});
|
||||
function arrayBufferViewTypeToIndex(abView) {
|
||||
const type = ObjectPrototypeToString(abView);
|
||||
if (type === '[object Int8Array]') return 0;
|
||||
if (type === '[object Uint8Array]') return 1;
|
||||
if (type === '[object Uint8ClampedArray]') return 2;
|
||||
if (type === '[object Int16Array]') return 3;
|
||||
if (type === '[object Uint16Array]') return 4;
|
||||
if (type === '[object Int32Array]') return 5;
|
||||
if (type === '[object Uint32Array]') return 6;
|
||||
if (type === '[object Float32Array]') return 7;
|
||||
if (type === '[object Float64Array]') return 8;
|
||||
if (type === '[object DataView]') return 9;
|
||||
// Index 10 is FastBuffer.
|
||||
if (type === '[object BigInt64Array]') return 11;
|
||||
if (type === '[object BigUint64Array]') return 12;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const bufferConstructorIndex =
|
||||
ArrayPrototypePush(arrayBufferViewTypes, FastBuffer) - 1;
|
||||
function arrayBufferViewIndexToType(index) {
|
||||
if (index === 0) return Int8Array;
|
||||
if (index === 1) return Uint8Array;
|
||||
if (index === 2) return Uint8ClampedArray;
|
||||
if (index === 3) return Int16Array;
|
||||
if (index === 4) return Uint16Array;
|
||||
if (index === 5) return Int32Array;
|
||||
if (index === 6) return Uint32Array;
|
||||
if (index === 7) return Float32Array;
|
||||
if (index === 8) return Float64Array;
|
||||
if (index === 9) return DataView;
|
||||
if (index === 10) return FastBuffer;
|
||||
if (index === 11) return BigInt64Array;
|
||||
if (index === 12) return BigUint64Array;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
class DefaultSerializer extends Serializer {
|
||||
constructor() {
|
||||
@ -285,14 +294,17 @@ class DefaultSerializer extends Serializer {
|
||||
* @returns {void}
|
||||
*/
|
||||
_writeHostObject(abView) {
|
||||
let i = 0;
|
||||
if (abView.constructor === Buffer) {
|
||||
i = bufferConstructorIndex;
|
||||
} else {
|
||||
const tag = ObjectPrototypeToString(abView);
|
||||
i = arrayBufferViewTypeToIndex.get(tag);
|
||||
|
||||
if (i === undefined) {
|
||||
// Keep track of how to handle different ArrayBufferViews. The default
|
||||
// Serializer for Node does not use the V8 methods for serializing those
|
||||
// objects because Node's `Buffer` objects use pooled allocation in many
|
||||
// cases, and their underlying `ArrayBuffer`s would show up in the
|
||||
// serialization. Because a) those may contain sensitive data and the user
|
||||
// may not be aware of that and b) they are often much larger than the
|
||||
// `Buffer` itself, custom serialization is applied.
|
||||
let i = 10; // FastBuffer
|
||||
if (abView.constructor !== Buffer) {
|
||||
i = arrayBufferViewTypeToIndex(abView);
|
||||
if (i === -1) {
|
||||
throw new this._getDataCloneError(
|
||||
`Unserializable host object: ${inspect(abView)}`);
|
||||
}
|
||||
@ -313,7 +325,7 @@ class DefaultDeserializer extends Deserializer {
|
||||
*/
|
||||
_readHostObject() {
|
||||
const typeIndex = this.readUint32();
|
||||
const ctor = arrayBufferViewTypes[typeIndex];
|
||||
const ctor = arrayBufferViewIndexToType(typeIndex);
|
||||
const byteLength = this.readUint32();
|
||||
const byteOffset = this._readRawBytes(byteLength);
|
||||
const BYTES_PER_ELEMENT = ctor.BYTES_PER_ELEMENT || 1;
|
||||
|
@ -14,10 +14,18 @@ circular.circular = circular;
|
||||
const objects = [
|
||||
{ foo: 'bar' },
|
||||
{ bar: 'baz' },
|
||||
new Int8Array([1, 2, 3, 4]),
|
||||
new Uint8Array([1, 2, 3, 4]),
|
||||
new Int16Array([1, 2, 3, 4]),
|
||||
new Uint16Array([1, 2, 3, 4]),
|
||||
new Int32Array([1, 2, 3, 4]),
|
||||
new Uint32Array([1, 2, 3, 4]),
|
||||
new Float32Array([1, 2, 3, 4]),
|
||||
new Float64Array([1, 2, 3, 4]),
|
||||
new DataView(new ArrayBuffer(42)),
|
||||
Buffer.from([1, 2, 3, 4]),
|
||||
new BigInt64Array([42n]),
|
||||
new BigUint64Array([42n]),
|
||||
undefined,
|
||||
null,
|
||||
42,
|
||||
|
Loading…
Reference in New Issue
Block a user