diff --git a/README.md b/README.md
index 8deacf55..225877a5 100644
--- a/README.md
+++ b/README.md
@@ -240,6 +240,8 @@ The following values are the only values accepted by `seroval`:
- `Map`
- `Set`
- `Object.create(null)`
+- `ArrayBuffer`
+- `DataView`
- `TypedArray`
- `Int8Array`
- `Int16Array`
@@ -260,11 +262,17 @@ The following values are the only values accepted by `seroval`:
- `SyntaxError`
- `TypeError`
- `URIError`
-- `Promise` (with `serializeAsync`)
+- `Promise` (with `serializeAsync` and `toJSONAsync`)
- [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol)
- [Well-known symbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#static_properties)
-- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL)
-- [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
+- Web API
+ - [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL)
+ - [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
+ - [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) (with `serializeAsync` and `toJSONAsync`)
+ - [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) (with `serializeAsync` and `toJSONAsync`)
+ - [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
+ - [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
+ - If `FormData` has a `Blob`/`File` entry, it can only be serialized with `serializeAsync` and `toJSONAsync`
- Cyclic references (both self and mutual)
- Isomorphic references (a reference that exist on both the serializer and deserializer side)
@@ -356,6 +364,10 @@ By default, all feature flags are enabled. The following are the feature flags a
- Throws and disables the following usage:
- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL)
- [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
+ - [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
+ - [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File)
+ - [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
+ - [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
## Sponsors
diff --git a/benchmark/results/charts/circular-dedupe to string.chart.html b/benchmark/results/charts/circular-dedupe to string.chart.html
index 0272cc0a..c5ef1718 100644
--- a/benchmark/results/charts/circular-dedupe to string.chart.html
+++ b/benchmark/results/charts/circular-dedupe to string.chart.html
@@ -28,7 +28,7 @@
-
+
" and "\" to avoid invalid escapes in the output.
// http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
-export default function quote(str: string) {
+export function serializeString(str: string) {
let result = '';
let lastPos = 0;
+ let replacement: string | undefined;
for (let i = 0, len = str.length; i < len; i++) {
- let replacement;
- switch (str[i]) {
- case '"':
- replacement = '\\"';
- break;
- case '\\':
- replacement = '\\\\';
- break;
- case '<':
- replacement = '\\x3C';
- break;
- case '\n':
- replacement = '\\n';
- break;
- case '\r':
- replacement = '\\r';
- break;
- case '\u2028':
- replacement = '\\u2028';
- break;
- case '\u2029':
- replacement = '\\u2029';
- break;
- default:
- continue;
+ replacement = serializeChar(str[i]);
+ if (replacement) {
+ result += str.slice(lastPos, i) + replacement;
+ lastPos = i + 1;
}
- result += str.slice(lastPos, i) + replacement;
- lastPos = i + 1;
}
if (lastPos === 0) {
result = str;
@@ -44,13 +38,16 @@ export default function quote(str: string) {
return result;
}
-export function invQuote(str: string): string {
+export function deserializeString(str: string): string {
return str
.replace(/\\"/g, '"')
.replace(/\\\\/g, '\\')
- .replace(/\\x3C/g, '<')
.replace(/\\n/g, '\n')
.replace(/\\r/g, '\r')
+ .replace(/\\b/g, '\b')
+ .replace(/\\t/g, '\t')
+ .replace(/\\f/g, '\f')
+ .replace(/\\x3C/g, '<')
.replace(/\\u2028/g, '\u2028')
.replace(/\\u2029/g, '\u2029');
}
diff --git a/packages/seroval/src/tree/async.ts b/packages/seroval/src/tree/async.ts
index 04450121..f78a6ed3 100644
--- a/packages/seroval/src/tree/async.ts
+++ b/packages/seroval/src/tree/async.ts
@@ -3,7 +3,7 @@
import assert from '../assert';
import { Feature } from '../compat';
import { createIndexedValue, getRootID, ParserContext } from '../context';
-import quote from '../quote';
+import { serializeString } from '../string';
import {
BigIntTypedArrayValue,
TypedArrayValue,
@@ -27,6 +27,8 @@ import {
TRUE_NODE,
UNDEFINED_NODE,
createReferenceNode,
+ createArrayBufferNode,
+ createDataViewNode,
} from './primitives';
import { hasReferenceID } from './reference';
import {
@@ -40,6 +42,8 @@ import {
SerovalAggregateErrorNode,
SerovalArrayNode,
SerovalErrorNode,
+ SerovalFormDataNode,
+ SerovalHeadersNode,
SerovalIterableNode,
SerovalMapNode,
SerovalNode,
@@ -50,7 +54,12 @@ import {
SerovalPromiseNode,
SerovalSetNode,
} from './types';
-import { createURLNode, createURLSearchParamsNode } from './web-api';
+import {
+ createBlobNode,
+ createFileNode,
+ createURLNode,
+ createURLSearchParamsNode,
+} from './web-api';
type ObjectLikeNode =
| SerovalObjectNode
@@ -104,6 +113,7 @@ async function generateArrayNode(
d: undefined,
a: await generateNodeList(ctx, current),
f: undefined,
+ b: undefined,
};
}
@@ -146,6 +156,7 @@ async function generateMapNode(
d: { k: keyNodes, v: valueNodes, s: len },
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -182,6 +193,7 @@ async function generateSetNode(
d: undefined,
a: nodes,
f: undefined,
+ b: undefined,
};
}
@@ -198,14 +210,16 @@ async function generateProperties(
let deferredSize = 0;
let nodesSize = 0;
let item: unknown;
+ let escaped: string;
for (const key of keys) {
item = properties[key];
+ escaped = serializeString(key);
if (isIterable(item)) {
- deferredKeys[deferredSize] = key;
+ deferredKeys[deferredSize] = escaped;
deferredValues[deferredSize] = item;
deferredSize++;
} else {
- keyNodes[nodesSize] = key;
+ keyNodes[nodesSize] = escaped;
valueNodes[nodesSize] = await parse(ctx, item);
nodesSize++;
}
@@ -242,6 +256,7 @@ async function generateIterableNode(
: undefined,
a: await generateNodeList(ctx, array),
f: undefined,
+ b: undefined,
};
}
@@ -262,6 +277,7 @@ async function generatePromiseNode(
d: undefined,
a: undefined,
f: await parse(ctx, value),
+ b: undefined,
}));
}
@@ -287,6 +303,7 @@ async function generateObjectNode(
d: await generateProperties(ctx, current as Record),
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -303,12 +320,13 @@ async function generateAggregateErrorNode(
t: SerovalNodeType.AggregateError,
i: id,
s: undefined,
- l: current.errors.length,
+ l: undefined,
c: undefined,
- m: quote(current.message),
+ m: serializeString(current.message),
d: optionsNode,
- a: await generateNodeList(ctx, current.errors as unknown[]),
+ a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -327,10 +345,59 @@ async function generateErrorNode(
s: undefined,
l: undefined,
c: getErrorConstructorName(current),
- m: quote(current.message),
+ m: serializeString(current.message),
d: optionsNode,
a: undefined,
f: undefined,
+ b: undefined,
+ };
+}
+
+async function generateHeadersNode(
+ ctx: ParserContext,
+ id: number,
+ current: Headers,
+): Promise {
+ assert(ctx.features & Feature.WebAPI, 'Unsupported type "Headers"');
+ const items: Record = {};
+ current.forEach((value, key) => {
+ items[key] = value;
+ });
+ return {
+ t: SerovalNodeType.Headers,
+ i: id,
+ s: undefined,
+ l: undefined,
+ c: undefined,
+ m: undefined,
+ d: await generateProperties(ctx, items),
+ a: undefined,
+ f: undefined,
+ b: undefined,
+ };
+}
+
+async function generateFormDataNode(
+ ctx: ParserContext,
+ id: number,
+ current: FormData,
+): Promise {
+ assert(ctx.features & Feature.WebAPI, 'Unsupported type "FormData"');
+ const items: Record = {};
+ current.forEach((value, key) => {
+ items[key] = value;
+ });
+ return {
+ t: SerovalNodeType.FormData,
+ i: id,
+ s: undefined,
+ l: undefined,
+ c: undefined,
+ m: undefined,
+ d: await generateProperties(ctx, items),
+ a: undefined,
+ f: undefined,
+ b: undefined,
};
}
@@ -384,6 +451,8 @@ async function parse(
return createRegExpNode(id, current as unknown as RegExp);
case Promise:
return generatePromiseNode(ctx, id, current as unknown as Promise);
+ case ArrayBuffer:
+ return createArrayBufferNode(id, current as unknown as ArrayBuffer);
case Int8Array:
case Int16Array:
case Int32Array:
@@ -397,6 +466,8 @@ async function parse(
case BigInt64Array:
case BigUint64Array:
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
+ case DataView:
+ return createDataViewNode(ctx, id, current as unknown as DataView);
case Map:
return generateMapNode(
ctx,
@@ -440,6 +511,14 @@ async function parse(
return createURLNode(ctx, id, current as unknown as URL);
case URLSearchParams:
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
+ case Blob:
+ return createBlobNode(ctx, id, current as unknown as Blob);
+ case File:
+ return createFileNode(ctx, id, current as unknown as File);
+ case Headers:
+ return generateHeadersNode(ctx, id, current as unknown as Headers);
+ case FormData:
+ return generateFormDataNode(ctx, id, current as unknown as FormData);
default:
break;
}
diff --git a/packages/seroval/src/tree/deserialize.ts b/packages/seroval/src/tree/deserialize.ts
index 563c28a7..b940f7b6 100644
--- a/packages/seroval/src/tree/deserialize.ts
+++ b/packages/seroval/src/tree/deserialize.ts
@@ -1,17 +1,24 @@
+/* eslint-disable prefer-spread */
/* eslint-disable @typescript-eslint/no-use-before-define */
import {
SerializationContext,
} from '../context';
-import { invQuote } from '../quote';
-import { AsyncServerValue } from '../types';
+import { deserializeString } from '../string';
import { getReference } from './reference';
import { getErrorConstructor, getTypedArrayConstructor } from './shared';
import { SYMBOL_REF } from './symbols';
import {
SerovalAggregateErrorNode,
+ SerovalArrayBufferNode,
SerovalArrayNode,
SerovalBigIntTypedArrayNode,
+ SerovalBlobNode,
+ SerovalDataViewNode,
+ SerovalDateNode,
SerovalErrorNode,
+ SerovalFileNode,
+ SerovalFormDataNode,
+ SerovalHeadersNode,
SerovalIterableNode,
SerovalMapNode,
SerovalNode,
@@ -20,8 +27,12 @@ import {
SerovalObjectNode,
SerovalObjectRecordNode,
SerovalPromiseNode,
+ SerovalReferenceNode,
+ SerovalRegExpNode,
SerovalSetNode,
SerovalTypedArrayNode,
+ SerovalURLNode,
+ SerovalURLSearchParamsNode,
} from './types';
function assignIndexedValue(
@@ -29,17 +40,23 @@ function assignIndexedValue(
index: number,
value: T,
) {
- ctx.valueMap.set(index, value);
+ if (ctx.markedRefs.has(index)) {
+ ctx.valueMap.set(index, value);
+ }
return value;
}
-function deserializeNodeList(
+function deserializeArray(
ctx: SerializationContext,
- node: SerovalArrayNode | SerovalIterableNode | SerovalAggregateErrorNode,
- result: unknown[],
+ node: SerovalArrayNode,
) {
+ const result: unknown[] = assignIndexedValue(
+ ctx,
+ node.i,
+ new Array(node.l),
+ );
let item: SerovalNode;
- for (let i = 0, len = node.a.length; i < len; i++) {
+ for (let i = 0, len = node.l; i < len; i++) {
item = node.a[i];
if (item) {
result[i] = deserializeTree(ctx, item);
@@ -48,21 +65,6 @@ function deserializeNodeList(
return result;
}
-function deserializeArray(
- ctx: SerializationContext,
- node: SerovalArrayNode,
-) {
- const result: AsyncServerValue[] = assignIndexedValue(
- ctx,
- node.i,
- new Array(node.l),
- );
- ctx.stack.push(node.i);
- deserializeNodeList(ctx, node, result);
- ctx.stack.pop();
- return result;
-}
-
function deserializeProperties(
ctx: SerializationContext,
node: SerovalObjectRecordNode,
@@ -72,7 +74,7 @@ function deserializeProperties(
return {};
}
for (let i = 0; i < node.s; i++) {
- result[node.k[i]] = deserializeTree(ctx, node.v[i]);
+ result[deserializeString(node.k[i])] = deserializeTree(ctx, node.v[i]);
}
return result;
}
@@ -84,11 +86,9 @@ function deserializeNullConstructor(
const result = assignIndexedValue(
ctx,
node.i,
- Object.create(null) as Record,
+ Object.create(null) as Record,
);
- ctx.stack.push(node.i);
deserializeProperties(ctx, node.d, result);
- ctx.stack.pop();
return result;
}
@@ -96,10 +96,8 @@ function deserializeObject(
ctx: SerializationContext,
node: SerovalObjectNode,
) {
- const result = assignIndexedValue(ctx, node.i, {} as Record);
- ctx.stack.push(node.i);
+ const result = assignIndexedValue(ctx, node.i, {} as Record);
deserializeProperties(ctx, node.d, result);
- ctx.stack.pop();
return result;
}
@@ -108,11 +106,9 @@ function deserializeSet(
node: SerovalSetNode,
) {
const result = assignIndexedValue(ctx, node.i, new Set());
- ctx.stack.push(node.i);
- for (let i = 0, len = node.a.length; i < len; i++) {
+ for (let i = 0, len = node.l; i < len; i++) {
result.add(deserializeTree(ctx, node.a[i]));
}
- ctx.stack.pop();
return result;
}
@@ -125,18 +121,16 @@ function deserializeMap(
node.i,
new Map(),
);
- ctx.stack.push(node.i);
- for (let i = 0; i < node.d.s; i++) {
+ for (let i = 0, len = node.d.s; i < len; i++) {
result.set(
deserializeTree(ctx, node.d.k[i]),
deserializeTree(ctx, node.d.v[i]),
);
}
- ctx.stack.pop();
return result;
}
-type AssignableValue = AggregateError | Error | Iterable
+type AssignableValue = AggregateError | Error | Iterable
type AssignableNode = SerovalAggregateErrorNode | SerovalErrorNode | SerovalIterableNode;
function deserializeDictionary(
@@ -145,9 +139,7 @@ function deserializeDictionary(
result: T,
) {
if (node.d) {
- ctx.stack.push(node.i);
const fields = deserializeProperties(ctx, node.d, {});
- ctx.stack.pop();
Object.assign(result, fields);
}
return result;
@@ -158,10 +150,11 @@ function deserializeAggregateError(
node: SerovalAggregateErrorNode,
) {
// Serialize the required arguments
- const result = assignIndexedValue(ctx, node.i, new AggregateError([], invQuote(node.m)));
- ctx.stack.push(node.i);
- result.errors = deserializeNodeList(ctx, node, new Array(node.l));
- ctx.stack.pop();
+ const result = assignIndexedValue(
+ ctx,
+ node.i,
+ new AggregateError([], deserializeString(node.m)),
+ );
// `AggregateError` might've been extended
// either through class or custom properties
// Make sure to assign extra properties
@@ -173,7 +166,7 @@ function deserializeError(
node: SerovalErrorNode,
) {
const ErrorConstructor = getErrorConstructor(node.c);
- const result = assignIndexedValue(ctx, node.i, new ErrorConstructor(invQuote(node.m)));
+ const result = assignIndexedValue(ctx, node.i, new ErrorConstructor(deserializeString(node.m)));
return deserializeDictionary(ctx, node, result);
}
@@ -204,21 +197,26 @@ function deserializePromise(
return result;
}
+function deserializeArrayBuffer(
+ ctx: SerializationContext,
+ node: SerovalArrayBufferNode,
+) {
+ const bytes = new Uint8Array(node.s);
+ const result = assignIndexedValue(ctx, node.i, bytes.buffer);
+ return result;
+}
+
function deserializeTypedArray(
ctx: SerializationContext,
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
) {
const TypedArray = getTypedArrayConstructor(node.c);
- const dummy = new TypedArray();
+ const source = deserializeTree(ctx, node.f) as ArrayBuffer;
const result = assignIndexedValue(ctx, node.i, new TypedArray(
- dummy.buffer,
+ source,
+ node.b,
node.l,
));
- for (let i = 0, len = node.s.length; i < len; i++) {
- result[i] = node.t === SerovalNodeType.BigIntTypedArray
- ? BigInt(node.s[i])
- : Number(node.s[i]);
- }
return result;
}
@@ -226,14 +224,121 @@ function deserializeIterable(
ctx: SerializationContext,
node: SerovalIterableNode,
) {
- const values: AsyncServerValue[] = [];
- deserializeNodeList(ctx, node, values);
- const result = assignIndexedValue(ctx, node.i, {
+ const values: unknown[] = [];
+ let item: SerovalNode;
+ for (let i = 0, len = node.l; i < len; i++) {
+ item = node.a[i];
+ if (item) {
+ values[i] = deserializeTree(ctx, item);
+ }
+ }
+ const result: Iterable = assignIndexedValue(ctx, node.i, {
[Symbol.iterator]: () => values.values(),
});
return deserializeDictionary(ctx, node, result);
}
+function deserializeDate(
+ ctx: SerializationContext,
+ node: SerovalDateNode,
+) {
+ return assignIndexedValue(ctx, node.i, new Date(node.s));
+}
+
+function deserializeRegExp(
+ ctx: SerializationContext,
+ node: SerovalRegExpNode,
+) {
+ return assignIndexedValue(ctx, node.i, new RegExp(node.c, node.m));
+}
+
+function deserializeURL(
+ ctx: SerializationContext,
+ node: SerovalURLNode,
+) {
+ return assignIndexedValue(ctx, node.i, new URL(deserializeString(node.s)));
+}
+
+function deserializeURLSearchParams(
+ ctx: SerializationContext,
+ node: SerovalURLSearchParamsNode,
+) {
+ return assignIndexedValue(ctx, node.i, new URLSearchParams(deserializeString(node.s)));
+}
+
+function deserializeReference(
+ ctx: SerializationContext,
+ node: SerovalReferenceNode,
+) {
+ return assignIndexedValue(ctx, node.i, getReference(deserializeString(node.s)));
+}
+
+function deserializeDataView(
+ ctx: SerializationContext,
+ node: SerovalDataViewNode,
+) {
+ const source = deserializeTree(ctx, node.f) as ArrayBuffer;
+ const result = assignIndexedValue(ctx, node.i, new DataView(
+ source,
+ node.b,
+ node.l,
+ ));
+ return result;
+}
+
+function deserializeBlob(
+ ctx: SerializationContext,
+ node: SerovalBlobNode,
+) {
+ const source = deserializeTree(ctx, node.f) as ArrayBuffer;
+ const result = assignIndexedValue(ctx, node.i, new Blob(
+ [source],
+ { type: deserializeString(node.c) },
+ ));
+ return result;
+}
+
+function deserializeFile(
+ ctx: SerializationContext,
+ node: SerovalFileNode,
+) {
+ const source = deserializeTree(ctx, node.f) as ArrayBuffer;
+ const result = assignIndexedValue(ctx, node.i, new File(
+ [source],
+ deserializeString(node.m),
+ { type: deserializeString(node.c), lastModified: node.b },
+ ));
+ return result;
+}
+
+function deserializeHeaders(
+ ctx: SerializationContext,
+ node: SerovalHeadersNode,
+) {
+ const result = assignIndexedValue(ctx, node.i, new Headers());
+ for (let i = 0, len = node.d.s; i < len; i++) {
+ result.set(
+ deserializeString(node.d.k[i]),
+ deserializeTree(ctx, node.d.v[i]) as string,
+ );
+ }
+ return result;
+}
+
+function deserializeFormData(
+ ctx: SerializationContext,
+ node: SerovalFormDataNode,
+) {
+ const result = assignIndexedValue(ctx, node.i, new FormData());
+ for (let i = 0, len = node.d.s; i < len; i++) {
+ result.set(
+ deserializeString(node.d.k[i]),
+ deserializeTree(ctx, node.d.v[i]) as FormDataEntryValue,
+ );
+ }
+ return result;
+}
+
export default function deserializeTree(
ctx: SerializationContext,
node: SerovalNode,
@@ -243,7 +348,7 @@ export default function deserializeTree(
case SerovalNodeType.Boolean:
return node.s;
case SerovalNodeType.String:
- return invQuote(node.s);
+ return deserializeString(node.s);
case SerovalNodeType.Undefined:
return undefined;
case SerovalNodeType.Null:
@@ -267,16 +372,20 @@ export default function deserializeTree(
case SerovalNodeType.NullConstructor:
return deserializeNullConstructor(ctx, node);
case SerovalNodeType.Date:
- return assignIndexedValue(ctx, node.i, new Date(node.s));
+ return deserializeDate(ctx, node);
case SerovalNodeType.RegExp:
- return assignIndexedValue(ctx, node.i, new RegExp(node.c, node.m));
+ return deserializeRegExp(ctx, node);
case SerovalNodeType.Set:
return deserializeSet(ctx, node);
case SerovalNodeType.Map:
return deserializeMap(ctx, node);
+ case SerovalNodeType.ArrayBuffer:
+ return deserializeArrayBuffer(ctx, node);
case SerovalNodeType.BigIntTypedArray:
case SerovalNodeType.TypedArray:
return deserializeTypedArray(ctx, node);
+ case SerovalNodeType.DataView:
+ return deserializeDataView(ctx, node);
case SerovalNodeType.AggregateError:
return deserializeAggregateError(ctx, node);
case SerovalNodeType.Error:
@@ -288,11 +397,19 @@ export default function deserializeTree(
case SerovalNodeType.WKSymbol:
return SYMBOL_REF[node.s];
case SerovalNodeType.URL:
- return assignIndexedValue(ctx, node.i, new URL(node.s));
+ return deserializeURL(ctx, node);
case SerovalNodeType.URLSearchParams:
- return assignIndexedValue(ctx, node.i, new URLSearchParams(node.s));
+ return deserializeURLSearchParams(ctx, node);
case SerovalNodeType.Reference:
- return assignIndexedValue(ctx, node.i, getReference(invQuote(node.s)));
+ return deserializeReference(ctx, node);
+ case SerovalNodeType.Blob:
+ return deserializeBlob(ctx, node);
+ case SerovalNodeType.File:
+ return deserializeFile(ctx, node);
+ case SerovalNodeType.Headers:
+ return deserializeHeaders(ctx, node);
+ case SerovalNodeType.FormData:
+ return deserializeFormData(ctx, node);
default:
throw new Error('Unsupported type');
}
diff --git a/packages/seroval/src/tree/primitives.ts b/packages/seroval/src/tree/primitives.ts
index b91464a7..3bb9d925 100644
--- a/packages/seroval/src/tree/primitives.ts
+++ b/packages/seroval/src/tree/primitives.ts
@@ -1,7 +1,7 @@
import assert from '../assert';
import { Feature } from '../compat';
-import { ParserContext } from '../context';
-import quote from '../quote';
+import { ParserContext, createIndexedValue } from '../context';
+import { serializeString } from '../string';
import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
import { getReferenceID } from './reference';
import { INV_SYMBOL_REF, WellKnownSymbols } from './symbols';
@@ -24,6 +24,8 @@ import {
SerovalUndefinedNode,
SerovalWKSymbolNode,
SerovalReferenceNode,
+ SerovalArrayBufferNode,
+ SerovalDataViewNode,
} from './types';
export const TRUE_NODE: SerovalBooleanNode = {
@@ -36,6 +38,7 @@ export const TRUE_NODE: SerovalBooleanNode = {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
export const FALSE_NODE: SerovalBooleanNode = {
t: SerovalNodeType.Boolean,
@@ -47,6 +50,7 @@ export const FALSE_NODE: SerovalBooleanNode = {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
export const UNDEFINED_NODE: SerovalUndefinedNode = {
t: SerovalNodeType.Undefined,
@@ -58,6 +62,7 @@ export const UNDEFINED_NODE: SerovalUndefinedNode = {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
export const NULL_NODE: SerovalNullNode = {
t: SerovalNodeType.Null,
@@ -69,6 +74,7 @@ export const NULL_NODE: SerovalNullNode = {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
export const NEG_ZERO_NODE: SerovalNegativeZeroNode = {
t: SerovalNodeType.NegativeZero,
@@ -80,6 +86,7 @@ export const NEG_ZERO_NODE: SerovalNegativeZeroNode = {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
export const INFINITY_NODE: SerovalInfinityNode = {
t: SerovalNodeType.Infinity,
@@ -91,6 +98,7 @@ export const INFINITY_NODE: SerovalInfinityNode = {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
export const NEG_INFINITY_NODE: SerovalNegativeInfinityNode = {
t: SerovalNodeType.NegativeInfinity,
@@ -102,6 +110,7 @@ export const NEG_INFINITY_NODE: SerovalNegativeInfinityNode = {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
export const NAN_NODE: SerovalNaNNode = {
t: SerovalNodeType.NaN,
@@ -113,6 +122,7 @@ export const NAN_NODE: SerovalNaNNode = {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
export function createNumberNode(value: number): SerovalNumberNode {
@@ -126,6 +136,7 @@ export function createNumberNode(value: number): SerovalNumberNode {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -133,13 +144,14 @@ export function createStringNode(value: string): SerovalStringNode {
return {
t: SerovalNodeType.String,
i: undefined,
- s: quote(value),
+ s: serializeString(value),
l: undefined,
c: undefined,
m: undefined,
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -158,6 +170,7 @@ export function createBigIntNode(
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -172,6 +185,7 @@ export function createIndexedValueNode(id: number): SerovalIndexedValueNode {
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -186,6 +200,7 @@ export function createDateNode(id: number, current: Date): SerovalDateNode {
d: undefined,
f: undefined,
a: undefined,
+ b: undefined,
};
}
@@ -200,9 +215,45 @@ export function createRegExpNode(id: number, current: RegExp): SerovalRegExpNode
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
}
+export function createArrayBufferNode(
+ id: number,
+ current: ArrayBuffer,
+): SerovalArrayBufferNode {
+ const bytes = new Uint8Array(current);
+ const len = bytes.length;
+ const values = new Array(len);
+ for (let i = 0; i < len; i++) {
+ values[i] = bytes[i];
+ }
+ return {
+ t: SerovalNodeType.ArrayBuffer,
+ i: id,
+ s: values,
+ l: undefined,
+ c: undefined,
+ m: undefined,
+ d: undefined,
+ a: undefined,
+ f: undefined,
+ b: undefined,
+ };
+}
+
+export function serializeArrayBuffer(
+ ctx: ParserContext,
+ current: ArrayBuffer,
+) {
+ const id = createIndexedValue(ctx, current);
+ if (ctx.markedRefs.has(id)) {
+ return createIndexedValueNode(id);
+ }
+ return createArrayBufferNode(id, current);
+}
+
export function createTypedArrayNode(
ctx: ParserContext,
id: number,
@@ -210,21 +261,17 @@ export function createTypedArrayNode(
): SerovalTypedArrayNode {
const constructor = current.constructor.name;
assert(ctx.features & Feature.TypedArray, `Unsupported value type "${constructor}"`);
- const len = current.length;
- const values = new Array(len);
- for (let i = 0; i < len; i++) {
- values[i] = '' + current[i];
- }
return {
t: SerovalNodeType.TypedArray,
i: id,
- s: values,
- l: current.byteOffset,
+ s: undefined,
+ l: current.length,
c: constructor,
m: undefined,
d: undefined,
a: undefined,
- f: undefined,
+ f: serializeArrayBuffer(ctx, current.buffer),
+ b: current.byteOffset,
};
}
@@ -240,21 +287,17 @@ export function createBigIntTypedArrayNode(
(ctx.features & BIGINT_FLAG) === BIGINT_FLAG,
`Unsupported value type "${constructor}"`,
);
- const len = current.length;
- const values = new Array(len);
- for (let i = 0; i < len; i++) {
- values[i] = '' + current[i];
- }
return {
t: SerovalNodeType.BigIntTypedArray,
i: id,
- s: values,
- l: current.byteOffset,
+ s: undefined,
+ l: current.length,
c: constructor,
m: undefined,
d: undefined,
a: undefined,
- f: undefined,
+ f: serializeArrayBuffer(ctx, current.buffer),
+ b: current.byteOffset,
};
}
@@ -274,6 +317,7 @@ export function createWKSymbolNode(
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -284,12 +328,32 @@ export function createReferenceNode(
return {
t: SerovalNodeType.Reference,
i: id,
- s: quote(getReferenceID(ref)),
+ s: serializeString(getReferenceID(ref)),
l: undefined,
c: undefined,
m: undefined,
d: undefined,
a: undefined,
f: undefined,
+ b: undefined,
+ };
+}
+
+export function createDataViewNode(
+ ctx: ParserContext,
+ id: number,
+ current: DataView,
+): SerovalDataViewNode {
+ return {
+ t: SerovalNodeType.DataView,
+ i: id,
+ s: undefined,
+ l: current.byteLength,
+ c: undefined,
+ m: undefined,
+ d: undefined,
+ a: undefined,
+ f: serializeArrayBuffer(ctx, current.buffer),
+ b: current.byteOffset,
};
}
diff --git a/packages/seroval/src/tree/serialize.ts b/packages/seroval/src/tree/serialize.ts
index ecf467f6..b1b6025d 100644
--- a/packages/seroval/src/tree/serialize.ts
+++ b/packages/seroval/src/tree/serialize.ts
@@ -6,7 +6,6 @@ import {
getRefParam,
markRef,
} from '../context';
-import quote from '../quote';
import { GLOBAL_KEY } from './reference';
import { isValidIdentifier } from './shared';
import { SYMBOL_STRING } from './symbols';
@@ -26,16 +25,29 @@ import {
SerovalIndexedValueNode,
SerovalSetNode,
SerovalTypedArrayNode,
+ SerovalArrayBufferNode,
+ SerovalDataViewNode,
+ SerovalBlobNode,
+ SerovalFileNode,
+ SerovalHeadersNode,
+ SerovalRegExpNode,
+ SerovalDateNode,
+ SerovalURLNode,
+ SerovalURLSearchParamsNode,
+ SerovalReferenceNode,
+ SerovalFormDataNode,
} from './types';
function getAssignmentExpression(assignment: Assignment): string {
switch (assignment.t) {
case 'index':
return assignment.s + '=' + assignment.v;
- case 'map':
- return assignment.s + '.set(' + assignment.k + ',' + assignment.v + ')';
case 'set':
+ return assignment.s + '.set(' + assignment.k + ',' + assignment.v + ')';
+ case 'add':
return assignment.s + '.add(' + assignment.v + ')';
+ case 'append':
+ return assignment.s + '.append(' + assignment.k + ',' + assignment.v + ')';
default:
return '';
}
@@ -66,11 +78,11 @@ function mergeAssignments(assignments: Assignment[]) {
current = item;
}
break;
- case 'map':
+ case 'set':
if (item.s === prev.s) {
// Maps has chaining methods, merge if source is the same
current = {
- t: 'map',
+ t: 'set',
s: getAssignmentExpression(current),
k: item.k,
v: item.v,
@@ -81,11 +93,11 @@ function mergeAssignments(assignments: Assignment[]) {
current = item;
}
break;
- case 'set':
+ case 'add':
if (item.s === prev.s) {
// Sets has chaining methods too
current = {
- t: 'set',
+ t: 'add',
s: getAssignmentExpression(current),
k: undefined,
v: item.v,
@@ -96,6 +108,11 @@ function mergeAssignments(assignments: Assignment[]) {
current = item;
}
break;
+ case 'append':
+ // Different assignment, push current
+ newAssignments.push(current);
+ current = item;
+ break;
default:
break;
}
@@ -146,29 +163,41 @@ function createAssignment(
});
}
-function createSetAdd(
+function createAddAssignment(
ctx: SerializationContext,
ref: number,
value: string,
) {
- markRef(ctx, ref);
ctx.assignments.push({
- t: 'set',
+ t: 'add',
s: getRefParam(ctx, ref),
k: undefined,
v: value,
});
}
-function createMapSet(
+function createSetAssignment(
+ ctx: SerializationContext,
+ ref: number,
+ key: string,
+ value: string,
+) {
+ ctx.assignments.push({
+ t: 'set',
+ s: getRefParam(ctx, ref),
+ k: key,
+ v: value,
+ });
+}
+
+function createAppendAssignment(
ctx: SerializationContext,
ref: number,
key: string,
value: string,
) {
- markRef(ctx, ref);
ctx.assignments.push({
- t: 'map',
+ t: 'append',
s: getRefParam(ctx, ref),
k: key,
v: value,
@@ -181,7 +210,6 @@ function createArrayAssign(
index: number | string,
value: string,
) {
- markRef(ctx, ref);
createAssignment(ctx, getRefParam(ctx, ref) + '[' + index + ']', value);
}
@@ -213,9 +241,13 @@ function isIndexedValueInStack(
return node.t === SerovalNodeType.IndexedValue && ctx.stack.includes(node.i);
}
+type SerovalNodeListNode =
+ | SerovalArrayNode
+ | SerovalIterableNode;
+
function serializeNodeList(
ctx: SerializationContext,
- node: SerovalArrayNode | SerovalIterableNode | SerovalAggregateErrorNode,
+ node: SerovalNodeListNode,
) {
// This is different than Map and Set
// because we also need to serialize
@@ -234,6 +266,7 @@ function serializeNodeList(
if (item) {
// Check if item is a parent
if (isIndexedValueInStack(ctx, item)) {
+ markRef(ctx, node.i);
createArrayAssign(ctx, node.i, i, getRefParam(ctx, item.i));
isHoley = true;
} else {
@@ -273,9 +306,11 @@ function serializeProperties(
let isIdentifier: boolean;
let refParam: string;
let hasPrev = false;
- for (let i = 0; i < node.s; i++) {
- key = node.k[i];
- val = node.v[i];
+ const keys = node.k;
+ const values = node.v;
+ for (let i = 0, len = node.s; i < len; i++) {
+ key = keys[i];
+ val = values[i];
check = Number(key);
// Test if key is a valid number or JS identifier
// so that we don't have to serialize the key and wrap with brackets
@@ -283,13 +318,15 @@ function serializeProperties(
if (isIndexedValueInStack(ctx, val)) {
refParam = getRefParam(ctx, val.i);
if (isIdentifier && Number.isNaN(check)) {
+ markRef(ctx, sourceID);
createObjectAssign(ctx, sourceID, key, refParam);
} else {
- createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
+ markRef(ctx, sourceID);
+ createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + key + '"'), refParam);
}
} else {
result += (hasPrev ? ',' : '')
- + (isIdentifier ? key : ('"' + quote(key) + '"'))
+ + (isIdentifier ? key : ('"' + key + '"'))
+ ':' + serializeTree(ctx, val);
hasPrev = true;
}
@@ -324,12 +361,14 @@ function serializeAssignments(
let check: number;
let parentAssignment: Assignment[];
let isIdentifier: boolean;
- for (let i = 0; i < node.s; i++) {
+ const keys = node.k;
+ const values = node.v;
+ for (let i = 0, len = node.s; i < len; i++) {
parentStack = ctx.stack;
ctx.stack = [];
- refParam = serializeTree(ctx, node.v[i]);
+ refParam = serializeTree(ctx, values[i]);
ctx.stack = parentStack;
- key = node.k[i];
+ key = keys[i];
check = Number(key);
parentAssignment = ctx.assignments;
ctx.assignments = mainAssignments;
@@ -339,7 +378,7 @@ function serializeAssignments(
if (isIdentifier && Number.isNaN(check)) {
createObjectAssign(ctx, sourceID, key, refParam);
} else {
- createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
+ createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + key + '"'), refParam);
}
ctx.assignments = parentAssignment;
}
@@ -395,7 +434,8 @@ function serializeSet(
for (let i = 0; i < size; i++) {
item = node.a[i];
if (isIndexedValueInStack(ctx, item)) {
- createSetAdd(ctx, node.i, getRefParam(ctx, item.i));
+ markRef(ctx, node.i);
+ createAddAssignment(ctx, node.i, getRefParam(ctx, item.i));
} else {
// Push directly
result += (hasPrev ? ',' : '') + serializeTree(ctx, item);
@@ -431,13 +471,14 @@ function serializeMap(
if (isIndexedValueInStack(ctx, key)) {
// Create reference for the map instance
keyRef = getRefParam(ctx, key.i);
+ markRef(ctx, node.i);
// Check if value is a parent
if (isIndexedValueInStack(ctx, val)) {
valueRef = getRefParam(ctx, val.i);
// Register an assignment since
// both key and value are a parent of this
// Map instance
- createMapSet(ctx, node.i, keyRef, valueRef);
+ createSetAssignment(ctx, node.i, keyRef, valueRef);
} else {
// Reset the stack
// This is required because the serialized
@@ -446,16 +487,17 @@ function serializeMap(
// assignment
parent = ctx.stack;
ctx.stack = [];
- createMapSet(ctx, node.i, keyRef, serializeTree(ctx, val));
+ createSetAssignment(ctx, node.i, keyRef, serializeTree(ctx, val));
ctx.stack = parent;
}
} else if (isIndexedValueInStack(ctx, val)) {
// Create ref for the Map instance
valueRef = getRefParam(ctx, val.i);
+ markRef(ctx, node.i);
// Reset stack for the key serialization
parent = ctx.stack;
ctx.stack = [];
- createMapSet(ctx, node.i, serializeTree(ctx, key), valueRef);
+ createSetAssignment(ctx, node.i, serializeTree(ctx, key), valueRef);
ctx.stack = parent;
} else {
result += (hasPrev ? ',[' : '[') + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
@@ -479,7 +521,7 @@ function serializeAggregateError(
) {
// Serialize the required arguments
ctx.stack.push(node.i);
- const serialized = 'new AggregateError(' + serializeNodeList(ctx, node) + ',"' + quote(node.m) + '")';
+ const serialized = 'new AggregateError([],"' + node.m + '")';
ctx.stack.pop();
// `AggregateError` might've been extended
// either through class or custom properties
@@ -491,7 +533,7 @@ function serializeError(
ctx: SerializationContext,
node: SerovalErrorNode,
) {
- const serialized = 'new ' + node.c + '("' + quote(node.m) + '")';
+ const serialized = 'new ' + node.c + '("' + node.m + '")';
return serializeDictionary(ctx, node.i, node.d, serialized);
}
@@ -522,16 +564,26 @@ function serializePromise(
return assignIndexedValue(ctx, node.i, serialized);
}
+function serializeArrayBuffer(
+ ctx: SerializationContext,
+ node: SerovalArrayBufferNode,
+) {
+ let result = 'new Uint8Array(';
+ if (node.s.length) {
+ result += '[';
+ for (let i = 0, len = node.s.length; i < len; i++) {
+ result += ((i > 0) ? ',' : '') + node.s[i];
+ }
+ result += ']';
+ }
+ return assignIndexedValue(ctx, node.i, result + ').buffer');
+}
+
function serializeTypedArray(
ctx: SerializationContext,
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
) {
- let result = '';
- const isBigInt = node.t === SerovalNodeType.BigIntTypedArray;
- for (let i = 0, len = node.s.length; i < len; i++) {
- result += (i !== 0 ? ',' : '') + node.s[i] + (isBigInt ? 'n' : '');
- }
- const args = '[' + result + ']' + (node.l !== 0 ? (',' + node.l) : '');
+ const args = serializeTree(ctx, node.f) + ',' + node.b + ',' + node.l;
return assignIndexedValue(ctx, node.i, 'new ' + node.c + '(' + args + ')');
}
@@ -559,6 +611,112 @@ function serializeIterable(
return serializeDictionary(ctx, node.i, node.d, serialized);
}
+function serializeDate(
+ ctx: SerializationContext,
+ node: SerovalDateNode,
+) {
+ return assignIndexedValue(ctx, node.i, 'new Date("' + node.s + '")');
+}
+
+function serializeRegExp(
+ ctx: SerializationContext,
+ node: SerovalRegExpNode,
+) {
+ return assignIndexedValue(ctx, node.i, '/' + node.c + '/' + node.m);
+}
+
+function serializeURL(
+ ctx: SerializationContext,
+ node: SerovalURLNode,
+) {
+ return assignIndexedValue(ctx, node.i, 'new URL("' + node.s + '")');
+}
+
+function serializeURLSearchParams(
+ ctx: SerializationContext,
+ node: SerovalURLSearchParamsNode,
+) {
+ return assignIndexedValue(ctx, node.i, node.s ? 'new URLSearchParams("' + node.s + '")' : 'new URLSearchParams');
+}
+
+function serializeReference(
+ ctx: SerializationContext,
+ node: SerovalReferenceNode,
+) {
+ return assignIndexedValue(ctx, node.i, GLOBAL_KEY + '.get("' + node.s + '")');
+}
+
+function serializeDataView(
+ ctx: SerializationContext,
+ node: SerovalDataViewNode,
+) {
+ const args = serializeTree(ctx, node.f) + ',' + node.b + ',' + node.l;
+ return assignIndexedValue(ctx, node.i, 'new DataView(' + args + ')');
+}
+
+function serializeBlob(
+ ctx: SerializationContext,
+ node: SerovalBlobNode,
+) {
+ const args = '[' + serializeTree(ctx, node.f) + '],{type:"' + node.c + '"}';
+ return assignIndexedValue(ctx, node.i, 'new Blob(' + args + ')');
+}
+
+function serializeFile(
+ ctx: SerializationContext,
+ node: SerovalFileNode,
+) {
+ const options = '{type:"' + node.c + '",lastModified:' + node.b + '}';
+ const args = '[' + serializeTree(ctx, node.f) + '],"' + node.m + '",' + options;
+ return assignIndexedValue(ctx, node.i, 'new File(' + args + ')');
+}
+
+function serializeHeaders(
+ ctx: SerializationContext,
+ node: SerovalHeadersNode,
+) {
+ return assignIndexedValue(ctx, node.i, 'new Headers(' + serializeProperties(ctx, node.i, node.d) + ')');
+}
+
+function serializeFormDataEntries(
+ ctx: SerializationContext,
+ node: SerovalFormDataNode,
+) {
+ ctx.stack.push(node.i);
+ const mainAssignments: Assignment[] = [];
+ let parentStack: number[];
+ let value: string;
+ let key: string;
+ let parentAssignment: Assignment[];
+ for (let i = 0; i < node.d.s; i++) {
+ parentStack = ctx.stack;
+ ctx.stack = [];
+ value = serializeTree(ctx, node.d.v[i]);
+ key = node.d.k[i];
+ ctx.stack = parentStack;
+ parentAssignment = ctx.assignments;
+ ctx.assignments = mainAssignments;
+ createAppendAssignment(ctx, node.i, '"' + key + '"', value);
+ ctx.assignments = parentAssignment;
+ }
+ ctx.stack.pop();
+ return resolveAssignments(mainAssignments);
+}
+
+function serializeFormData(
+ ctx: SerializationContext,
+ node: SerovalFormDataNode,
+) {
+ if (node.d.s) {
+ markRef(ctx, node.i);
+ }
+ const result = assignIndexedValue(ctx, node.i, 'new FormData()');
+ if (node.d.s) {
+ return '(' + result + ',' + serializeFormDataEntries(ctx, node) + getRefParam(ctx, node.i) + ')';
+ }
+ return result;
+}
+
export default function serializeTree(
ctx: SerializationContext,
node: SerovalNode,
@@ -593,16 +751,20 @@ export default function serializeTree(
case SerovalNodeType.NullConstructor:
return serializeNullConstructor(ctx, node);
case SerovalNodeType.Date:
- return assignIndexedValue(ctx, node.i, 'new Date("' + node.s + '")');
+ return serializeDate(ctx, node);
case SerovalNodeType.RegExp:
- return assignIndexedValue(ctx, node.i, '/' + node.c + '/' + node.m);
+ return serializeRegExp(ctx, node);
case SerovalNodeType.Set:
return serializeSet(ctx, node);
case SerovalNodeType.Map:
return serializeMap(ctx, node);
+ case SerovalNodeType.ArrayBuffer:
+ return serializeArrayBuffer(ctx, node);
case SerovalNodeType.BigIntTypedArray:
case SerovalNodeType.TypedArray:
return serializeTypedArray(ctx, node);
+ case SerovalNodeType.DataView:
+ return serializeDataView(ctx, node);
case SerovalNodeType.AggregateError:
return serializeAggregateError(ctx, node);
case SerovalNodeType.Error:
@@ -614,11 +776,19 @@ export default function serializeTree(
case SerovalNodeType.WKSymbol:
return SYMBOL_STRING[node.s];
case SerovalNodeType.URL:
- return assignIndexedValue(ctx, node.i, 'new URL("' + node.s + '")');
+ return serializeURL(ctx, node);
case SerovalNodeType.URLSearchParams:
- return assignIndexedValue(ctx, node.i, node.s ? 'new URLSearchParams("' + node.s + '")' : 'new URLSearchParams');
+ return serializeURLSearchParams(ctx, node);
case SerovalNodeType.Reference:
- return assignIndexedValue(ctx, node.i, GLOBAL_KEY + '.get("' + node.s + '")');
+ return serializeReference(ctx, node);
+ case SerovalNodeType.Blob:
+ return serializeBlob(ctx, node);
+ case SerovalNodeType.File:
+ return serializeFile(ctx, node);
+ case SerovalNodeType.Headers:
+ return serializeHeaders(ctx, node);
+ case SerovalNodeType.FormData:
+ return serializeFormData(ctx, node);
default:
throw new Error('Unsupported type');
}
diff --git a/packages/seroval/src/tree/sync.ts b/packages/seroval/src/tree/sync.ts
index d02143fa..8a3c6073 100644
--- a/packages/seroval/src/tree/sync.ts
+++ b/packages/seroval/src/tree/sync.ts
@@ -2,7 +2,7 @@
import assert from '../assert';
import { Feature } from '../compat';
import { createIndexedValue, getRootID, ParserContext } from '../context';
-import quote from '../quote';
+import { serializeString } from '../string';
import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
import {
createBigIntNode,
@@ -23,6 +23,8 @@ import {
TRUE_NODE,
UNDEFINED_NODE,
createReferenceNode,
+ createArrayBufferNode,
+ createDataViewNode,
} from './primitives';
import {
hasReferenceID,
@@ -38,6 +40,8 @@ import {
SerovalAggregateErrorNode,
SerovalArrayNode,
SerovalErrorNode,
+ SerovalFormDataNode,
+ SerovalHeadersNode,
SerovalIterableNode,
SerovalMapNode,
SerovalNode,
@@ -89,6 +93,7 @@ function generateArrayNode(
d: undefined,
a: generateNodeList(ctx, current),
f: undefined,
+ b: undefined,
};
}
@@ -131,6 +136,7 @@ function generateMapNode(
d: { k: keyNodes, v: valueNodes, s: len },
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -167,6 +173,7 @@ function generateSetNode(
d: undefined,
a: nodes,
f: undefined,
+ b: undefined,
};
}
@@ -183,14 +190,16 @@ function generateProperties(
let deferredSize = 0;
let nodesSize = 0;
let item: unknown;
+ let escaped: string;
for (const key of keys) {
item = properties[key];
+ escaped = serializeString(key);
if (isIterable(item)) {
- deferredKeys[deferredSize] = key;
+ deferredKeys[deferredSize] = escaped;
deferredValues[deferredSize] = item;
deferredSize++;
} else {
- keyNodes[nodesSize] = key;
+ keyNodes[nodesSize] = escaped;
valueNodes[nodesSize] = parse(ctx, item);
nodesSize++;
}
@@ -227,6 +236,7 @@ function generateIterableNode(
: undefined,
a: generateNodeList(ctx, array),
f: undefined,
+ b: undefined,
};
}
@@ -249,6 +259,7 @@ function generateObjectNode(
d: generateProperties(ctx, current),
a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -265,12 +276,13 @@ function generateAggregateErrorNode(
t: SerovalNodeType.AggregateError,
i: id,
s: undefined,
- l: current.errors.length,
+ l: undefined,
c: undefined,
- m: quote(current.message),
+ m: serializeString(current.message),
d: optionsNode,
- a: generateNodeList(ctx, current.errors as unknown[]),
+ a: undefined,
f: undefined,
+ b: undefined,
};
}
@@ -289,10 +301,59 @@ function generateErrorNode(
s: undefined,
l: undefined,
c: getErrorConstructorName(current),
- m: quote(current.message),
+ m: serializeString(current.message),
d: optionsNode,
a: undefined,
f: undefined,
+ b: undefined,
+ };
+}
+
+function generateHeadersNode(
+ ctx: ParserContext,
+ id: number,
+ current: Headers,
+): SerovalHeadersNode {
+ assert(ctx.features & Feature.WebAPI, 'Unsupported type "Headers"');
+ const items: Record = {};
+ current.forEach((value, key) => {
+ items[key] = value;
+ });
+ return {
+ t: SerovalNodeType.Headers,
+ i: id,
+ s: undefined,
+ l: undefined,
+ c: undefined,
+ m: undefined,
+ d: generateProperties(ctx, items),
+ a: undefined,
+ f: undefined,
+ b: undefined,
+ };
+}
+
+function generateFormDataNode(
+ ctx: ParserContext,
+ id: number,
+ current: FormData,
+): SerovalFormDataNode {
+ assert(ctx.features & Feature.WebAPI, 'Unsupported type "FormData"');
+ const items: Record = {};
+ current.forEach((value, key) => {
+ items[key] = value;
+ });
+ return {
+ t: SerovalNodeType.FormData,
+ i: id,
+ s: undefined,
+ l: undefined,
+ c: undefined,
+ m: undefined,
+ d: generateProperties(ctx, items),
+ a: undefined,
+ f: undefined,
+ b: undefined,
};
}
@@ -344,6 +405,8 @@ function parse(
return createDateNode(id, current as unknown as Date);
case RegExp:
return createRegExpNode(id, current as unknown as RegExp);
+ case ArrayBuffer:
+ return createArrayBufferNode(id, current as unknown as ArrayBuffer);
case Int8Array:
case Int16Array:
case Int32Array:
@@ -357,6 +420,8 @@ function parse(
case BigInt64Array:
case BigUint64Array:
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
+ case DataView:
+ return createDataViewNode(ctx, id, current as unknown as DataView);
case Map:
return generateMapNode(ctx, id, current as unknown as Map);
case Set:
@@ -392,6 +457,10 @@ function parse(
return createURLNode(ctx, id, current as unknown as URL);
case URLSearchParams:
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
+ case Headers:
+ return generateHeadersNode(ctx, id, current as unknown as Headers);
+ case FormData:
+ return generateFormDataNode(ctx, id, current as unknown as FormData);
default:
break;
}
diff --git a/packages/seroval/src/tree/types.ts b/packages/seroval/src/tree/types.ts
index 12a65f90..6b720277 100644
--- a/packages/seroval/src/tree/types.ts
+++ b/packages/seroval/src/tree/types.ts
@@ -29,6 +29,12 @@ export const enum SerovalNodeType {
URL,
URLSearchParams,
Reference,
+ ArrayBuffer,
+ DataView,
+ Blob,
+ File,
+ Headers,
+ FormData,
}
export interface SerovalBaseNode {
@@ -38,11 +44,11 @@ export interface SerovalBaseNode {
i: number | undefined;
// Serialized value
s: any;
- // Size/Byte offset
+ // size/length
l: number | undefined;
// Constructor name / RegExp source
c: string | undefined;
- // message /flags
+ // message/flags
m: string | undefined;
// dictionary
d: SerovalDictionaryNode | undefined;
@@ -50,6 +56,8 @@ export interface SerovalBaseNode {
a: SerovalNode[] | undefined;
// fulfilled node
f: SerovalNode | undefined;
+ // byte offset
+ b: number | undefined;
}
export interface SerovalObjectRecordNode {
@@ -120,22 +128,27 @@ export type SerovalPrimitiveNode =
export interface SerovalIndexedValueNode extends SerovalBaseNode {
t: SerovalNodeType.IndexedValue;
+ // id
i: number;
}
export interface SerovalBigIntNode extends SerovalBaseNode {
t: SerovalNodeType.BigInt;
+ // value in string
s: string;
}
export interface SerovalDateNode extends SerovalBaseNode {
t: SerovalNodeType.Date;
+ // id (Dates are stateful)
i: number;
+ // value in ISO string
s: string;
}
export interface SerovalRegExpNode extends SerovalBaseNode {
t: SerovalNodeType.RegExp;
+ // id (RegExp are stateful)
i: number;
// source
c: string;
@@ -143,20 +156,39 @@ export interface SerovalRegExpNode extends SerovalBaseNode {
m: string;
}
+export interface SerovalArrayBufferNode extends SerovalBaseNode {
+ t: SerovalNodeType.ArrayBuffer;
+ // id
+ i: number;
+ // sequence in bytes
+ s: number[];
+}
+
export interface SerovalTypedArrayNode extends SerovalBaseNode {
t: SerovalNodeType.TypedArray;
+ // id
i: number;
- s: string[];
+ // length
l: number;
+ // TypedArray Constructor
c: string;
+ // ArrayBuffer reference
+ f: SerovalNode;
+ // Byte Offset
+ b: number;
}
export interface SerovalBigIntTypedArrayNode extends SerovalBaseNode {
t: SerovalNodeType.BigIntTypedArray;
i: number;
- s: string[];
+ // length
l: number;
+ // TypedArray Constructor
c: string;
+ // ArrayBuffer reference
+ f: SerovalNode;
+ // Byte Offset
+ b: number;
}
export type SerovalSemiPrimitiveNode =
@@ -168,63 +200,78 @@ export type SerovalSemiPrimitiveNode =
export interface SerovalSetNode extends SerovalBaseNode {
t: SerovalNodeType.Set;
+ // id
+ i: number;
+ // Size of Set
l: number;
+ // Items in Set (as array)
a: SerovalNode[];
- i: number;
}
export interface SerovalMapNode extends SerovalBaseNode {
t: SerovalNodeType.Map;
- d: SerovalMapRecordNode;
i: number;
+ // key/value pairs
+ d: SerovalMapRecordNode;
}
export interface SerovalArrayNode extends SerovalBaseNode {
t: SerovalNodeType.Array;
+ // size of array
l: number;
+ // items
a: SerovalNode[];
i: number;
}
export interface SerovalObjectNode extends SerovalBaseNode {
t: SerovalNodeType.Object;
+ // key/value pairs
d: SerovalObjectRecordNode;
i: number;
}
export interface SerovalNullConstructorNode extends SerovalBaseNode {
t: SerovalNodeType.NullConstructor;
+ // key/value pairs
d: SerovalObjectRecordNode;
i: number;
}
export interface SerovalPromiseNode extends SerovalBaseNode {
t: SerovalNodeType.Promise;
+ // resolved value
f: SerovalNode;
i: number;
}
export interface SerovalErrorNode extends SerovalBaseNode {
t: SerovalNodeType.Error;
+ // constructor name
c: string;
+ // message
m: string;
+ // other properties
d: SerovalObjectRecordNode | undefined;
i: number;
}
export interface SerovalAggregateErrorNode extends SerovalBaseNode {
t: SerovalNodeType.AggregateError;
+ i: number;
+ // message
m: string;
+ // other properties
d: SerovalObjectRecordNode | undefined;
- l: number;
- a: SerovalNode[];
- i: number;
}
export interface SerovalIterableNode extends SerovalBaseNode {
t: SerovalNodeType.Iterable;
+ // other properties
d: SerovalObjectRecordNode | undefined;
+ // number of emitted items
l: number;
+ // array of items
a: SerovalNode[];
i: number;
}
@@ -237,21 +284,69 @@ export interface SerovalWKSymbolNode extends SerovalBaseNode {
export interface SerovalURLNode extends SerovalBaseNode {
t: SerovalNodeType.URL;
i: number;
+ // raw URL
s: string;
}
export interface SerovalURLSearchParamsNode extends SerovalBaseNode {
t: SerovalNodeType.URLSearchParams;
i: number;
+ // raw URL search params
s: string;
}
export interface SerovalReferenceNode extends SerovalBaseNode {
t: SerovalNodeType.Reference;
i: number;
+ // id of the reference in the map
s: string;
}
+export interface SerovalDataViewNode extends SerovalBaseNode {
+ t: SerovalNodeType.DataView;
+ i: number;
+ // byte length
+ l: number;
+ // reference to array buffer
+ f: SerovalNode;
+ // byte offset
+ b: number;
+}
+
+export interface SerovalBlobNode extends SerovalBaseNode {
+ t: SerovalNodeType.Blob;
+ i: number;
+ // file type
+ c: string;
+ // reference to array buffer
+ f: SerovalNode;
+}
+
+export interface SerovalFileNode extends SerovalBaseNode {
+ t: SerovalNodeType.File;
+ i: number;
+ // file type
+ c: string;
+ // file name
+ m: string;
+ // reference to array buffer
+ f: SerovalNode;
+ // last modified
+ b: number;
+}
+
+export interface SerovalHeadersNode extends SerovalBaseNode {
+ t: SerovalNodeType.Headers;
+ i: number;
+ d: SerovalObjectRecordNode;
+}
+
+export interface SerovalFormDataNode extends SerovalBaseNode {
+ t: SerovalNodeType.FormData;
+ i: number;
+ d: SerovalObjectRecordNode;
+}
+
export type SerovalNode =
| SerovalPrimitiveNode
| SerovalIndexedValueNode
@@ -268,4 +363,10 @@ export type SerovalNode =
| SerovalWKSymbolNode
| SerovalURLNode
| SerovalURLSearchParamsNode
- | SerovalReferenceNode;
+ | SerovalReferenceNode
+ | SerovalArrayBufferNode
+ | SerovalDataViewNode
+ | SerovalBlobNode
+ | SerovalFileNode
+ | SerovalHeadersNode
+ | SerovalFormDataNode;
diff --git a/packages/seroval/src/tree/web-api.ts b/packages/seroval/src/tree/web-api.ts
index 72b74f0e..bcaa20ef 100644
--- a/packages/seroval/src/tree/web-api.ts
+++ b/packages/seroval/src/tree/web-api.ts
@@ -1,7 +1,15 @@
import assert from '../assert';
import { Feature } from '../compat';
import { ParserContext } from '../context';
-import { SerovalNodeType, SerovalURLNode, SerovalURLSearchParamsNode } from './types';
+import { serializeString } from '../string';
+import { serializeArrayBuffer } from './primitives';
+import {
+ SerovalBlobNode,
+ SerovalFileNode,
+ SerovalNodeType,
+ SerovalURLNode,
+ SerovalURLSearchParamsNode,
+} from './types';
export function createURLNode(
ctx: ParserContext,
@@ -12,13 +20,14 @@ export function createURLNode(
return {
t: SerovalNodeType.URL,
i: id,
- s: current.href,
+ s: serializeString(current.href),
l: undefined,
c: undefined,
m: undefined,
d: undefined,
f: undefined,
a: undefined,
+ b: undefined,
};
}
@@ -31,12 +40,53 @@ export function createURLSearchParamsNode(
return {
t: SerovalNodeType.URLSearchParams,
i: id,
- s: current.toString(),
+ s: serializeString(current.toString()),
l: undefined,
c: undefined,
m: undefined,
d: undefined,
f: undefined,
a: undefined,
+ b: undefined,
+ };
+}
+
+export async function createBlobNode(
+ ctx: ParserContext,
+ id: number,
+ current: Blob,
+): Promise {
+ assert(ctx.features & Feature.WebAPI, 'Unsupported type "Blob"');
+ return {
+ t: SerovalNodeType.Blob,
+ i: id,
+ s: undefined,
+ l: undefined,
+ c: serializeString(current.type),
+ m: undefined,
+ d: undefined,
+ f: serializeArrayBuffer(ctx, await current.arrayBuffer()),
+ a: undefined,
+ b: undefined,
+ };
+}
+
+export async function createFileNode(
+ ctx: ParserContext,
+ id: number,
+ current: File,
+): Promise {
+ assert(ctx.features & Feature.WebAPI, 'Unsupported type "File"');
+ return {
+ t: SerovalNodeType.File,
+ i: id,
+ s: undefined,
+ l: undefined,
+ c: serializeString(current.type),
+ m: serializeString(current.name),
+ d: undefined,
+ f: serializeArrayBuffer(ctx, await current.arrayBuffer()),
+ a: undefined,
+ b: current.lastModified,
};
}
diff --git a/packages/seroval/test.js b/packages/seroval/test.js
index 0bb521c0..4c02933b 100644
--- a/packages/seroval/test.js
+++ b/packages/seroval/test.js
@@ -1,5 +1,15 @@
-import { fromJSON, toJSON } from 'seroval';
+import { serialize, Feature } from 'seroval';
-console.log([fromJSON(toJSON('"hello"'))]);
-console.log([fromJSON(toJSON(''))]);
\ No newline at end of file
+const errors = [];
+const example = Object.assign(new AggregateError(errors), {
+ errors,
+});
+errors[0] = example;
+console.log(errors)
+
+console.dir(serialize(example, { disabledFeatures: Feature.ErrorPrototypeStack }), {
+ depth: null
+});
+
+console.log(((h,j)=>(h=Object.assign(new AggregateError([],""),{name:"AggregateError",errors:j=[,]}),j[0]=h,h))());
\ No newline at end of file
diff --git a/packages/seroval/test/__snapshots__/array.test.ts.snap b/packages/seroval/test/__snapshots__/array.test.ts.snap
index 928f4d32..1ba9b22f 100644
--- a/packages/seroval/test/__snapshots__/array.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/array.test.ts.snap
@@ -4,9 +4,9 @@ exports[`array holes > serialize > supports array holes 1`] = `"[,,,,,,,,,,]"`;
exports[`array holes > serializeAsync > supports array holes 1`] = `"Promise.resolve([,,,,,,,,,,])"`;
-exports[`array holes > toJSON > supports array holes 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":10,\\"a\\":[null,null,null,null,null,null,null,null,null,null]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`array holes > toJSON > supports array holes 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":10,\\"a\\":[null,null,null,null,null,null,null,null,null,null]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`array holes > toJSONAsync > supports array holes 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":15,\\"i\\":1,\\"l\\":10,\\"a\\":[null,null,null,null,null,null,null,null,null,null]}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`array holes > toJSONAsync > supports array holes 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":15,\\"i\\":1,\\"l\\":10,\\"a\\":[null,null,null,null,null,null,null,null,null,null]}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
exports[`arrays > serialize > supports Arrays 1`] = `"[1,2,3]"`;
@@ -16,10 +16,10 @@ exports[`arrays > serializeAsync > supports Arrays 1`] = `"Promise.resolve([1,2,
exports[`arrays > serializeAsync > supports self recursion 1`] = `"(h=>(h=[Promise.resolve().then(()=>h),Promise.resolve().then(()=>h)]))()"`;
-exports[`arrays > toJSON > supports Arrays 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":3,\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`arrays > toJSON > supports Arrays 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":3,\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`arrays > toJSON > supports self recursion 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":10,\\"i\\":0},{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[0]}"`;
+exports[`arrays > toJSON > supports self recursion 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":10,\\"i\\":0},{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[0]}"`;
-exports[`arrays > toJSONAsync > supports Arrays 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":15,\\"i\\":1,\\"l\\":3,\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`arrays > toJSONAsync > supports Arrays 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":15,\\"i\\":1,\\"l\\":3,\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`arrays > toJSONAsync > supports self recursion 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":10,\\"i\\":0}},{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":10,\\"i\\":0}}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[0]}"`;
+exports[`arrays > toJSONAsync > supports self recursion 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":10,\\"i\\":0}},{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":10,\\"i\\":0}}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[0]}"`;
diff --git a/packages/seroval/test/__snapshots__/bigint.test.ts.snap b/packages/seroval/test/__snapshots__/bigint.test.ts.snap
index 44813f6e..417aebd6 100644
--- a/packages/seroval/test/__snapshots__/bigint.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/bigint.test.ts.snap
@@ -8,6 +8,6 @@ exports[`bigint > serialize > supports bigint 1`] = `"9007199254740991n"`;
exports[`bigint > serializeAsync > supports bigint 1`] = `"Promise.resolve(9007199254740991n)"`;
-exports[`bigint > toJSON > supports bigint 1`] = `"{\\"t\\":{\\"t\\":9,\\"s\\":\\"9007199254740991\\"},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`bigint > toJSON > supports bigint 1`] = `"{\\"t\\":{\\"t\\":9,\\"s\\":\\"9007199254740991\\"},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`bigint > toJSONAsync > supports bigint 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":9,\\"s\\":\\"9007199254740991\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`bigint > toJSONAsync > supports bigint 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":9,\\"s\\":\\"9007199254740991\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/data-view.test.ts.snap b/packages/seroval/test/__snapshots__/data-view.test.ts.snap
new file mode 100644
index 00000000..c0a7d57b
--- /dev/null
+++ b/packages/seroval/test/__snapshots__/data-view.test.ts.snap
@@ -0,0 +1,9 @@
+// Vitest Snapshot v1
+
+exports[`DataView > serialize > supports DataView 1`] = `"new DataView(new Uint8Array([0,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0]).buffer,0,16)"`;
+
+exports[`DataView > serializeAsync > supports DataView 1`] = `"Promise.resolve(new DataView(new Uint8Array([0,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0]).buffer,0,16))"`;
+
+exports[`DataView > toJSON > supports DataView 1`] = `"{\\"t\\":{\\"t\\":29,\\"i\\":0,\\"l\\":16,\\"f\\":{\\"t\\":28,\\"i\\":1,\\"s\\":[0,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0]},\\"b\\":0},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
+
+exports[`DataView > toJSONAsync > supports DataView 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":29,\\"i\\":1,\\"l\\":16,\\"f\\":{\\"t\\":28,\\"i\\":2,\\"s\\":[0,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0]},\\"b\\":0}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/date.test.ts.snap b/packages/seroval/test/__snapshots__/date.test.ts.snap
index a9765054..14555db5 100644
--- a/packages/seroval/test/__snapshots__/date.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/date.test.ts.snap
@@ -4,6 +4,6 @@ exports[`Date > serialize > supports Date 1`] = `"new Date(\\"2023-03-14T11:16:2
exports[`Date > serializeAsync > supports Date 1`] = `"Promise.resolve(new Date(\\"2023-03-14T11:16:24.879Z\\"))"`;
-exports[`Date > toJSON > supports Date 1`] = `"{\\"t\\":{\\"t\\":11,\\"i\\":0,\\"s\\":\\"2023-03-14T11:16:24.879Z\\"},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Date > toJSON > supports Date 1`] = `"{\\"t\\":{\\"t\\":11,\\"i\\":0,\\"s\\":\\"2023-03-14T11:16:24.879Z\\"},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Date > toJSONAsync > supports Date 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":11,\\"i\\":1,\\"s\\":\\"2023-03-14T11:16:24.879Z\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Date > toJSONAsync > supports Date 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":11,\\"i\\":1,\\"s\\":\\"2023-03-14T11:16:24.879Z\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/error.test.ts.snap b/packages/seroval/test/__snapshots__/error.test.ts.snap
index 09630758..fcf4ef25 100644
--- a/packages/seroval/test/__snapshots__/error.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/error.test.ts.snap
@@ -12,14 +12,14 @@ exports[`Error > serializeAsync > supports Error.prototype.name 1`] = `"Promise.
exports[`Error > serializeAsync > supports other Error classes 1`] = `"Promise.resolve(Object.assign(new ReferenceError(\\"A\\"),{stack:\\"\\"}))"`;
-exports[`Error > toJSON > supports Error.prototype.cause 1`] = `"{\\"t\\":{\\"t\\":19,\\"i\\":0,\\"c\\":\\"Error\\",\\"m\\":\\"B\\",\\"d\\":{\\"k\\":[\\"stack\\",\\"cause\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"},{\\"t\\":19,\\"i\\":1,\\"c\\":\\"Error\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":1}}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Error > toJSON > supports Error.prototype.cause 1`] = `"{\\"t\\":{\\"t\\":19,\\"i\\":0,\\"c\\":\\"Error\\",\\"m\\":\\"B\\",\\"d\\":{\\"k\\":[\\"stack\\",\\"cause\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"},{\\"t\\":19,\\"i\\":1,\\"c\\":\\"Error\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":1}}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Error > toJSON > supports Error.prototype.name 1`] = `"{\\"t\\":{\\"t\\":19,\\"i\\":0,\\"c\\":\\"Error\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"name\\",\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"ExampleError\\"},{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Error > toJSON > supports Error.prototype.name 1`] = `"{\\"t\\":{\\"t\\":19,\\"i\\":0,\\"c\\":\\"Error\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"name\\",\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"ExampleError\\"},{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Error > toJSON > supports other Error classes 1`] = `"{\\"t\\":{\\"t\\":19,\\"i\\":0,\\"c\\":\\"ReferenceError\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Error > toJSON > supports other Error classes 1`] = `"{\\"t\\":{\\"t\\":19,\\"i\\":0,\\"c\\":\\"ReferenceError\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Error > toJSONAsync > supports Error.prototype.cause 1`] = `"{\\"t\\":{\\"t\\":19,\\"i\\":0,\\"c\\":\\"Error\\",\\"m\\":\\"B\\",\\"d\\":{\\"k\\":[\\"stack\\",\\"cause\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"},{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":19,\\"i\\":2,\\"c\\":\\"Error\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":1}}}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Error > toJSONAsync > supports Error.prototype.cause 1`] = `"{\\"t\\":{\\"t\\":19,\\"i\\":0,\\"c\\":\\"Error\\",\\"m\\":\\"B\\",\\"d\\":{\\"k\\":[\\"stack\\",\\"cause\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"},{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":19,\\"i\\":2,\\"c\\":\\"Error\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":1}}}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Error > toJSONAsync > supports Error.prototype.name 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":19,\\"i\\":1,\\"c\\":\\"Error\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"name\\",\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"ExampleError\\"},{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":2}}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Error > toJSONAsync > supports Error.prototype.name 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":19,\\"i\\":1,\\"c\\":\\"Error\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"name\\",\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"ExampleError\\"},{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":2}}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Error > toJSONAsync > supports other Error classes 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":19,\\"i\\":1,\\"c\\":\\"ReferenceError\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":1}}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Error > toJSONAsync > supports other Error classes 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":19,\\"i\\":1,\\"c\\":\\"ReferenceError\\",\\"m\\":\\"A\\",\\"d\\":{\\"k\\":[\\"stack\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"\\"}],\\"s\\":1}}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/iterable.test.ts.snap b/packages/seroval/test/__snapshots__/iterable.test.ts.snap
index 0c44fc05..160aa500 100644
--- a/packages/seroval/test/__snapshots__/iterable.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/iterable.test.ts.snap
@@ -10,15 +10,15 @@ exports[`Iterable > compat > should use method shorthand instead of arrow functi
exports[`Iterable > compat#toJSON > should throw an error for unsupported target 1`] = `"Unsupported type \\"Iterable\\""`;
-exports[`Iterable > compat#toJSON > should use Symbol.iterator instead of Array.values. 1`] = `"{\\"t\\":{\\"t\\":21,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":true,\\"f\\":12285,\\"m\\":[0]}"`;
+exports[`Iterable > compat#toJSON > should use Symbol.iterator instead of Array.values. 1`] = `"{\\"t\\":{\\"t\\":21,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":true,\\"f\\":16381,\\"m\\":[0]}"`;
exports[`Iterable > compat#toJSON > should use Symbol.iterator instead of Array.values. 2`] = `"(h=>(h={[Symbol.iterator]:()=>[h][Symbol.iterator]()}))()"`;
-exports[`Iterable > compat#toJSON > should use functions instead of method shorthand. 1`] = `"{\\"t\\":{\\"t\\":21,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":true,\\"f\\":12219,\\"m\\":[0]}"`;
+exports[`Iterable > compat#toJSON > should use functions instead of method shorthand. 1`] = `"{\\"t\\":{\\"t\\":21,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":true,\\"f\\":16315,\\"m\\":[0]}"`;
exports[`Iterable > compat#toJSON > should use functions instead of method shorthand. 2`] = `"(function(h){return h={[Symbol.iterator]:function(){return [h].values()}}})()"`;
-exports[`Iterable > compat#toJSON > should use method shorthand instead of arrow functions. 1`] = `"{\\"t\\":{\\"t\\":21,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":true,\\"f\\":12283,\\"m\\":[0]}"`;
+exports[`Iterable > compat#toJSON > should use method shorthand instead of arrow functions. 1`] = `"{\\"t\\":{\\"t\\":21,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":true,\\"f\\":16379,\\"m\\":[0]}"`;
exports[`Iterable > compat#toJSON > should use method shorthand instead of arrow functions. 2`] = `"(function(h){return h={[Symbol.iterator](){return [h].values()}}})()"`;
@@ -26,6 +26,6 @@ exports[`Iterable > serialize > supports Iterables 1`] = `"(Object.assign({[Symb
exports[`Iterable > serializeAsync > supports Iterables 1`] = `"Promise.resolve(Object.assign({[Symbol.iterator]:()=>[1,2,3].values()},{title:\\"Hello World\\"}))"`;
-exports[`Iterable > toJSON > supports Iterables 1`] = `"{\\"t\\":{\\"t\\":21,\\"i\\":0,\\"l\\":3,\\"d\\":{\\"k\\":[\\"title\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"Hello World\\"}],\\"s\\":1},\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]},\\"r\\":0,\\"i\\":true,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Iterable > toJSON > supports Iterables 1`] = `"{\\"t\\":{\\"t\\":21,\\"i\\":0,\\"l\\":3,\\"d\\":{\\"k\\":[\\"title\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"Hello World\\"}],\\"s\\":1},\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]},\\"r\\":0,\\"i\\":true,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Iterable > toJSONAsync > supports Iterables 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":21,\\"i\\":1,\\"l\\":3,\\"d\\":{\\"k\\":[\\"title\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"Hello World\\"}],\\"s\\":1},\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Iterable > toJSONAsync > supports Iterables 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":21,\\"i\\":1,\\"l\\":3,\\"d\\":{\\"k\\":[\\"title\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"Hello World\\"}],\\"s\\":1},\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/map.test.ts.snap b/packages/seroval/test/__snapshots__/map.test.ts.snap
index df133742..48264366 100644
--- a/packages/seroval/test/__snapshots__/map.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/map.test.ts.snap
@@ -12,10 +12,10 @@ exports[`Map > serializeAsync > supports Map 1`] = `"Promise.resolve(new Map([[1
exports[`Map > serializeAsync > supports self-recursion 1`] = `"(h=>(h=new Map([[Promise.resolve().then(()=>h),Promise.resolve().then(()=>h)]])))()"`;
-exports[`Map > toJSON > supports Map 1`] = `"{\\"t\\":{\\"t\\":14,\\"i\\":0,\\"d\\":{\\"k\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":3}],\\"v\\":[{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":4}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Map > toJSON > supports Map 1`] = `"{\\"t\\":{\\"t\\":14,\\"i\\":0,\\"d\\":{\\"k\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":3}],\\"v\\":[{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":4}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Map > toJSON > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":14,\\"i\\":0,\\"d\\":{\\"k\\":[{\\"t\\":10,\\"i\\":0}],\\"v\\":[{\\"t\\":10,\\"i\\":0}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[0]}"`;
+exports[`Map > toJSON > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":14,\\"i\\":0,\\"d\\":{\\"k\\":[{\\"t\\":10,\\"i\\":0}],\\"v\\":[{\\"t\\":10,\\"i\\":0}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[0]}"`;
-exports[`Map > toJSONAsync > supports Map 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":14,\\"i\\":1,\\"d\\":{\\"k\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":3}],\\"v\\":[{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":4}],\\"s\\":2}}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Map > toJSONAsync > supports Map 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":14,\\"i\\":1,\\"d\\":{\\"k\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":3}],\\"v\\":[{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":4}],\\"s\\":2}}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Map > toJSONAsync > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":14,\\"i\\":0,\\"d\\":{\\"k\\":[{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":10,\\"i\\":0}}],\\"v\\":[{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":10,\\"i\\":0}}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[0]}"`;
+exports[`Map > toJSONAsync > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":14,\\"i\\":0,\\"d\\":{\\"k\\":[{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":10,\\"i\\":0}}],\\"v\\":[{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":10,\\"i\\":0}}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[0]}"`;
diff --git a/packages/seroval/test/__snapshots__/mutual-cycle.test.ts.snap b/packages/seroval/test/__snapshots__/mutual-cycle.test.ts.snap
index 4b689734..2fddbba7 100644
--- a/packages/seroval/test/__snapshots__/mutual-cycle.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/mutual-cycle.test.ts.snap
@@ -12,14 +12,14 @@ exports[`mutual cyclic references > serializeAsync > supports Arrays and Objects
exports[`mutual cyclic references > serializeAsync > supports Objects and Objects 1`] = `"((h,j)=>([h={0:Promise.resolve(j={0:Promise.resolve().then(()=>h)})},j]))()"`;
-exports[`mutual cyclic references > toJSON > supports Arrays and Arrays 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":15,\\"i\\":1,\\"l\\":1,\\"a\\":[{\\"t\\":15,\\"i\\":2,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":1}]}]},{\\"t\\":10,\\"i\\":2}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[1,2]}"`;
+exports[`mutual cyclic references > toJSON > supports Arrays and Arrays 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":15,\\"i\\":1,\\"l\\":1,\\"a\\":[{\\"t\\":15,\\"i\\":2,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":1}]}]},{\\"t\\":10,\\"i\\":2}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[1,2]}"`;
-exports[`mutual cyclic references > toJSON > supports Arrays and Objects 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":15,\\"i\\":1,\\"l\\":1,\\"a\\":[{\\"t\\":16,\\"i\\":2,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":10,\\"i\\":1}],\\"s\\":1}}]},{\\"t\\":10,\\"i\\":2}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[1,2]}"`;
+exports[`mutual cyclic references > toJSON > supports Arrays and Objects 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":15,\\"i\\":1,\\"l\\":1,\\"a\\":[{\\"t\\":16,\\"i\\":2,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":10,\\"i\\":1}],\\"s\\":1}}]},{\\"t\\":10,\\"i\\":2}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[1,2]}"`;
-exports[`mutual cyclic references > toJSON > supports Objects and Objects 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":16,\\"i\\":1,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":16,\\"i\\":2,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":10,\\"i\\":1}],\\"s\\":1}}],\\"s\\":1}},{\\"t\\":10,\\"i\\":2}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[1,2]}"`;
+exports[`mutual cyclic references > toJSON > supports Objects and Objects 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":16,\\"i\\":1,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":16,\\"i\\":2,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":10,\\"i\\":1}],\\"s\\":1}}],\\"s\\":1}},{\\"t\\":10,\\"i\\":2}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[1,2]}"`;
-exports[`mutual cyclic references > toJSONAsync > supports Arrays and Arrays 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":15,\\"i\\":1,\\"l\\":1,\\"a\\":[{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":15,\\"i\\":3,\\"l\\":1,\\"a\\":[{\\"t\\":18,\\"i\\":4,\\"f\\":{\\"t\\":10,\\"i\\":1}}]}}]},{\\"t\\":10,\\"i\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[1,3]}"`;
+exports[`mutual cyclic references > toJSONAsync > supports Arrays and Arrays 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":15,\\"i\\":1,\\"l\\":1,\\"a\\":[{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":15,\\"i\\":3,\\"l\\":1,\\"a\\":[{\\"t\\":18,\\"i\\":4,\\"f\\":{\\"t\\":10,\\"i\\":1}}]}}]},{\\"t\\":10,\\"i\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[1,3]}"`;
-exports[`mutual cyclic references > toJSONAsync > supports Arrays and Objects 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":15,\\"i\\":1,\\"l\\":1,\\"a\\":[{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":16,\\"i\\":3,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":18,\\"i\\":4,\\"f\\":{\\"t\\":10,\\"i\\":1}}],\\"s\\":1}}}]},{\\"t\\":10,\\"i\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[1,3]}"`;
+exports[`mutual cyclic references > toJSONAsync > supports Arrays and Objects 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":15,\\"i\\":1,\\"l\\":1,\\"a\\":[{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":16,\\"i\\":3,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":18,\\"i\\":4,\\"f\\":{\\"t\\":10,\\"i\\":1}}],\\"s\\":1}}}]},{\\"t\\":10,\\"i\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[1,3]}"`;
-exports[`mutual cyclic references > toJSONAsync > supports Objects and Objects 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":16,\\"i\\":1,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":16,\\"i\\":3,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":18,\\"i\\":4,\\"f\\":{\\"t\\":10,\\"i\\":1}}],\\"s\\":1}}}],\\"s\\":1}},{\\"t\\":10,\\"i\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[1,3]}"`;
+exports[`mutual cyclic references > toJSONAsync > supports Objects and Objects 1`] = `"{\\"t\\":{\\"t\\":15,\\"i\\":0,\\"l\\":2,\\"a\\":[{\\"t\\":16,\\"i\\":1,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":16,\\"i\\":3,\\"d\\":{\\"k\\":[\\"0\\"],\\"v\\":[{\\"t\\":18,\\"i\\":4,\\"f\\":{\\"t\\":10,\\"i\\":1}}],\\"s\\":1}}}],\\"s\\":1}},{\\"t\\":10,\\"i\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[1,3]}"`;
diff --git a/packages/seroval/test/__snapshots__/null-constructor.test.ts.snap b/packages/seroval/test/__snapshots__/null-constructor.test.ts.snap
index fd5496b8..496b2767 100644
--- a/packages/seroval/test/__snapshots__/null-constructor.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/null-constructor.test.ts.snap
@@ -2,7 +2,7 @@
exports[`null-constructor > compat > should use manual assignment instead of Object.assign 1`] = `"(h=>((h=Object.create(null),h.hello=\\"world\\",h)))()"`;
-exports[`null-constructor > compat#toJSON > should use manual assignment instead of Object.assign 1`] = `"{\\"t\\":{\\"t\\":17,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":12159,\\"m\\":[]}"`;
+exports[`null-constructor > compat#toJSON > should use manual assignment instead of Object.assign 1`] = `"{\\"t\\":{\\"t\\":17,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":16255,\\"m\\":[]}"`;
exports[`null-constructor > compat#toJSON > should use manual assignment instead of Object.assign 2`] = `"(h=>((h=Object.create(null),h.hello=\\"world\\",h)))()"`;
@@ -10,6 +10,6 @@ exports[`null-constructor > serialize > supports Object.create(null) 1`] = `"Obj
exports[`null-constructor > serializeAsync > supports Object.create(null) 1`] = `"Object.assign(Object.create(null),{hello:\\"world\\"})"`;
-exports[`null-constructor > toJSON > supports Object.create(null) 1`] = `"{\\"t\\":{\\"t\\":17,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`null-constructor > toJSON > supports Object.create(null) 1`] = `"{\\"t\\":{\\"t\\":17,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`null-constructor > toJSONAsync > supports Object.create(null) 1`] = `"{\\"t\\":{\\"t\\":17,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`null-constructor > toJSONAsync > supports Object.create(null) 1`] = `"{\\"t\\":{\\"t\\":17,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/number.test.ts.snap b/packages/seroval/test/__snapshots__/number.test.ts.snap
index e412ce39..13be95c0 100644
--- a/packages/seroval/test/__snapshots__/number.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/number.test.ts.snap
@@ -1,21 +1,21 @@
// Vitest Snapshot v1
-exports[`number > toJSON > supports numbers 1`] = `"{\\"t\\":{\\"t\\":0,\\"s\\":3735928559},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSON > supports numbers 1`] = `"{\\"t\\":{\\"t\\":0,\\"s\\":3735928559},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSON > supports numbers 2`] = `"{\\"t\\":{\\"t\\":8},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSON > supports numbers 2`] = `"{\\"t\\":{\\"t\\":8},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSON > supports numbers 3`] = `"{\\"t\\":{\\"t\\":6},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSON > supports numbers 3`] = `"{\\"t\\":{\\"t\\":6},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSON > supports numbers 4`] = `"{\\"t\\":{\\"t\\":7},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSON > supports numbers 4`] = `"{\\"t\\":{\\"t\\":7},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSON > supports numbers 5`] = `"{\\"t\\":{\\"t\\":5},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSON > supports numbers 5`] = `"{\\"t\\":{\\"t\\":5},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSONAsync > supports numbers 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":0,\\"s\\":3735928559}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSONAsync > supports numbers 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":0,\\"s\\":3735928559}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSONAsync > supports numbers 2`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":8}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSONAsync > supports numbers 2`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":8}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSONAsync > supports numbers 3`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":6}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSONAsync > supports numbers 3`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":6}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSONAsync > supports numbers 4`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":7}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSONAsync > supports numbers 4`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":7}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`number > toJSONAsync > supports numbers 5`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":5}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`number > toJSONAsync > supports numbers 5`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":5}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/object.test.ts.snap b/packages/seroval/test/__snapshots__/object.test.ts.snap
index 2d3e3975..73271d36 100644
--- a/packages/seroval/test/__snapshots__/object.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/object.test.ts.snap
@@ -8,10 +8,10 @@ exports[`objects > serializeAsync > supports Objects 1`] = `"Promise.resolve({he
exports[`objects > serializeAsync > supports self-recursion 1`] = `"(h=>(h={a:Promise.resolve().then(()=>h),b:Promise.resolve().then(()=>h)}))()"`;
-exports[`objects > toJSON > supports Objects 1`] = `"{\\"t\\":{\\"t\\":16,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":true,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`objects > toJSON > supports Objects 1`] = `"{\\"t\\":{\\"t\\":16,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}},\\"r\\":0,\\"i\\":true,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`objects > toJSON > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":16,\\"i\\":0,\\"d\\":{\\"k\\":[\\"a\\",\\"b\\"],\\"v\\":[{\\"t\\":10,\\"i\\":0},{\\"t\\":10,\\"i\\":0}],\\"s\\":2}},\\"r\\":0,\\"i\\":true,\\"f\\":12287,\\"m\\":[0]}"`;
+exports[`objects > toJSON > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":16,\\"i\\":0,\\"d\\":{\\"k\\":[\\"a\\",\\"b\\"],\\"v\\":[{\\"t\\":10,\\"i\\":0},{\\"t\\":10,\\"i\\":0}],\\"s\\":2}},\\"r\\":0,\\"i\\":true,\\"f\\":16383,\\"m\\":[0]}"`;
-exports[`objects > toJSONAsync > supports Objects 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":16,\\"i\\":1,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`objects > toJSONAsync > supports Objects 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":16,\\"i\\":1,\\"d\\":{\\"k\\":[\\"hello\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"}],\\"s\\":1}}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`objects > toJSONAsync > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":16,\\"i\\":0,\\"d\\":{\\"k\\":[\\"a\\",\\"b\\"],\\"v\\":[{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":10,\\"i\\":0}},{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":10,\\"i\\":0}}],\\"s\\":2}},\\"r\\":0,\\"i\\":true,\\"f\\":12287,\\"m\\":[0]}"`;
+exports[`objects > toJSONAsync > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":16,\\"i\\":0,\\"d\\":{\\"k\\":[\\"a\\",\\"b\\"],\\"v\\":[{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":10,\\"i\\":0}},{\\"t\\":18,\\"i\\":2,\\"f\\":{\\"t\\":10,\\"i\\":0}}],\\"s\\":2}},\\"r\\":0,\\"i\\":true,\\"f\\":16383,\\"m\\":[0]}"`;
diff --git a/packages/seroval/test/__snapshots__/reference.test.ts.snap b/packages/seroval/test/__snapshots__/reference.test.ts.snap
index 4eb5cdbf..1c8b6b56 100644
--- a/packages/seroval/test/__snapshots__/reference.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/reference.test.ts.snap
@@ -4,6 +4,6 @@ exports[`Reference > serialize > supports Reference 1`] = `"__SEROVAL__.get(\\"e
exports[`Reference > serializeAsync > supports Reference 1`] = `"Promise.resolve(__SEROVAL__.get(\\"example\\"))"`;
-exports[`Reference > toJSON > supports Reference 1`] = `"{\\"t\\":{\\"t\\":27,\\"i\\":0,\\"s\\":\\"example\\"},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Reference > toJSON > supports Reference 1`] = `"{\\"t\\":{\\"t\\":27,\\"i\\":0,\\"s\\":\\"example\\"},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Reference > toJSONAsync > supports Reference 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":27,\\"i\\":1,\\"s\\":\\"example\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Reference > toJSONAsync > supports Reference 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":27,\\"i\\":1,\\"s\\":\\"example\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/regexp.test.ts.snap b/packages/seroval/test/__snapshots__/regexp.test.ts.snap
index ee619708..83f944b1 100644
--- a/packages/seroval/test/__snapshots__/regexp.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/regexp.test.ts.snap
@@ -4,6 +4,6 @@ exports[`RegExp > serialize > supports RegExp 1`] = `"/[a-z0-9]+/i"`;
exports[`RegExp > serializeAsync > supports RegExp 1`] = `"Promise.resolve(/[a-z0-9]+/i)"`;
-exports[`RegExp > toJSON > supports RegExp 1`] = `"{\\"t\\":{\\"t\\":12,\\"i\\":0,\\"c\\":\\"[a-z0-9]+\\",\\"m\\":\\"i\\"},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`RegExp > toJSON > supports RegExp 1`] = `"{\\"t\\":{\\"t\\":12,\\"i\\":0,\\"c\\":\\"[a-z0-9]+\\",\\"m\\":\\"i\\"},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`RegExp > toJSONAsync > supports RegExp 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":12,\\"i\\":1,\\"c\\":\\"[a-z0-9]+\\",\\"m\\":\\"i\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`RegExp > toJSONAsync > supports RegExp 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":12,\\"i\\":1,\\"c\\":\\"[a-z0-9]+\\",\\"m\\":\\"i\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/set.test.ts.snap b/packages/seroval/test/__snapshots__/set.test.ts.snap
index 9b7b71fb..f71379e0 100644
--- a/packages/seroval/test/__snapshots__/set.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/set.test.ts.snap
@@ -12,10 +12,10 @@ exports[`Set > serializeAsync > supports Set 1`] = `"Promise.resolve(new Set([1,
exports[`Set > serializeAsync > supports self-recursion 1`] = `"(h=>(h=new Set([Promise.resolve().then(()=>h)])))()"`;
-exports[`Set > toJSON > supports Set 1`] = `"{\\"t\\":{\\"t\\":13,\\"i\\":0,\\"l\\":3,\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Set > toJSON > supports Set 1`] = `"{\\"t\\":{\\"t\\":13,\\"i\\":0,\\"l\\":3,\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Set > toJSON > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":13,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[0]}"`;
+exports[`Set > toJSON > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":13,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":10,\\"i\\":0}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[0]}"`;
-exports[`Set > toJSONAsync > supports Set 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":13,\\"i\\":1,\\"l\\":3,\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`Set > toJSONAsync > supports Set 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":13,\\"i\\":1,\\"l\\":3,\\"a\\":[{\\"t\\":0,\\"s\\":1},{\\"t\\":0,\\"s\\":2},{\\"t\\":0,\\"s\\":3}]}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`Set > toJSONAsync > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":13,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":10,\\"i\\":0}}]},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[0]}"`;
+exports[`Set > toJSONAsync > supports self-recursion 1`] = `"{\\"t\\":{\\"t\\":13,\\"i\\":0,\\"l\\":1,\\"a\\":[{\\"t\\":18,\\"i\\":1,\\"f\\":{\\"t\\":10,\\"i\\":0}}]},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[0]}"`;
diff --git a/packages/seroval/test/__snapshots__/string.test.ts.snap b/packages/seroval/test/__snapshots__/string.test.ts.snap
index 3ddc57c7..7182db7b 100644
--- a/packages/seroval/test/__snapshots__/string.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/string.test.ts.snap
@@ -8,10 +8,10 @@ exports[`string > serializeAsync > supports strings 1`] = `"Promise.resolve(\\"\
exports[`string > serializeAsync > supports strings 2`] = `"Promise.resolve(\\"\\\\x3Cscript>\\\\x3C/script>\\")"`;
-exports[`string > toJSON > supports strings 1`] = `"{\\"t\\":{\\"t\\":1,\\"s\\":\\"\\\\\\\\\\\\\\"hello\\\\\\\\\\\\\\"\\"},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`string > toJSON > supports strings 1`] = `"{\\"t\\":{\\"t\\":1,\\"s\\":\\"\\\\\\\\\\\\\\"hello\\\\\\\\\\\\\\"\\"},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`string > toJSON > supports strings 2`] = `"{\\"t\\":{\\"t\\":1,\\"s\\":\\"\\\\\\\\x3Cscript>\\\\\\\\x3C/script>\\"},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`string > toJSON > supports strings 2`] = `"{\\"t\\":{\\"t\\":1,\\"s\\":\\"\\\\\\\\x3Cscript>\\\\\\\\x3C/script>\\"},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`string > toJSONAsync > supports strings 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":1,\\"s\\":\\"\\\\\\\\\\\\\\"hello\\\\\\\\\\\\\\"\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`string > toJSONAsync > supports strings 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":1,\\"s\\":\\"\\\\\\\\\\\\\\"hello\\\\\\\\\\\\\\"\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`string > toJSONAsync > supports strings 2`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":1,\\"s\\":\\"\\\\\\\\x3Cscript>\\\\\\\\x3C/script>\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`string > toJSONAsync > supports strings 2`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":1,\\"s\\":\\"\\\\\\\\x3Cscript>\\\\\\\\x3C/script>\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/typed-array.test.ts.snap b/packages/seroval/test/__snapshots__/typed-array.test.ts.snap
new file mode 100644
index 00000000..892d5b39
--- /dev/null
+++ b/packages/seroval/test/__snapshots__/typed-array.test.ts.snap
@@ -0,0 +1,9 @@
+// Vitest Snapshot v1
+
+exports[`typed arrays > serialize > supports typed arrays 1`] = `"new Uint32Array(new Uint8Array([255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255]).buffer,0,4)"`;
+
+exports[`typed arrays > serializeAsync > supports typed arrays 1`] = `"Promise.resolve(new Uint32Array(new Uint8Array([255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255]).buffer,0,4))"`;
+
+exports[`typed arrays > toJSON > supports typed arrays 1`] = `"{\\"t\\":{\\"t\\":22,\\"i\\":0,\\"l\\":4,\\"c\\":\\"Uint32Array\\",\\"f\\":{\\"t\\":28,\\"i\\":1,\\"s\\":[255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255]},\\"b\\":0},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
+
+exports[`typed arrays > toJSONAsync > supports typed arrays 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":22,\\"i\\":1,\\"l\\":4,\\"c\\":\\"Uint32Array\\",\\"f\\":{\\"t\\":28,\\"i\\":2,\\"s\\":[255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255]},\\"b\\":0}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/wk-symbols.test.ts.snap b/packages/seroval/test/__snapshots__/wk-symbols.test.ts.snap
index 27b01478..989fd75c 100644
--- a/packages/seroval/test/__snapshots__/wk-symbols.test.ts.snap
+++ b/packages/seroval/test/__snapshots__/wk-symbols.test.ts.snap
@@ -52,54 +52,54 @@ exports[`well-known symbols > serializeAsync > supports strings 12`] = `"Promise
exports[`well-known symbols > serializeAsync > supports strings 13`] = `"Promise.resolve(Symbol.unscopables)"`;
-exports[`well-known symbols > toJSON > supports strings 1`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":0},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 1`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":0},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 2`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":1},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 2`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":1},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 3`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":2},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 3`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":2},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 4`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":3},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 4`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":3},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 5`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":4},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 5`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":4},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 6`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":5},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 6`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":5},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 7`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":6},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 7`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":6},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 8`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":7},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 8`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":7},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 9`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":8},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 9`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":8},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 10`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":9},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 10`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":9},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 11`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":10},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 11`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":10},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 12`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":11},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 12`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":11},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSON > supports strings 13`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":12},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSON > supports strings 13`] = `"{\\"t\\":{\\"t\\":24,\\"s\\":12},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":0}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":0}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 2`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 2`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":1}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 3`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 3`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 4`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":3}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 4`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":3}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 5`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":4}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 5`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":4}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 6`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":5}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 6`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":5}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 7`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":6}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 7`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":6}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 8`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":7}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 8`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":7}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 9`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":8}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 9`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":8}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 10`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":9}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 10`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":9}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 11`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":10}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 11`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":10}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 12`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":11}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 12`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":11}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`well-known symbols > toJSONAsync > supports strings 13`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":12}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`well-known symbols > toJSONAsync > supports strings 13`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":24,\\"s\\":12}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/data-view.test.ts b/packages/seroval/test/data-view.test.ts
new file mode 100644
index 00000000..5339bcde
--- /dev/null
+++ b/packages/seroval/test/data-view.test.ts
@@ -0,0 +1,60 @@
+import { describe, it, expect } from 'vitest';
+import {
+ deserialize,
+ fromJSON,
+ serialize,
+ serializeAsync,
+ toJSONAsync,
+ toJSON,
+} from '../src';
+
+describe('DataView', () => {
+ describe('serialize', () => {
+ it('supports DataView', () => {
+ const buffer = new ArrayBuffer(16);
+ const example = new DataView(buffer, 0);
+ example.setInt16(1, 42);
+ const result = serialize(example);
+ expect(result).toMatchSnapshot();
+ const back = deserialize(result);
+ expect(back).toBeInstanceOf(DataView);
+ expect(back.getInt16(1)).toBe(example.getInt16(1));
+ });
+ });
+ describe('serializeAsync', () => {
+ it('supports DataView', async () => {
+ const buffer = new ArrayBuffer(16);
+ const example = new DataView(buffer, 0);
+ example.setInt16(1, 42);
+ const result = await serializeAsync(Promise.resolve(example));
+ expect(result).toMatchSnapshot();
+ const back = await deserialize>(result);
+ expect(back).toBeInstanceOf(DataView);
+ expect(back.getInt16(1)).toBe(example.getInt16(1));
+ });
+ });
+ describe('toJSON', () => {
+ it('supports DataView', () => {
+ const buffer = new ArrayBuffer(16);
+ const example = new DataView(buffer, 0);
+ example.setInt16(1, 42);
+ const result = toJSON(example);
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = fromJSON(result);
+ expect(back).toBeInstanceOf(DataView);
+ expect(back.getInt16(1)).toBe(example.getInt16(1));
+ });
+ });
+ describe('toJSONAsync', () => {
+ it('supports DataView', async () => {
+ const buffer = new ArrayBuffer(16);
+ const example = new DataView(buffer, 0);
+ example.setInt16(1, 42);
+ const result = await toJSONAsync(Promise.resolve(example));
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = await fromJSON>(result);
+ expect(back).toBeInstanceOf(DataView);
+ expect(back.getInt16(1)).toBe(example.getInt16(1));
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/seroval/test/typed-array.test.ts b/packages/seroval/test/typed-array.test.ts
new file mode 100644
index 00000000..d3ef43e8
--- /dev/null
+++ b/packages/seroval/test/typed-array.test.ts
@@ -0,0 +1,84 @@
+import { describe, it, expect } from 'vitest';
+import {
+ deserialize,
+ fromJSON,
+ serialize,
+ serializeAsync,
+ toJSONAsync,
+ toJSON,
+} from '../src';
+
+describe('typed arrays', () => {
+ describe('serialize', () => {
+ it('supports typed arrays', () => {
+ const example = new Uint32Array([
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ ]);
+ const result = serialize(example);
+ expect(result).toMatchSnapshot();
+ const back = deserialize(result);
+ expect(back).toBeInstanceOf(Uint32Array);
+ expect(back[0]).toBe(example[0]);
+ expect(back[1]).toBe(example[1]);
+ expect(back[2]).toBe(example[2]);
+ expect(back[3]).toBe(example[3]);
+ });
+ });
+ describe('serializeAsync', () => {
+ it('supports typed arrays', async () => {
+ const example = new Uint32Array([
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ ]);
+ const result = await serializeAsync(Promise.resolve(example));
+ expect(result).toMatchSnapshot();
+ const back = await deserialize>(result);
+ expect(back).toBeInstanceOf(Uint32Array);
+ expect(back[0]).toBe(example[0]);
+ expect(back[1]).toBe(example[1]);
+ expect(back[2]).toBe(example[2]);
+ expect(back[3]).toBe(example[3]);
+ });
+ });
+ describe('toJSON', () => {
+ it('supports typed arrays', () => {
+ const example = new Uint32Array([
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ ]);
+ const result = toJSON(example);
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = fromJSON(result);
+ expect(back).toBeInstanceOf(Uint32Array);
+ expect(back[0]).toBe(example[0]);
+ expect(back[1]).toBe(example[1]);
+ expect(back[2]).toBe(example[2]);
+ expect(back[3]).toBe(example[3]);
+ });
+ });
+ describe('toJSONAsync', () => {
+ it('supports typed arrays', async () => {
+ const example = new Uint32Array([
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ ]);
+ const result = await toJSONAsync(Promise.resolve(example));
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = await fromJSON>(result);
+ expect(back).toBeInstanceOf(Uint32Array);
+ expect(back[0]).toBe(example[0]);
+ expect(back[1]).toBe(example[1]);
+ expect(back[2]).toBe(example[2]);
+ expect(back[3]).toBe(example[3]);
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/seroval/test/web-api/__snapshots__/blob.test.ts.snap b/packages/seroval/test/web-api/__snapshots__/blob.test.ts.snap
new file mode 100644
index 00000000..ef8835b0
--- /dev/null
+++ b/packages/seroval/test/web-api/__snapshots__/blob.test.ts.snap
@@ -0,0 +1,5 @@
+// Vitest Snapshot v1
+
+exports[`Blob > serializeAsync > supports Blob 1`] = `"Promise.resolve(new Blob([new Uint8Array([72,101,108,108,111,32,87,111,114,108,100]).buffer],{type:\\"text/plain\\"}))"`;
+
+exports[`Blob > toJSONAsync > supports Blob 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":30,\\"i\\":1,\\"c\\":\\"text/plain\\",\\"f\\":{\\"t\\":28,\\"i\\":2,\\"s\\":[72,101,108,108,111,32,87,111,114,108,100]}}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/web-api/__snapshots__/file.test.ts.snap b/packages/seroval/test/web-api/__snapshots__/file.test.ts.snap
new file mode 100644
index 00000000..023664f5
--- /dev/null
+++ b/packages/seroval/test/web-api/__snapshots__/file.test.ts.snap
@@ -0,0 +1,5 @@
+// Vitest Snapshot v1
+
+exports[`File > serializeAsync > supports File 1`] = `"Promise.resolve(new File([new Uint8Array([72,101,108,108,111,32,87,111,114,108,100]).buffer],\\"hello.txt\\",{type:\\"text/plain\\",lastModified:1681027542680}))"`;
+
+exports[`File > toJSONAsync > supports File 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":31,\\"i\\":1,\\"c\\":\\"text/plain\\",\\"m\\":\\"hello.txt\\",\\"f\\":{\\"t\\":28,\\"i\\":2,\\"s\\":[72,101,108,108,111,32,87,111,114,108,100]},\\"b\\":1681027542680}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/web-api/__snapshots__/form-data.test.ts.snap b/packages/seroval/test/web-api/__snapshots__/form-data.test.ts.snap
new file mode 100644
index 00000000..2ba6095b
--- /dev/null
+++ b/packages/seroval/test/web-api/__snapshots__/form-data.test.ts.snap
@@ -0,0 +1,9 @@
+// Vitest Snapshot v1
+
+exports[`FormData > serialize > supports FormData 1`] = `"(h=>((h=new FormData(),h.append(\\"hello\\",\\"world\\"),h.append(\\"foo\\",\\"bar\\"),h)))()"`;
+
+exports[`FormData > serializeAsync > supports FormData 1`] = `"(h=>(Promise.resolve((h=new FormData(),h.append(\\"hello-world\\",new File([new Uint8Array([72,101,108,108,111,32,87,111,114,108,100]).buffer],\\"hello.txt\\",{type:\\"text/plain\\",lastModified:1681027542680})),h.append(\\"foo-bar\\",new File([new Uint8Array([70,111,111,32,66,97,114]).buffer],\\"foo-bar.txt\\",{type:\\"text/plain\\",lastModified:1681027542680})),h))))()"`;
+
+exports[`FormData > toJSON > supports FormData 1`] = `"{\\"t\\":{\\"t\\":33,\\"i\\":0,\\"d\\":{\\"k\\":[\\"hello\\",\\"foo\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"world\\"},{\\"t\\":1,\\"s\\":\\"bar\\"}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
+
+exports[`FormData > toJSONAsync > supports FormData 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":33,\\"i\\":1,\\"d\\":{\\"k\\":[\\"example\\",\\"foo-bar\\"],\\"v\\":[{\\"t\\":31,\\"i\\":2,\\"c\\":\\"text/plain\\",\\"m\\":\\"hello.txt\\",\\"f\\":{\\"t\\":28,\\"i\\":3,\\"s\\":[72,101,108,108,111,32,87,111,114,108,100]},\\"b\\":1681027542680},{\\"t\\":31,\\"i\\":4,\\"c\\":\\"text/plain\\",\\"m\\":\\"foo-bar.txt\\",\\"f\\":{\\"t\\":28,\\"i\\":5,\\"s\\":[70,111,111,32,66,97,114]},\\"b\\":1681027542680}],\\"s\\":2}}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/web-api/__snapshots__/headers.test.ts.snap b/packages/seroval/test/web-api/__snapshots__/headers.test.ts.snap
new file mode 100644
index 00000000..9d464ec3
--- /dev/null
+++ b/packages/seroval/test/web-api/__snapshots__/headers.test.ts.snap
@@ -0,0 +1,9 @@
+// Vitest Snapshot v1
+
+exports[`Headers > serialize > supports Headers 1`] = `"new Headers({\\"content-encoding\\":\\"gzip\\",\\"content-type\\":\\"text/plain\\"})"`;
+
+exports[`Headers > serializeAsync > supports Headers 1`] = `"Promise.resolve(new Headers({\\"content-encoding\\":\\"gzip\\",\\"content-type\\":\\"text/plain\\"}))"`;
+
+exports[`Headers > toJSON > supports Headers 1`] = `"{\\"t\\":{\\"t\\":32,\\"i\\":0,\\"d\\":{\\"k\\":[\\"content-encoding\\",\\"content-type\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"gzip\\"},{\\"t\\":1,\\"s\\":\\"text/plain\\"}],\\"s\\":2}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
+
+exports[`Headers > toJSONAsync > supports Headers 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":32,\\"i\\":1,\\"d\\":{\\"k\\":[\\"content-encoding\\",\\"content-type\\"],\\"v\\":[{\\"t\\":1,\\"s\\":\\"gzip\\"},{\\"t\\":1,\\"s\\":\\"text/plain\\"}],\\"s\\":2}}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/url-search-params.test.ts.snap b/packages/seroval/test/web-api/__snapshots__/url-search-params.test.ts.snap
similarity index 86%
rename from packages/seroval/test/__snapshots__/url-search-params.test.ts.snap
rename to packages/seroval/test/web-api/__snapshots__/url-search-params.test.ts.snap
index 3be5070e..ec4318b9 100644
--- a/packages/seroval/test/__snapshots__/url-search-params.test.ts.snap
+++ b/packages/seroval/test/web-api/__snapshots__/url-search-params.test.ts.snap
@@ -4,6 +4,6 @@ exports[`URLSearchParams > serialize > supports URLSearchParams 1`] = `"new URLS
exports[`URLSearchParams > serializeAsync > supports URLSearchParams 1`] = `"Promise.resolve(new URLSearchParams(\\"hello=world&foo=bar\\"))"`;
-exports[`URLSearchParams > toJSON > supports URLSearchParams 1`] = `"{\\"t\\":{\\"t\\":26,\\"i\\":0,\\"s\\":\\"hello=world&foo=bar\\"},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`URLSearchParams > toJSON > supports URLSearchParams 1`] = `"{\\"t\\":{\\"t\\":26,\\"i\\":0,\\"s\\":\\"hello=world&foo=bar\\"},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`URLSearchParams > toJSONAsync > supports URLSearchParams 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":26,\\"i\\":1,\\"s\\":\\"hello=world&foo=bar\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`URLSearchParams > toJSONAsync > supports URLSearchParams 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":26,\\"i\\":1,\\"s\\":\\"hello=world&foo=bar\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/__snapshots__/url.test.ts.snap b/packages/seroval/test/web-api/__snapshots__/url.test.ts.snap
similarity index 85%
rename from packages/seroval/test/__snapshots__/url.test.ts.snap
rename to packages/seroval/test/web-api/__snapshots__/url.test.ts.snap
index c0df8162..78251078 100644
--- a/packages/seroval/test/__snapshots__/url.test.ts.snap
+++ b/packages/seroval/test/web-api/__snapshots__/url.test.ts.snap
@@ -4,6 +4,6 @@ exports[`URL > serialize > supports URL 1`] = `"new URL(\\"https://github.com/lx
exports[`URL > serializeAsync > supports URL 1`] = `"Promise.resolve(new URL(\\"https://github.com/lxsmnsyc/seroval?hello=world\\"))"`;
-exports[`URL > toJSON > supports URL 1`] = `"{\\"t\\":{\\"t\\":25,\\"i\\":0,\\"s\\":\\"https://github.com/lxsmnsyc/seroval?hello=world\\"},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`URL > toJSON > supports URL 1`] = `"{\\"t\\":{\\"t\\":25,\\"i\\":0,\\"s\\":\\"https://github.com/lxsmnsyc/seroval?hello=world\\"},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
-exports[`URL > toJSONAsync > supports URL 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":25,\\"i\\":1,\\"s\\":\\"https://github.com/lxsmnsyc/seroval?hello=world\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":12287,\\"m\\":[]}"`;
+exports[`URL > toJSONAsync > supports URL 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":25,\\"i\\":1,\\"s\\":\\"https://github.com/lxsmnsyc/seroval?hello=world\\"}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
diff --git a/packages/seroval/test/web-api/blob.test.ts b/packages/seroval/test/web-api/blob.test.ts
new file mode 100644
index 00000000..870be1c2
--- /dev/null
+++ b/packages/seroval/test/web-api/blob.test.ts
@@ -0,0 +1,37 @@
+import { describe, it, expect } from 'vitest';
+import 'node-fetch-native/polyfill';
+import {
+ deserialize,
+ fromJSON,
+ serializeAsync,
+ toJSONAsync,
+} from '../../src';
+
+describe('Blob', () => {
+ describe('serializeAsync', () => {
+ it('supports Blob', async () => {
+ const example = new Blob(['Hello World'], {
+ type: 'text/plain',
+ });
+ const result = await serializeAsync(Promise.resolve(example));
+ expect(result).toMatchSnapshot();
+ const back = await deserialize>(result);
+ expect(back).toBeInstanceOf(Blob);
+ expect(await back.text()).toBe(await example.text());
+ expect(back.type).toBe(example.type);
+ });
+ });
+ describe('toJSONAsync', () => {
+ it('supports Blob', async () => {
+ const example = new Blob(['Hello World'], {
+ type: 'text/plain',
+ });
+ const result = await toJSONAsync(Promise.resolve(example));
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = await fromJSON>(result);
+ expect(back).toBeInstanceOf(Blob);
+ expect(await back.text()).toBe(await example.text());
+ expect(back.type).toBe(example.type);
+ });
+ });
+});
diff --git a/packages/seroval/test/web-api/file.test.ts b/packages/seroval/test/web-api/file.test.ts
new file mode 100644
index 00000000..82f28bd2
--- /dev/null
+++ b/packages/seroval/test/web-api/file.test.ts
@@ -0,0 +1,39 @@
+import { describe, it, expect } from 'vitest';
+import 'node-fetch-native/polyfill';
+import {
+ deserialize,
+ fromJSON,
+ serializeAsync,
+ toJSONAsync,
+} from '../../src';
+
+describe('File', () => {
+ describe('serializeAsync', () => {
+ it('supports File', async () => {
+ const example = new File(['Hello World'], 'hello.txt', {
+ type: 'text/plain',
+ lastModified: 1681027542680,
+ });
+ const result = await serializeAsync(Promise.resolve(example));
+ expect(result).toMatchSnapshot();
+ const back = await deserialize>(result);
+ expect(back).toBeInstanceOf(File);
+ expect(await back.text()).toBe(await example.text());
+ expect(back.type).toBe(example.type);
+ });
+ });
+ describe('toJSONAsync', () => {
+ it('supports File', async () => {
+ const example = new File(['Hello World'], 'hello.txt', {
+ type: 'text/plain',
+ lastModified: 1681027542680,
+ });
+ const result = await toJSONAsync(Promise.resolve(example));
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = await fromJSON>(result);
+ expect(back).toBeInstanceOf(File);
+ expect(await back.text()).toBe(await example.text());
+ expect(back.type).toBe(example.type);
+ });
+ });
+});
diff --git a/packages/seroval/test/web-api/form-data.test.ts b/packages/seroval/test/web-api/form-data.test.ts
new file mode 100644
index 00000000..5ede1190
--- /dev/null
+++ b/packages/seroval/test/web-api/form-data.test.ts
@@ -0,0 +1,70 @@
+import { describe, it, expect } from 'vitest';
+import 'node-fetch-native/polyfill';
+import {
+ deserialize,
+ fromJSON,
+ serialize,
+ serializeAsync,
+ toJSON,
+ toJSONAsync,
+} from '../../src';
+
+describe('FormData', () => {
+ describe('serialize', () => {
+ it('supports FormData', () => {
+ const example = new FormData();
+ example.set('hello', 'world');
+ example.set('foo', 'bar');
+ const result = serialize(example);
+ expect(result).toMatchSnapshot();
+ const back = deserialize(result);
+ expect(back).toBeInstanceOf(FormData);
+ });
+ });
+ describe('serializeAsync', () => {
+ it('supports FormData', async () => {
+ const example = new FormData();
+ example.set('hello-world', new File(['Hello World'], 'hello.txt', {
+ type: 'text/plain',
+ lastModified: 1681027542680,
+ }));
+ example.set('foo-bar', new File(['Foo Bar'], 'foo-bar.txt', {
+ type: 'text/plain',
+ lastModified: 1681027542680,
+ }));
+ const result = await serializeAsync(Promise.resolve(example));
+ expect(result).toMatchSnapshot();
+ const back = await deserialize>(result);
+ expect(back).toBeInstanceOf(FormData);
+ });
+ });
+ describe('toJSON', () => {
+ it('supports FormData', () => {
+ const example = new FormData();
+ example.set('hello', 'world');
+ example.set('foo', 'bar');
+ const result = toJSON(example);
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = fromJSON(result);
+ expect(back).toBeInstanceOf(FormData);
+ });
+ });
+ describe('toJSONAsync', () => {
+ it('supports FormData', async () => {
+ const example = new FormData();
+ example.set('example', new File(['Hello World'], 'hello.txt', {
+ type: 'text/plain',
+ lastModified: 1681027542680,
+ }));
+ example.set('foo-bar', new File(['Foo Bar'], 'foo-bar.txt', {
+ type: 'text/plain',
+ lastModified: 1681027542680,
+ }));
+ const result = await toJSONAsync(Promise.resolve(example));
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = await fromJSON>(result);
+ expect(back).toBeInstanceOf(FormData);
+ expect(String(back)).toBe(String(example));
+ });
+ });
+});
diff --git a/packages/seroval/test/web-api/headers.test.ts b/packages/seroval/test/web-api/headers.test.ts
new file mode 100644
index 00000000..026cd2c5
--- /dev/null
+++ b/packages/seroval/test/web-api/headers.test.ts
@@ -0,0 +1,65 @@
+import { describe, it, expect } from 'vitest';
+import 'node-fetch-native/polyfill';
+import {
+ deserialize,
+ fromJSON,
+ serialize,
+ serializeAsync,
+ toJSON,
+ toJSONAsync,
+} from '../../src';
+
+describe('Headers', () => {
+ describe('serialize', () => {
+ it('supports Headers', () => {
+ const example = new Headers([
+ ['Content-Type', 'text/plain'],
+ ['Content-Encoding', 'gzip'],
+ ]);
+ const result = serialize(example);
+ expect(result).toMatchSnapshot();
+ const back = deserialize(result);
+ expect(back).toBeInstanceOf(Headers);
+ expect(String(back)).toBe(String(example));
+ });
+ });
+ describe('serializeAsync', () => {
+ it('supports Headers', async () => {
+ const example = new Headers([
+ ['Content-Type', 'text/plain'],
+ ['Content-Encoding', 'gzip'],
+ ]);
+ const result = await serializeAsync(Promise.resolve(example));
+ expect(result).toMatchSnapshot();
+ const back = await deserialize>(result);
+ expect(back).toBeInstanceOf(Headers);
+ expect(String(back)).toBe(String(example));
+ });
+ });
+ describe('toJSON', () => {
+ it('supports Headers', () => {
+ const example = new Headers([
+ ['Content-Type', 'text/plain'],
+ ['Content-Encoding', 'gzip'],
+ ]);
+ const result = toJSON(example);
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = fromJSON(result);
+ expect(back).toBeInstanceOf(Headers);
+ expect(String(back)).toBe(String(example));
+ });
+ });
+ describe('toJSONAsync', () => {
+ it('supports Headers', async () => {
+ const example = new Headers([
+ ['Content-Type', 'text/plain'],
+ ['Content-Encoding', 'gzip'],
+ ]);
+ const result = await toJSONAsync(Promise.resolve(example));
+ expect(JSON.stringify(result)).toMatchSnapshot();
+ const back = await fromJSON>(result);
+ expect(back).toBeInstanceOf(Headers);
+ expect(String(back)).toBe(String(example));
+ });
+ });
+});
diff --git a/packages/seroval/test/url-search-params.test.ts b/packages/seroval/test/web-api/url-search-params.test.ts
similarity index 98%
rename from packages/seroval/test/url-search-params.test.ts
rename to packages/seroval/test/web-api/url-search-params.test.ts
index 321528a9..9cf5fdec 100644
--- a/packages/seroval/test/url-search-params.test.ts
+++ b/packages/seroval/test/web-api/url-search-params.test.ts
@@ -6,7 +6,7 @@ import {
serializeAsync,
toJSON,
toJSONAsync,
-} from '../src';
+} from '../../src';
describe('URLSearchParams', () => {
describe('serialize', () => {
diff --git a/packages/seroval/test/url.test.ts b/packages/seroval/test/web-api/url.test.ts
similarity index 98%
rename from packages/seroval/test/url.test.ts
rename to packages/seroval/test/web-api/url.test.ts
index c6c008b9..ef46d236 100644
--- a/packages/seroval/test/url.test.ts
+++ b/packages/seroval/test/web-api/url.test.ts
@@ -6,7 +6,7 @@ import {
serializeAsync,
toJSON,
toJSONAsync,
-} from '../src';
+} from '../../src';
describe('URL', () => {
describe('serialize', () => {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8bce2a6a..61b978c6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -80,6 +80,9 @@ importers:
eslint-config-lxsmnsyc:
specifier: ^0.5.1
version: 0.5.1(eslint@8.33.0)(typescript@4.9.5)
+ node-fetch-native:
+ specifier: ^1.1.0
+ version: 1.1.0
pridepack:
specifier: 2.4.1
version: 2.4.1(eslint@8.33.0)(tslib@2.5.0)(typescript@4.9.5)
@@ -3894,7 +3897,7 @@ packages:
dependencies:
confusing-browser-globals: 1.0.11
eslint: 8.33.0
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
object.assign: 4.1.4
object.entries: 1.1.6
semver: 6.3.0
@@ -3909,7 +3912,7 @@ packages:
dependencies:
confusing-browser-globals: 1.0.11
eslint: 8.36.0
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
object.assign: 4.1.4
object.entries: 1.1.6
semver: 6.3.0
@@ -3924,7 +3927,7 @@ packages:
dependencies:
confusing-browser-globals: 1.0.11
eslint: 8.38.0
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
object.assign: 4.1.4
object.entries: 1.1.6
semver: 6.3.0
@@ -3942,7 +3945,7 @@ packages:
dependencies:
eslint: 8.33.0
eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.33.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.33.0)
eslint-plugin-react: 7.32.2(eslint@8.33.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.33.0)
@@ -3962,7 +3965,7 @@ packages:
dependencies:
eslint: 8.36.0
eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.36.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.36.0)
eslint-plugin-react: 7.32.2(eslint@8.36.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.36.0)
@@ -3982,7 +3985,7 @@ packages:
dependencies:
eslint: 8.38.0
eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.38.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.38.0)
eslint-plugin-react: 7.32.2(eslint@8.38.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.38.0)
@@ -4005,7 +4008,7 @@ packages:
eslint-config-preact: 1.3.0(@typescript-eslint/eslint-plugin@5.55.0)(eslint@8.33.0)(typescript@4.9.5)
eslint-import-resolver-node: 0.3.7
eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.33.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.33.0)
eslint-plugin-react: 7.32.2(eslint@8.33.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.33.0)
@@ -4032,7 +4035,7 @@ packages:
eslint-config-preact: 1.3.0(@typescript-eslint/eslint-plugin@5.55.0)(eslint@8.36.0)(typescript@4.9.5)
eslint-import-resolver-node: 0.3.7
eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.36.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.36.0)
eslint-plugin-react: 7.32.2(eslint@8.36.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.36.0)
@@ -4059,7 +4062,7 @@ packages:
eslint-config-preact: 1.3.0(@typescript-eslint/eslint-plugin@5.55.0)(eslint@8.38.0)(typescript@4.9.5)
eslint-import-resolver-node: 0.3.7
eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.38.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.38.0)
eslint-plugin-react: 7.32.2(eslint@8.38.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.38.0)
@@ -4158,7 +4161,7 @@ packages:
enhanced-resolve: 5.12.0
eslint: 8.33.0
eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
get-tsconfig: 4.5.0
globby: 13.1.3
is-core-module: 2.11.0
@@ -4182,7 +4185,7 @@ packages:
enhanced-resolve: 5.12.0
eslint: 8.36.0
eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
get-tsconfig: 4.5.0
globby: 13.1.3
is-core-module: 2.11.0
@@ -4206,7 +4209,7 @@ packages:
enhanced-resolve: 5.12.0
eslint: 8.38.0
eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.38.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
get-tsconfig: 4.5.0
globby: 13.1.3
is-core-module: 2.11.0
@@ -4360,7 +4363,7 @@ packages:
semver: 7.3.5
dev: true
- /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0):
+ /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0):
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'}
peerDependencies:
@@ -4370,15 +4373,15 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
- '@typescript-eslint/parser': 5.55.0(eslint@8.33.0)(typescript@4.9.5)
+ '@typescript-eslint/parser': 5.55.0(eslint@8.36.0)(typescript@4.9.5)
array-includes: 3.1.6
array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1
debug: 3.2.7
doctrine: 2.1.0
- eslint: 8.33.0
+ eslint: 8.36.0
eslint-import-resolver-node: 0.3.7
- eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.33.0)
+ eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.55.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.36.0)
has: 1.0.3
is-core-module: 2.11.0
is-glob: 4.0.3
@@ -6610,6 +6613,10 @@ packages:
resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==}
dev: true
+ /node-fetch-native@1.1.0:
+ resolution: {integrity: sha512-nl5goFCig93JZ9FIV8GHT9xpNqXbxQUzkOmKIMKmncsBH9jhg7qKex8hirpymkBFmNQ114chEEG5lS4wgK2I+Q==}
+ dev: true
+
/node-fetch@2.6.9:
resolution: {integrity: sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==}
engines: {node: 4.x || >=6.0.0}