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: { env: {
"jest/globals": true "jest/globals": true
}, },
parserOptions: {
ecmaVersion: 2020
},
globals: { globals: {
nsObj: false, nsObj: false,
jasmine: false jasmine: false

View File

@ -84,6 +84,7 @@ const I8_HEADER = 0x60;
const I32_HEADER = 0x40; const I32_HEADER = 0x40;
const F64_HEADER = 0x20; const F64_HEADER = 0x20;
const SHORT_STRING_HEADER = 0x80; const SHORT_STRING_HEADER = 0x80;
const BIGINT_HEADER = 0x32;
/** Uplift high-order bits */ /** Uplift high-order bits */
const NUMBERS_HEADER_MASK = 0xe0; const NUMBERS_HEADER_MASK = 0xe0;
@ -331,6 +332,16 @@ class BinaryMiddleware extends SerializerMiddleware {
} }
break; 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": { case "number": {
const type = identifyNumber(thing); const type = identifyNumber(thing);
if (type === 0 && thing >= 0 && thing <= 10) { if (type === 0 && thing >= 0 && thing <= 10) {
@ -847,6 +858,25 @@ class BinaryMiddleware extends SerializerMiddleware {
result.push(read(1).readInt8(0)); 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: default:
if (header <= 10) { if (header <= 10) {
return () => result.push(header); return () => result.push(header);

View File

@ -397,6 +397,9 @@ class ObjectMiddleware extends SerializerMiddleware {
", " ", "
)} }`; )} }`;
} }
if (typeof item === "bigint") {
return `BigInt ${item}n`;
}
try { try {
return `${item}`; return `${item}`;
} catch (e) { } catch (e) {
@ -686,6 +689,8 @@ class ObjectMiddleware extends SerializerMiddleware {
const end1 = read(); const end1 = read();
if (end1 !== ESCAPE) { if (end1 !== ESCAPE) {
console.log("END" + end1);
throw new Error("Expected end of object"); 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|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 */ /** @typedef {Buffer|(() => BufferSerializableType[] | Promise<BufferSerializableType[]>)} BufferSerializableType */

View File

@ -41,6 +41,8 @@ describe("Compiler (filesystem caching)", () => {
] ]
}; };
const isBigIntSupported = typeof BigInt !== "undefined";
options.plugins = [ options.plugins = [
{ {
apply(compiler) { apply(compiler) {
@ -63,22 +65,50 @@ describe("Compiler (filesystem caching)", () => {
if (result) { if (result) {
expect(result.number).toEqual(42); expect(result.number).toEqual(42);
expect(result.number1).toEqual(3.14);
expect(result.number2).toEqual(6.2);
expect(result.string).toEqual("string"); expect(result.string).toEqual("string");
expect(result.error.cause.message).toEqual("cause"); expect(result.error.cause.message).toEqual("cause");
expect(result.error1.cause.string).toBe("string"); expect(result.error1.cause.string).toBe("string");
expect(result.error1.cause.number).toBe(42); 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; return;
} }
const number = 42; const storeValue = {};
const string = "string";
const error = new Error("error", { cause: new Error("cause") });
const error1 = new Error("error", {
cause: { string, number }
});
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);
} }
); );
}); });