-
-
Notifications
You must be signed in to change notification settings - Fork 0
Add CBOR serialization for complex JavaScript types in IPC #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
4710ea6
340d411
7e3282f
8d99ed9
469f109
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| /** | ||
| * BigInt Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("BigInt Serialization") | ||
| .step("Return BigInt value", () => { | ||
| // BigInt cannot be serialized by JSON.stringify | ||
| return { | ||
| value: BigInt(9007199254740991), | ||
| timestamp: BigInt(Date.now()), | ||
| }; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the BigInt values | ||
| return { | ||
| received: typeof ctx.previous.value === "bigint", | ||
| }; | ||
|
Comment on lines
+14
to
+18
|
||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| /** | ||
| * Function Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("Function Serialization") | ||
| .step("Return Function value", () => { | ||
| // Functions are omitted when serialized by JSON.stringify | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return { | ||
| callback: () => "hello", | ||
| method: function namedFn() { | ||
| return 42; | ||
| }, | ||
| arrow: (x: number) => x * 2, | ||
| }; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the Function values | ||
| return { | ||
| hasCallback: typeof ctx.previous.callback === "function", | ||
| hasMethod: typeof ctx.previous.method === "function", | ||
| hasArrow: typeof ctx.previous.arrow === "function", | ||
| }; | ||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /** | ||
| * Symbol Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("Symbol Serialization") | ||
| .step("Return Symbol value", () => { | ||
| // Symbols are omitted when serialized by JSON.stringify | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return { | ||
| id: Symbol("unique-id"), | ||
| tag: Symbol.for("global-tag"), | ||
| iterator: Symbol.iterator, | ||
| }; | ||
|
Comment on lines
+12
to
+13
|
||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the Symbol values | ||
| return { | ||
| hasId: typeof ctx.previous.id === "symbol", | ||
| hasTag: typeof ctx.previous.tag === "symbol", | ||
| hasIterator: typeof ctx.previous.iterator === "symbol", | ||
| }; | ||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| /** | ||
| * Circular Reference Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("Circular Reference Serialization") | ||
| .step("Return circular reference", () => { | ||
| // Circular references cause TypeError in JSON.stringify | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const obj: Record<string, unknown> = { name: "parent" }; | ||
| obj.self = obj; | ||
| return obj; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the circular reference | ||
| return { | ||
| hasName: ctx.previous.name === "parent", | ||
| hasSelf: ctx.previous.self === ctx.previous, | ||
| }; | ||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /** | ||
| * Undefined Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("Undefined Serialization") | ||
| .step("Return undefined values", () => { | ||
| // undefined values in object properties are omitted by JSON.stringify | ||
| // undefined in arrays becomes null | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return { | ||
| explicit: undefined, | ||
| nested: { | ||
| value: undefined, | ||
| defined: "exists", | ||
| }, | ||
| array: [1, undefined, 3], | ||
| }; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the undefined values | ||
| return { | ||
| hasExplicit: "explicit" in ctx.previous, | ||
| explicitIsUndefined: ctx.previous.explicit === undefined, | ||
| nestedValueIsUndefined: ctx.previous.nested.value === undefined, | ||
| nestedDefinedExists: ctx.previous.nested.defined === "exists", | ||
| arraySecondIsUndefined: ctx.previous.array[1] === undefined, | ||
| }; | ||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /** | ||
| * Map/Set Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("Map/Set Serialization") | ||
| .step("Return Map and Set values", () => { | ||
| // Map and Set are serialized as empty objects {} by JSON.stringify | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const map = new Map<string, number>([ | ||
| ["a", 1], | ||
| ["b", 2], | ||
| ]); | ||
| const set = new Set([1, 2, 3]); | ||
| return { | ||
| map, | ||
| set, | ||
| weakMap: new WeakMap(), | ||
| weakSet: new WeakSet(), | ||
| }; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the Map and Set values | ||
| return { | ||
| mapIsMap: ctx.previous.map instanceof Map, | ||
| mapSize: ctx.previous.map.size, | ||
| setIsSet: ctx.previous.set instanceof Set, | ||
| setSize: ctx.previous.set.size, | ||
| }; | ||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /** | ||
| * RegExp Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("RegExp Serialization") | ||
| .step("Return RegExp values", () => { | ||
| // RegExp is serialized as empty object {} by JSON.stringify | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return { | ||
| pattern: /hello\s+world/gi, | ||
| email: new RegExp("^[a-z]+@[a-z]+\\.[a-z]+$", "i"), | ||
| unicode: /\p{Script=Hiragana}+/u, | ||
| }; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the RegExp values | ||
| return { | ||
| patternIsRegExp: ctx.previous.pattern instanceof RegExp, | ||
| patternSource: ctx.previous.pattern.source, | ||
| emailIsRegExp: ctx.previous.email instanceof RegExp, | ||
| unicodeFlags: ctx.previous.unicode.flags, | ||
| }; | ||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /** | ||
| * Error Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("Error Serialization") | ||
| .step("Return Error values", () => { | ||
| // Error objects lose most properties when serialized by JSON.stringify | ||
| // Only enumerable own properties are kept (message, name, stack are not enumerable) | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const error = new Error("Something went wrong"); | ||
| const typeError = new TypeError("Invalid type"); | ||
| const customError = Object.assign(new Error("Custom"), { | ||
| code: "ERR_CUSTOM", | ||
| details: { foo: "bar" }, | ||
| }); | ||
| return { | ||
| error, | ||
| typeError, | ||
| customError, | ||
| }; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the Error values | ||
| return { | ||
| errorIsError: ctx.previous.error instanceof Error, | ||
| errorMessage: ctx.previous.error.message, | ||
| errorHasStack: typeof ctx.previous.error.stack === "string", | ||
| typeErrorName: ctx.previous.typeError.name, | ||
| customErrorCode: ctx.previous.customError.code, | ||
| }; | ||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /** | ||
| * Date Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("Date Serialization") | ||
| .step("Return Date values", () => { | ||
| // Date is serialized as ISO string by JSON.stringify (loses type info) | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return { | ||
| now: new Date(), | ||
| epoch: new Date(0), | ||
| specific: new Date("2024-01-15T12:00:00Z"), | ||
| invalid: new Date("invalid"), | ||
| }; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the Date values | ||
| return { | ||
| nowIsDate: ctx.previous.now instanceof Date, | ||
| nowTime: ctx.previous.now.getTime(), | ||
| epochIsDate: ctx.previous.epoch instanceof Date, | ||
| epochTime: ctx.previous.epoch.getTime(), | ||
| specificYear: ctx.previous.specific.getUTCFullYear(), | ||
| invalidIsNaN: Number.isNaN(ctx.previous.invalid.getTime()), | ||
| }; | ||
| }) | ||
| .build(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /** | ||
| * TypedArray Serialization Test Scenario | ||
| */ | ||
| import { scenario } from "jsr:@probitas/probitas@^0"; | ||
|
|
||
| export default scenario("TypedArray Serialization") | ||
| .step("Return TypedArray values", () => { | ||
| // TypedArray is serialized as object with numeric keys by JSON.stringify | ||
| // ArrayBuffer cannot be directly serialized | ||
lambdalisue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return { | ||
| uint8: new Uint8Array([1, 2, 3, 4]), | ||
| int32: new Int32Array([100, 200, -300]), | ||
| float64: new Float64Array([1.5, 2.5, 3.5]), | ||
| buffer: new ArrayBuffer(8), | ||
| dataView: new DataView(new ArrayBuffer(4)), | ||
| }; | ||
| }) | ||
| .step("This step should also run", (ctx) => { | ||
| // This step accesses the TypedArray values | ||
| return { | ||
| uint8IsTypedArray: ctx.previous.uint8 instanceof Uint8Array, | ||
| uint8Length: ctx.previous.uint8.length, | ||
| uint8FirstValue: ctx.previous.uint8[0], | ||
| int32IsTypedArray: ctx.previous.int32 instanceof Int32Array, | ||
| float64Sum: ctx.previous.float64[0] + ctx.previous.float64[1], | ||
| bufferIsArrayBuffer: ctx.previous.buffer instanceof ArrayBuffer, | ||
| bufferByteLength: ctx.previous.buffer.byteLength, | ||
| }; | ||
| }) | ||
| .build(); | ||
Uh oh!
There was an error while loading. Please reload this page.