From b1dac043b3fe30ad14dea5b102543c4b6f8d855d Mon Sep 17 00:00:00 2001 From: "alexander.akait" Date: Tue, 30 May 2023 05:18:06 +0300 Subject: [PATCH] feat: support bigint serialization --- .eslintrc.js | 3 ++ lib/serialization/BinaryMiddleware.js | 30 ++++++++++++++++ lib/serialization/ObjectMiddleware.js | 5 +++ lib/serialization/types.js | 2 +- test/Compiler-filesystem-caching.test.js | 44 ++++++++++++++++++++---- 5 files changed, 76 insertions(+), 8 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index fb927cdd5..a8e25bd72 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -109,6 +109,9 @@ module.exports = { env: { "jest/globals": true }, + parserOptions: { + ecmaVersion: 2020 + }, globals: { nsObj: false, jasmine: false diff --git a/lib/serialization/BinaryMiddleware.js b/lib/serialization/BinaryMiddleware.js index e48c1fc36..4e2cc4363 100644 --- a/lib/serialization/BinaryMiddleware.js +++ b/lib/serialization/BinaryMiddleware.js @@ -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); diff --git a/lib/serialization/ObjectMiddleware.js b/lib/serialization/ObjectMiddleware.js index 5660883c4..882fcab49 100644 --- a/lib/serialization/ObjectMiddleware.js +++ b/lib/serialization/ObjectMiddleware.js @@ -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"); } diff --git a/lib/serialization/types.js b/lib/serialization/types.js index 04a91e5b6..4d8f4ef18 100644 --- a/lib/serialization/types.js +++ b/lib/serialization/types.js @@ -6,7 +6,7 @@ /** @typedef {undefined|null|number|string|boolean|Buffer|Object|(() => ComplexSerializableType[] | Promise)} ComplexSerializableType */ -/** @typedef {undefined|null|number|string|boolean|Buffer|(() => PrimitiveSerializableType[] | Promise)} PrimitiveSerializableType */ +/** @typedef {undefined|null|number|bigint|string|boolean|Buffer|(() => PrimitiveSerializableType[] | Promise)} PrimitiveSerializableType */ /** @typedef {Buffer|(() => BufferSerializableType[] | Promise)} BufferSerializableType */ diff --git a/test/Compiler-filesystem-caching.test.js b/test/Compiler-filesystem-caching.test.js index 16f2a1456..9c7304e41 100644 --- a/test/Compiler-filesystem-caching.test.js +++ b/test/Compiler-filesystem-caching.test.js @@ -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); } ); });