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}