feat: support bigint serialization

This commit is contained in:
alexander.akait 2023-05-30 05:18:06 +03:00
parent e90bd2021f
commit b1dac043b3
5 changed files with 76 additions and 8 deletions

View File

@ -109,6 +109,9 @@ module.exports = {
env: {
"jest/globals": true
},
parserOptions: {
ecmaVersion: 2020
},
globals: {
nsObj: false,
jasmine: false

View File

@ -84,6 +84,7 @@ const I8_HEADER = 0x60;
const I32_HEADER = 0x40;
const F64_HEADER = 0x20;
const SHORT_STRING_HEADER = 0x80;
const BIGINT_HEADER = 0x32;
/** Uplift high-order bits */
const NUMBERS_HEADER_MASK = 0xe0;
@ -331,6 +332,16 @@ class BinaryMiddleware extends SerializerMiddleware {
}
break;
}
case "bigint": {
const value = thing.toString();
const len = Buffer.byteLength(value);
allocate(len + HEADER_SIZE + I32_SIZE);
writeU8(BIGINT_HEADER);
writeU32(len);
currentBuffer.write(value, currentPosition);
currentPosition += len;
break;
}
case "number": {
const type = identifyNumber(thing);
if (type === 0 && thing >= 0 && thing <= 10) {
@ -847,6 +858,25 @@ class BinaryMiddleware extends SerializerMiddleware {
result.push(read(1).readInt8(0));
}
};
case BIGINT_HEADER: {
return () => {
const len = readU32();
if (isInCurrentBuffer(len) && currentPosition + len < 0x7fffffff) {
const value = currentBuffer.toString(
undefined,
currentPosition,
currentPosition + len
);
result.push(BigInt(value));
currentPosition += len;
checkOverflow();
} else {
const value = read(len).toString();
result.push(BigInt(value));
}
};
}
default:
if (header <= 10) {
return () => result.push(header);

View File

@ -397,6 +397,9 @@ class ObjectMiddleware extends SerializerMiddleware {
", "
)} }`;
}
if (typeof item === "bigint") {
return `BigInt ${item}n`;
}
try {
return `${item}`;
} catch (e) {
@ -686,6 +689,8 @@ class ObjectMiddleware extends SerializerMiddleware {
const end1 = read();
if (end1 !== ESCAPE) {
console.log("END" + end1);
throw new Error("Expected end of object");
}

View File

@ -6,7 +6,7 @@
/** @typedef {undefined|null|number|string|boolean|Buffer|Object|(() => ComplexSerializableType[] | Promise<ComplexSerializableType[]>)} ComplexSerializableType */
/** @typedef {undefined|null|number|string|boolean|Buffer|(() => PrimitiveSerializableType[] | Promise<PrimitiveSerializableType[]>)} PrimitiveSerializableType */
/** @typedef {undefined|null|number|bigint|string|boolean|Buffer|(() => PrimitiveSerializableType[] | Promise<PrimitiveSerializableType[]>)} PrimitiveSerializableType */
/** @typedef {Buffer|(() => BufferSerializableType[] | Promise<BufferSerializableType[]>)} BufferSerializableType */

View File

@ -41,6 +41,8 @@ describe("Compiler (filesystem caching)", () => {
]
};
const isBigIntSupported = typeof BigInt !== "undefined";
options.plugins = [
{
apply(compiler) {
@ -63,22 +65,50 @@ describe("Compiler (filesystem caching)", () => {
if (result) {
expect(result.number).toEqual(42);
expect(result.number1).toEqual(3.14);
expect(result.number2).toEqual(6.2);
expect(result.string).toEqual("string");
expect(result.error.cause.message).toEqual("cause");
expect(result.error1.cause.string).toBe("string");
expect(result.error1.cause.number).toBe(42);
if (isBigIntSupported) {
expect(result.bigint).toEqual(BigInt(123));
expect(result.bigint1).toEqual(
99999999999999999999999999999999999999999999999999991n
);
expect(result.obj.foo).toBe(BigInt(-10));
expect(Array.from(result.set)).toEqual([
BigInt(1),
BigInt(2)
]);
}
return;
}
const number = 42;
const string = "string";
const error = new Error("error", { cause: new Error("cause") });
const error1 = new Error("error", {
cause: { string, number }
});
const storeValue = {};
await cacheItem.storePromise({ number, string, error, error1 });
storeValue.number = 42;
storeValue.string = "string";
storeValue.error = new Error("error", {
cause: new Error("cause")
});
storeValue.error1 = new Error("error", {
cause: { string: "string", number: 42 }
});
storeValue.number1 = 3.14;
storeValue.number2 = 6.2;
if (isBigIntSupported) {
storeValue.bigint = BigInt(123);
storeValue.bigint1 =
99999999999999999999999999999999999999999999999999991n;
storeValue.obj = { foo: BigInt(-10) };
storeValue.set = new Set([BigInt(1), BigInt(2)]);
}
await cacheItem.storePromise(storeValue);
}
);
});