From c683916927f9824cd9020042c4e76a3ecf423b2d Mon Sep 17 00:00:00 2001 From: "FUJI Goro (gfx)" Date: Tue, 11 Jun 2019 22:46:33 +0900 Subject: [PATCH 1/6] add JavaScriptCodec to handle basic JavaScript objects --- src/JavaScriptCodec.ts | 59 +++++++++++++++++++++++++++++++++++ test/javascript-codec.test.ts | 28 +++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/JavaScriptCodec.ts create mode 100644 test/javascript-codec.test.ts diff --git a/src/JavaScriptCodec.ts b/src/JavaScriptCodec.ts new file mode 100644 index 00000000..330824c2 --- /dev/null +++ b/src/JavaScriptCodec.ts @@ -0,0 +1,59 @@ +import { ExtensionCodec, ExtensionCodecType } from "./ExtensionCodec"; +import { encode } from "./encode"; +import { decode } from "./decode"; + +export const JavaScriptCodecType = 0; + +export function encodeJavaScriptData(input: unknown): Uint8Array | null { + if (input instanceof Map) { + return encode(["Map", [...input]]); + } else if (input instanceof Set) { + return encode(["Set", [...input]]); + } else if (input instanceof Date) { + // Not a MessagePack timestamp because + // it may be overrided by users + return encode(["Date", input.getTime()]); + } else if (input instanceof RegExp) { + return encode(["RegExp", [input.source, input.flags]]); + } else { + return null; + } +} + +export function decodeJavaScriptData(data: Uint8Array) { + const [constructor, source] = decode(data) as [string, any]; + + switch (constructor) { + case "undefined": { + return undefined; + } + case "Map": { + return new Map(source); + } + case "Set": { + return new Set(source); + } + case "Date": { + return new Date(source); + } + case "RegExp": { + const [pattern, flags] = source; + return new RegExp(pattern, flags); + } + default: { + throw new Error(`Unknown constructor: ${constructor}`); + } + } +} + +export const JavaScriptCodec: ExtensionCodecType = (() => { + const ext = new ExtensionCodec(); + + ext.register({ + type: JavaScriptCodecType, + encode: encodeJavaScriptData, + decode: decodeJavaScriptData, + }); + + return ext; +})(); diff --git a/test/javascript-codec.test.ts b/test/javascript-codec.test.ts new file mode 100644 index 00000000..0d5ea8c4 --- /dev/null +++ b/test/javascript-codec.test.ts @@ -0,0 +1,28 @@ +import assert from "assert"; +import { encode, decode } from "@msgpack/msgpack"; +import { JavaScriptCodec } from "src/JavaScriptCodec"; + +describe("JavaScriptCodec", () => { + context("mixed", () => { + // this data comes from https://github.com/yahoo/serialize-javascript + + it("encodes and decodes the object", () => { + const object = { + str: "string", + num: 0, + obj: { foo: "foo", bar: "bar" }, + arr: [1, 2, 3], + bool: true, + nil: null, + // undef: undefined, + date: new Date("Thu, 28 Apr 2016 22:02:17 GMT"), + map: new Map([["foo", 10], ["bar", 20]]), + set: new Set([123, 456]), + regexp: /foo\n/i, + }; + const encoded = encode(object, { extensionCodec: JavaScriptCodec }); + + assert.deepStrictEqual(decode(encoded, { extensionCodec: JavaScriptCodec }), object); + }); + }); +}); From 0bfb144faffe563cfac977c4ee51c4832001903d Mon Sep 17 00:00:00 2001 From: "FUJI Goro (gfx)" Date: Tue, 11 Jun 2019 22:50:50 +0900 Subject: [PATCH 2/6] use const enum for JavaScript data types --- src/JavaScriptCodec.ts | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/JavaScriptCodec.ts b/src/JavaScriptCodec.ts index 330824c2..a5ff1279 100644 --- a/src/JavaScriptCodec.ts +++ b/src/JavaScriptCodec.ts @@ -4,44 +4,48 @@ import { decode } from "./decode"; export const JavaScriptCodecType = 0; +const enum JSData { + Map, + Set, + Date, + RegExp, +} + export function encodeJavaScriptData(input: unknown): Uint8Array | null { if (input instanceof Map) { - return encode(["Map", [...input]]); + return encode([JSData.Map, [...input]]); } else if (input instanceof Set) { - return encode(["Set", [...input]]); + return encode([JSData.Set, [...input]]); } else if (input instanceof Date) { // Not a MessagePack timestamp because // it may be overrided by users - return encode(["Date", input.getTime()]); + return encode([JSData.Date, input.getTime()]); } else if (input instanceof RegExp) { - return encode(["RegExp", [input.source, input.flags]]); + return encode([JSData.RegExp, [input.source, input.flags]]); } else { return null; } } export function decodeJavaScriptData(data: Uint8Array) { - const [constructor, source] = decode(data) as [string, any]; + const [jsDataType, source] = decode(data) as [JSData, any]; - switch (constructor) { - case "undefined": { - return undefined; - } - case "Map": { + switch (jsDataType) { + case JSData.Map: { return new Map(source); } - case "Set": { + case JSData.Set: { return new Set(source); } - case "Date": { + case JSData.Date: { return new Date(source); } - case "RegExp": { + case JSData.RegExp: { const [pattern, flags] = source; return new RegExp(pattern, flags); } default: { - throw new Error(`Unknown constructor: ${constructor}`); + throw new Error(`Unknown data type: ${jsDataType}`); } } } From 47ae1d4dfd8774753f4a3706188cf661f6207d14 Mon Sep 17 00:00:00 2001 From: "FUJI Goro (gfx)" Date: Tue, 11 Jun 2019 22:55:05 +0900 Subject: [PATCH 3/6] add BigInt support in JavaScriptCodec --- src/JavaScriptCodec.ts | 6 ++++++ test/javascript-codec.test.ts | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/JavaScriptCodec.ts b/src/JavaScriptCodec.ts index a5ff1279..a30958ea 100644 --- a/src/JavaScriptCodec.ts +++ b/src/JavaScriptCodec.ts @@ -9,6 +9,7 @@ const enum JSData { Set, Date, RegExp, + BigInt, } export function encodeJavaScriptData(input: unknown): Uint8Array | null { @@ -22,6 +23,8 @@ export function encodeJavaScriptData(input: unknown): Uint8Array | null { return encode([JSData.Date, input.getTime()]); } else if (input instanceof RegExp) { return encode([JSData.RegExp, [input.source, input.flags]]); + } else if (typeof input === "bigint") { + return encode([JSData.BigInt, input.toString()]); } else { return null; } @@ -44,6 +47,9 @@ export function decodeJavaScriptData(data: Uint8Array) { const [pattern, flags] = source; return new RegExp(pattern, flags); } + case JSData.BigInt: { + return BigInt(source); + } default: { throw new Error(`Unknown data type: ${jsDataType}`); } diff --git a/test/javascript-codec.test.ts b/test/javascript-codec.test.ts index 0d5ea8c4..445f36b6 100644 --- a/test/javascript-codec.test.ts +++ b/test/javascript-codec.test.ts @@ -14,11 +14,12 @@ describe("JavaScriptCodec", () => { arr: [1, 2, 3], bool: true, nil: null, - // undef: undefined, + // undef: undefined, // not supported date: new Date("Thu, 28 Apr 2016 22:02:17 GMT"), map: new Map([["foo", 10], ["bar", 20]]), set: new Set([123, 456]), regexp: /foo\n/i, + bigint: typeof(BigInt) !== "undefined" ? BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1) : null, }; const encoded = encode(object, { extensionCodec: JavaScriptCodec }); From f156faebc615b3e265414804b15a70cc40b5d99e Mon Sep 17 00:00:00 2001 From: "FUJI Goro (gfx)" Date: Tue, 11 Jun 2019 22:57:03 +0900 Subject: [PATCH 4/6] export JavaScriptCodec stuff in index.ts --- src/index.ts | 2 ++ test/javascript-codec.test.ts | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 50b50813..1d56fefb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,4 +20,6 @@ export { decodeTimestampExtension, } from "./timestamp"; +export { JavaScriptCodec, JavaScriptCodecType, encodeJavaScriptData, decodeJavaScriptData } from "./JavaScriptCodec"; + export { WASM_AVAILABLE as __WASM_AVAILABLE } from "./wasmFunctions"; diff --git a/test/javascript-codec.test.ts b/test/javascript-codec.test.ts index 445f36b6..2769ec80 100644 --- a/test/javascript-codec.test.ts +++ b/test/javascript-codec.test.ts @@ -1,6 +1,5 @@ import assert from "assert"; -import { encode, decode } from "@msgpack/msgpack"; -import { JavaScriptCodec } from "src/JavaScriptCodec"; +import { encode, decode, JavaScriptCodec } from "@msgpack/msgpack"; describe("JavaScriptCodec", () => { context("mixed", () => { From 4cef7e1d1e8ad3c5e818a999dab9bcec1ff0c801 Mon Sep 17 00:00:00 2001 From: "FUJI Goro (gfx)" Date: Tue, 11 Jun 2019 23:07:19 +0900 Subject: [PATCH 5/6] rename --- src/JavaScriptCodec.ts | 4 ++-- src/index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/JavaScriptCodec.ts b/src/JavaScriptCodec.ts index a30958ea..04fbf5d1 100644 --- a/src/JavaScriptCodec.ts +++ b/src/JavaScriptCodec.ts @@ -2,7 +2,7 @@ import { ExtensionCodec, ExtensionCodecType } from "./ExtensionCodec"; import { encode } from "./encode"; import { decode } from "./decode"; -export const JavaScriptCodecType = 0; +export const EXT_JAVASCRIPT = 0; const enum JSData { Map, @@ -60,7 +60,7 @@ export const JavaScriptCodec: ExtensionCodecType = (() => { const ext = new ExtensionCodec(); ext.register({ - type: JavaScriptCodecType, + type: EXT_JAVASCRIPT, encode: encodeJavaScriptData, decode: decodeJavaScriptData, }); diff --git a/src/index.ts b/src/index.ts index 1d56fefb..b1eb94a0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,6 +20,6 @@ export { decodeTimestampExtension, } from "./timestamp"; -export { JavaScriptCodec, JavaScriptCodecType, encodeJavaScriptData, decodeJavaScriptData } from "./JavaScriptCodec"; +export { JavaScriptCodec, EXT_JAVASCRIPT, encodeJavaScriptData, decodeJavaScriptData } from "./JavaScriptCodec"; export { WASM_AVAILABLE as __WASM_AVAILABLE } from "./wasmFunctions"; From a5a5d1bc7f19a7e7ca948012f1f5c855da3c5d15 Mon Sep 17 00:00:00 2001 From: "FUJI Goro (gfx)" Date: Tue, 11 Jun 2019 23:11:29 +0900 Subject: [PATCH 6/6] try to encode an object with custom encoder to override built-in's --- package.json | 2 +- src/ExtensionCodec.ts | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index bf1bd324..b197577c 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "test:cover:wasm": "npx nyc --no-clean npm run test:wasm", "test:cover:td": "npx nyc --no-clean npm run test:td", "cover:clean": "rimraf .nyc_output coverage/", - "cover:report": "nyc report --reporter=text-summary --reporter=html --reporter=json", + "cover:report": "npx nyc report --reporter=text-summary --reporter=html --reporter=json", "test:browser": "karma start --single-run", "test:browser:firefox": "karma start --single-run --browsers FirefoxHeadless", "test:browser:chrome": "karma start --single-run --browsers ChromeHeadless", diff --git a/src/ExtensionCodec.ts b/src/ExtensionCodec.ts index 3f12cb3b..ece0e9c2 100644 --- a/src/ExtensionCodec.ts +++ b/src/ExtensionCodec.ts @@ -50,25 +50,25 @@ export class ExtensionCodec implements ExtensionCodecType { } public tryToEncode(object: unknown): ExtData | null { - // built-in extensions - for (let i = 0; i < this.builtInEncoders.length; i++) { - const encoder = this.builtInEncoders[i]; + // custom extensions + for (let i = 0; i < this.encoders.length; i++) { + const encoder = this.encoders[i]; if (encoder != null) { const data = encoder(object); if (data != null) { - const type = -1 - i; + const type = i; return new ExtData(type, data); } } } - // custom extensions - for (let i = 0; i < this.encoders.length; i++) { - const encoder = this.encoders[i]; + // built-in extensions + for (let i = 0; i < this.builtInEncoders.length; i++) { + const encoder = this.builtInEncoders[i]; if (encoder != null) { const data = encoder(object); if (data != null) { - const type = i; + const type = -1 - i; return new ExtData(type, data); } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy