seroval 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -1
- package/dist/cjs/development/index.cjs +762 -228
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +762 -228
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/compat.d.ts +3 -2
- package/dist/types/context.d.ts +14 -9
- package/dist/types/index.d.ts +9 -9
- package/dist/types/string.d.ts +3 -0
- package/dist/types/tree/async.d.ts +1 -2
- package/dist/types/tree/deserialize.d.ts +1 -2
- package/dist/types/tree/primitives.d.ts +7 -3
- package/dist/types/tree/reference.d.ts +6 -0
- package/dist/types/tree/sync.d.ts +1 -2
- package/dist/types/tree/types.d.ts +73 -12
- package/dist/types/tree/web-api.d.ts +6 -0
- package/dist/types/types.d.ts +2 -1
- package/package.json +4 -3
- package/src/compat.ts +2 -1
- package/src/context.ts +19 -12
- package/src/index.ts +10 -16
- package/src/{quote.ts → string.ts} +27 -30
- package/src/tree/async.ts +164 -62
- package/src/tree/deserialize.ts +195 -67
- package/src/tree/primitives.ts +108 -22
- package/src/tree/reference.ts +61 -0
- package/src/tree/serialize.ts +236 -59
- package/src/tree/sync.ts +160 -55
- package/src/tree/types.ts +139 -14
- package/src/tree/web-api.ts +92 -0
- package/src/types.ts +6 -1
- package/dist/types/quote.d.ts +0 -2
package/src/index.ts
CHANGED
|
@@ -12,14 +12,6 @@ import deserializeTree from './tree/deserialize';
|
|
|
12
12
|
import serializeTree, { resolvePatches } from './tree/serialize';
|
|
13
13
|
import parseSync from './tree/sync';
|
|
14
14
|
import { SerovalNode } from './tree/types';
|
|
15
|
-
import {
|
|
16
|
-
AsyncServerValue,
|
|
17
|
-
PrimitiveValue,
|
|
18
|
-
ServerValue,
|
|
19
|
-
CommonServerValue,
|
|
20
|
-
SemiPrimitiveValue,
|
|
21
|
-
ErrorValue,
|
|
22
|
-
} from './types';
|
|
23
15
|
|
|
24
16
|
export {
|
|
25
17
|
AsyncServerValue,
|
|
@@ -28,8 +20,8 @@ export {
|
|
|
28
20
|
CommonServerValue,
|
|
29
21
|
SemiPrimitiveValue,
|
|
30
22
|
ErrorValue,
|
|
31
|
-
|
|
32
|
-
};
|
|
23
|
+
} from './types';
|
|
24
|
+
export { Feature } from './compat';
|
|
33
25
|
|
|
34
26
|
function finalize(
|
|
35
27
|
ctx: SerializationContext,
|
|
@@ -67,7 +59,7 @@ function finalize(
|
|
|
67
59
|
return result;
|
|
68
60
|
}
|
|
69
61
|
|
|
70
|
-
export function serialize<T
|
|
62
|
+
export function serialize<T>(
|
|
71
63
|
source: T,
|
|
72
64
|
options?: Partial<Options>,
|
|
73
65
|
) {
|
|
@@ -78,7 +70,7 @@ export function serialize<T extends ServerValue>(
|
|
|
78
70
|
return finalize(serial, rootID, isObject, result);
|
|
79
71
|
}
|
|
80
72
|
|
|
81
|
-
export async function serializeAsync<T
|
|
73
|
+
export async function serializeAsync<T>(
|
|
82
74
|
source: T,
|
|
83
75
|
options?: Partial<Options>,
|
|
84
76
|
) {
|
|
@@ -89,7 +81,7 @@ export async function serializeAsync<T extends AsyncServerValue>(
|
|
|
89
81
|
return finalize(serial, rootID, isObject, result);
|
|
90
82
|
}
|
|
91
83
|
|
|
92
|
-
export function deserialize<T
|
|
84
|
+
export function deserialize<T>(source: string): T {
|
|
93
85
|
// eslint-disable-next-line no-eval
|
|
94
86
|
return (0, eval)(source) as T;
|
|
95
87
|
}
|
|
@@ -102,7 +94,7 @@ export interface SerovalJSON {
|
|
|
102
94
|
m: number[],
|
|
103
95
|
}
|
|
104
96
|
|
|
105
|
-
export function toJSON<T
|
|
97
|
+
export function toJSON<T>(
|
|
106
98
|
source: T,
|
|
107
99
|
options?: Partial<Options>,
|
|
108
100
|
): SerovalJSON {
|
|
@@ -117,7 +109,7 @@ export function toJSON<T extends ServerValue>(
|
|
|
117
109
|
};
|
|
118
110
|
}
|
|
119
111
|
|
|
120
|
-
export async function toJSONAsync<T
|
|
112
|
+
export async function toJSONAsync<T>(
|
|
121
113
|
source: T,
|
|
122
114
|
options?: Partial<Options>,
|
|
123
115
|
): Promise<SerovalJSON> {
|
|
@@ -141,7 +133,7 @@ export function compileJSON(source: SerovalJSON): string {
|
|
|
141
133
|
return finalize(serial, source.r, source.i, result);
|
|
142
134
|
}
|
|
143
135
|
|
|
144
|
-
export function fromJSON<T
|
|
136
|
+
export function fromJSON<T>(source: SerovalJSON): T {
|
|
145
137
|
const serial = createSerializationContext({
|
|
146
138
|
features: source.f,
|
|
147
139
|
markedRefs: source.m,
|
|
@@ -150,3 +142,5 @@ export function fromJSON<T extends AsyncServerValue>(source: SerovalJSON): T {
|
|
|
150
142
|
}
|
|
151
143
|
|
|
152
144
|
export default serialize;
|
|
145
|
+
|
|
146
|
+
export { createReference } from './tree/reference';
|
|
@@ -1,40 +1,34 @@
|
|
|
1
|
+
export function serializeChar(str: string) {
|
|
2
|
+
switch (str) {
|
|
3
|
+
case '"': return '\\"';
|
|
4
|
+
case '\\': return '\\\\';
|
|
5
|
+
case '\n': return '\\n';
|
|
6
|
+
case '\r': return '\\r';
|
|
7
|
+
case '\b': return '\\b';
|
|
8
|
+
case '\t': return '\\t';
|
|
9
|
+
case '\f': return '\\f';
|
|
10
|
+
case '<': return '\\x3C';
|
|
11
|
+
case '\u2028': return '\\u2028';
|
|
12
|
+
case '\u2029': return '\\u2029';
|
|
13
|
+
default: return undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
1
17
|
// Written by https://github.com/DylanPiercey and is distributed under the MIT license.
|
|
2
18
|
// Creates a JavaScript double quoted string and escapes all characters
|
|
3
19
|
// not listed as DoubleStringCharacters on
|
|
4
20
|
// Also includes "<" to escape "</script>" and "\" to avoid invalid escapes in the output.
|
|
5
21
|
// http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
|
|
6
|
-
export
|
|
22
|
+
export function serializeString(str: string) {
|
|
7
23
|
let result = '';
|
|
8
24
|
let lastPos = 0;
|
|
25
|
+
let replacement: string | undefined;
|
|
9
26
|
for (let i = 0, len = str.length; i < len; i++) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
break;
|
|
15
|
-
case '\\':
|
|
16
|
-
replacement = '\\\\';
|
|
17
|
-
break;
|
|
18
|
-
case '<':
|
|
19
|
-
replacement = '\\x3C';
|
|
20
|
-
break;
|
|
21
|
-
case '\n':
|
|
22
|
-
replacement = '\\n';
|
|
23
|
-
break;
|
|
24
|
-
case '\r':
|
|
25
|
-
replacement = '\\r';
|
|
26
|
-
break;
|
|
27
|
-
case '\u2028':
|
|
28
|
-
replacement = '\\u2028';
|
|
29
|
-
break;
|
|
30
|
-
case '\u2029':
|
|
31
|
-
replacement = '\\u2029';
|
|
32
|
-
break;
|
|
33
|
-
default:
|
|
34
|
-
continue;
|
|
27
|
+
replacement = serializeChar(str[i]);
|
|
28
|
+
if (replacement) {
|
|
29
|
+
result += str.slice(lastPos, i) + replacement;
|
|
30
|
+
lastPos = i + 1;
|
|
35
31
|
}
|
|
36
|
-
result += str.slice(lastPos, i) + replacement;
|
|
37
|
-
lastPos = i + 1;
|
|
38
32
|
}
|
|
39
33
|
if (lastPos === 0) {
|
|
40
34
|
result = str;
|
|
@@ -44,13 +38,16 @@ export default function quote(str: string) {
|
|
|
44
38
|
return result;
|
|
45
39
|
}
|
|
46
40
|
|
|
47
|
-
export function
|
|
41
|
+
export function deserializeString(str: string): string {
|
|
48
42
|
return str
|
|
49
43
|
.replace(/\\"/g, '"')
|
|
50
44
|
.replace(/\\\\/g, '\\')
|
|
51
|
-
.replace(/\\x3C/g, '<')
|
|
52
45
|
.replace(/\\n/g, '\n')
|
|
53
46
|
.replace(/\\r/g, '\r')
|
|
47
|
+
.replace(/\\b/g, '\b')
|
|
48
|
+
.replace(/\\t/g, '\t')
|
|
49
|
+
.replace(/\\f/g, '\f')
|
|
50
|
+
.replace(/\\x3C/g, '<')
|
|
54
51
|
.replace(/\\u2028/g, '\u2028')
|
|
55
52
|
.replace(/\\u2029/g, '\u2029');
|
|
56
53
|
}
|
package/src/tree/async.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
3
3
|
import assert from '../assert';
|
|
4
4
|
import { Feature } from '../compat';
|
|
5
|
-
import {
|
|
5
|
+
import { createIndexedValue, getRootID, ParserContext } from '../context';
|
|
6
|
+
import { serializeString } from '../string';
|
|
6
7
|
import {
|
|
7
|
-
AsyncServerValue,
|
|
8
8
|
BigIntTypedArrayValue,
|
|
9
9
|
TypedArrayValue,
|
|
10
10
|
} from '../types';
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
createBigIntTypedArrayNode,
|
|
14
14
|
createDateNode,
|
|
15
15
|
createNumberNode,
|
|
16
|
-
|
|
16
|
+
createIndexedValueNode,
|
|
17
17
|
createRegExpNode,
|
|
18
18
|
createStringNode,
|
|
19
19
|
createTypedArrayNode,
|
|
@@ -26,18 +26,24 @@ import {
|
|
|
26
26
|
NULL_NODE,
|
|
27
27
|
TRUE_NODE,
|
|
28
28
|
UNDEFINED_NODE,
|
|
29
|
+
createReferenceNode,
|
|
30
|
+
createArrayBufferNode,
|
|
31
|
+
createDataViewNode,
|
|
29
32
|
} from './primitives';
|
|
33
|
+
import { hasReferenceID } from './reference';
|
|
30
34
|
import {
|
|
31
35
|
getErrorConstructorName,
|
|
32
36
|
getErrorOptions,
|
|
33
37
|
getIterableOptions,
|
|
34
38
|
isIterable,
|
|
35
39
|
} from './shared';
|
|
36
|
-
import {
|
|
40
|
+
import { WellKnownSymbols } from './symbols';
|
|
37
41
|
import {
|
|
38
42
|
SerovalAggregateErrorNode,
|
|
39
43
|
SerovalArrayNode,
|
|
40
44
|
SerovalErrorNode,
|
|
45
|
+
SerovalFormDataNode,
|
|
46
|
+
SerovalHeadersNode,
|
|
41
47
|
SerovalIterableNode,
|
|
42
48
|
SerovalMapNode,
|
|
43
49
|
SerovalNode,
|
|
@@ -48,6 +54,12 @@ import {
|
|
|
48
54
|
SerovalPromiseNode,
|
|
49
55
|
SerovalSetNode,
|
|
50
56
|
} from './types';
|
|
57
|
+
import {
|
|
58
|
+
createBlobNode,
|
|
59
|
+
createFileNode,
|
|
60
|
+
createURLNode,
|
|
61
|
+
createURLSearchParamsNode,
|
|
62
|
+
} from './web-api';
|
|
51
63
|
|
|
52
64
|
type ObjectLikeNode =
|
|
53
65
|
| SerovalObjectNode
|
|
@@ -56,18 +68,18 @@ type ObjectLikeNode =
|
|
|
56
68
|
| SerovalPromiseNode;
|
|
57
69
|
|
|
58
70
|
type ObjectLikeValue =
|
|
59
|
-
| Record<string,
|
|
60
|
-
| Iterable<
|
|
61
|
-
| PromiseLike<
|
|
71
|
+
| Record<string, unknown>
|
|
72
|
+
| Iterable<unknown>
|
|
73
|
+
| PromiseLike<unknown>;
|
|
62
74
|
|
|
63
75
|
async function generateNodeList(
|
|
64
76
|
ctx: ParserContext,
|
|
65
|
-
current:
|
|
77
|
+
current: unknown[],
|
|
66
78
|
) {
|
|
67
79
|
const size = current.length;
|
|
68
80
|
const nodes = new Array<SerovalNode>(size);
|
|
69
|
-
const deferred = new Array<
|
|
70
|
-
let item:
|
|
81
|
+
const deferred = new Array<unknown>(size);
|
|
82
|
+
let item: unknown;
|
|
71
83
|
for (let i = 0; i < size; i++) {
|
|
72
84
|
if (i in current) {
|
|
73
85
|
item = current[i];
|
|
@@ -89,7 +101,7 @@ async function generateNodeList(
|
|
|
89
101
|
async function generateArrayNode(
|
|
90
102
|
ctx: ParserContext,
|
|
91
103
|
id: number,
|
|
92
|
-
current:
|
|
104
|
+
current: unknown[],
|
|
93
105
|
): Promise<SerovalArrayNode> {
|
|
94
106
|
return {
|
|
95
107
|
t: SerovalNodeType.Array,
|
|
@@ -101,20 +113,21 @@ async function generateArrayNode(
|
|
|
101
113
|
d: undefined,
|
|
102
114
|
a: await generateNodeList(ctx, current),
|
|
103
115
|
f: undefined,
|
|
116
|
+
b: undefined,
|
|
104
117
|
};
|
|
105
118
|
}
|
|
106
119
|
|
|
107
120
|
async function generateMapNode(
|
|
108
121
|
ctx: ParserContext,
|
|
109
122
|
id: number,
|
|
110
|
-
current: Map<
|
|
123
|
+
current: Map<unknown, unknown>,
|
|
111
124
|
): Promise<SerovalMapNode> {
|
|
112
125
|
assert(ctx.features & Feature.Map, 'Unsupported type "Map"');
|
|
113
126
|
const len = current.size;
|
|
114
127
|
const keyNodes = new Array<SerovalNode>(len);
|
|
115
128
|
const valueNodes = new Array<SerovalNode>(len);
|
|
116
|
-
const deferredKey = new Array<
|
|
117
|
-
const deferredValue = new Array<
|
|
129
|
+
const deferredKey = new Array<unknown>(len);
|
|
130
|
+
const deferredValue = new Array<unknown>(len);
|
|
118
131
|
let deferredSize = 0;
|
|
119
132
|
let nodeSize = 0;
|
|
120
133
|
for (const [key, value] of current.entries()) {
|
|
@@ -143,18 +156,19 @@ async function generateMapNode(
|
|
|
143
156
|
d: { k: keyNodes, v: valueNodes, s: len },
|
|
144
157
|
a: undefined,
|
|
145
158
|
f: undefined,
|
|
159
|
+
b: undefined,
|
|
146
160
|
};
|
|
147
161
|
}
|
|
148
162
|
|
|
149
163
|
async function generateSetNode(
|
|
150
164
|
ctx: ParserContext,
|
|
151
165
|
id: number,
|
|
152
|
-
current: Set<
|
|
166
|
+
current: Set<unknown>,
|
|
153
167
|
): Promise<SerovalSetNode> {
|
|
154
168
|
assert(ctx.features & Feature.Set, 'Unsupported type "Set"');
|
|
155
169
|
const len = current.size;
|
|
156
170
|
const nodes = new Array<SerovalNode>(len);
|
|
157
|
-
const deferred = new Array<
|
|
171
|
+
const deferred = new Array<unknown>(len);
|
|
158
172
|
let deferredSize = 0;
|
|
159
173
|
let nodeSize = 0;
|
|
160
174
|
for (const item of current.keys()) {
|
|
@@ -179,30 +193,33 @@ async function generateSetNode(
|
|
|
179
193
|
d: undefined,
|
|
180
194
|
a: nodes,
|
|
181
195
|
f: undefined,
|
|
196
|
+
b: undefined,
|
|
182
197
|
};
|
|
183
198
|
}
|
|
184
199
|
|
|
185
200
|
async function generateProperties(
|
|
186
201
|
ctx: ParserContext,
|
|
187
|
-
properties: Record<string,
|
|
202
|
+
properties: Record<string, unknown>,
|
|
188
203
|
): Promise<SerovalObjectRecordNode> {
|
|
189
204
|
const keys = Object.keys(properties);
|
|
190
205
|
const size = keys.length;
|
|
191
206
|
const keyNodes = new Array<string>(size);
|
|
192
207
|
const valueNodes = new Array<SerovalNode>(size);
|
|
193
208
|
const deferredKeys = new Array<string>(size);
|
|
194
|
-
const deferredValues = new Array<
|
|
209
|
+
const deferredValues = new Array<unknown>(size);
|
|
195
210
|
let deferredSize = 0;
|
|
196
211
|
let nodesSize = 0;
|
|
197
|
-
let item:
|
|
212
|
+
let item: unknown;
|
|
213
|
+
let escaped: string;
|
|
198
214
|
for (const key of keys) {
|
|
199
215
|
item = properties[key];
|
|
216
|
+
escaped = serializeString(key);
|
|
200
217
|
if (isIterable(item)) {
|
|
201
|
-
deferredKeys[deferredSize] =
|
|
218
|
+
deferredKeys[deferredSize] = escaped;
|
|
202
219
|
deferredValues[deferredSize] = item;
|
|
203
220
|
deferredSize++;
|
|
204
221
|
} else {
|
|
205
|
-
keyNodes[nodesSize] =
|
|
222
|
+
keyNodes[nodesSize] = escaped;
|
|
206
223
|
valueNodes[nodesSize] = await parse(ctx, item);
|
|
207
224
|
nodesSize++;
|
|
208
225
|
}
|
|
@@ -221,7 +238,7 @@ async function generateProperties(
|
|
|
221
238
|
async function generateIterableNode(
|
|
222
239
|
ctx: ParserContext,
|
|
223
240
|
id: number,
|
|
224
|
-
current: Iterable<
|
|
241
|
+
current: Iterable<unknown>,
|
|
225
242
|
): Promise<SerovalIterableNode> {
|
|
226
243
|
assert(ctx.features & Feature.Symbol, 'Unsupported type "Iterable"');
|
|
227
244
|
const options = getIterableOptions(current);
|
|
@@ -235,17 +252,18 @@ async function generateIterableNode(
|
|
|
235
252
|
m: undefined,
|
|
236
253
|
// Parse options first before the items
|
|
237
254
|
d: options
|
|
238
|
-
? await generateProperties(ctx, options
|
|
255
|
+
? await generateProperties(ctx, options)
|
|
239
256
|
: undefined,
|
|
240
257
|
a: await generateNodeList(ctx, array),
|
|
241
258
|
f: undefined,
|
|
259
|
+
b: undefined,
|
|
242
260
|
};
|
|
243
261
|
}
|
|
244
262
|
|
|
245
263
|
async function generatePromiseNode(
|
|
246
264
|
ctx: ParserContext,
|
|
247
265
|
id: number,
|
|
248
|
-
current: PromiseLike<
|
|
266
|
+
current: PromiseLike<unknown>,
|
|
249
267
|
): Promise<SerovalPromiseNode> {
|
|
250
268
|
assert(ctx.features & Feature.Promise, 'Unsupported type "Promise"');
|
|
251
269
|
return current.then(async (value) => ({
|
|
@@ -259,6 +277,7 @@ async function generatePromiseNode(
|
|
|
259
277
|
d: undefined,
|
|
260
278
|
a: undefined,
|
|
261
279
|
f: await parse(ctx, value),
|
|
280
|
+
b: undefined,
|
|
262
281
|
}));
|
|
263
282
|
}
|
|
264
283
|
|
|
@@ -272,7 +291,7 @@ async function generateObjectNode(
|
|
|
272
291
|
return generateIterableNode(ctx, id, current);
|
|
273
292
|
}
|
|
274
293
|
if ('then' in current && typeof current.then === 'function') {
|
|
275
|
-
return generatePromiseNode(ctx, id, current as PromiseLike<
|
|
294
|
+
return generatePromiseNode(ctx, id, current as PromiseLike<unknown>);
|
|
276
295
|
}
|
|
277
296
|
return {
|
|
278
297
|
t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
@@ -281,9 +300,10 @@ async function generateObjectNode(
|
|
|
281
300
|
l: undefined,
|
|
282
301
|
c: undefined,
|
|
283
302
|
m: undefined,
|
|
284
|
-
d: await generateProperties(ctx, current as Record<string,
|
|
303
|
+
d: await generateProperties(ctx, current as Record<string, unknown>),
|
|
285
304
|
a: undefined,
|
|
286
305
|
f: undefined,
|
|
306
|
+
b: undefined,
|
|
287
307
|
};
|
|
288
308
|
}
|
|
289
309
|
|
|
@@ -300,12 +320,13 @@ async function generateAggregateErrorNode(
|
|
|
300
320
|
t: SerovalNodeType.AggregateError,
|
|
301
321
|
i: id,
|
|
302
322
|
s: undefined,
|
|
303
|
-
l:
|
|
323
|
+
l: undefined,
|
|
304
324
|
c: undefined,
|
|
305
|
-
m: current.message,
|
|
325
|
+
m: serializeString(current.message),
|
|
306
326
|
d: optionsNode,
|
|
307
|
-
a:
|
|
327
|
+
a: undefined,
|
|
308
328
|
f: undefined,
|
|
329
|
+
b: undefined,
|
|
309
330
|
};
|
|
310
331
|
}
|
|
311
332
|
|
|
@@ -324,16 +345,65 @@ async function generateErrorNode(
|
|
|
324
345
|
s: undefined,
|
|
325
346
|
l: undefined,
|
|
326
347
|
c: getErrorConstructorName(current),
|
|
327
|
-
m: current.message,
|
|
348
|
+
m: serializeString(current.message),
|
|
328
349
|
d: optionsNode,
|
|
329
350
|
a: undefined,
|
|
330
351
|
f: undefined,
|
|
352
|
+
b: undefined,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async function generateHeadersNode(
|
|
357
|
+
ctx: ParserContext,
|
|
358
|
+
id: number,
|
|
359
|
+
current: Headers,
|
|
360
|
+
): Promise<SerovalHeadersNode> {
|
|
361
|
+
assert(ctx.features & Feature.WebAPI, 'Unsupported type "Headers"');
|
|
362
|
+
const items: Record<string, string> = {};
|
|
363
|
+
current.forEach((value, key) => {
|
|
364
|
+
items[key] = value;
|
|
365
|
+
});
|
|
366
|
+
return {
|
|
367
|
+
t: SerovalNodeType.Headers,
|
|
368
|
+
i: id,
|
|
369
|
+
s: undefined,
|
|
370
|
+
l: undefined,
|
|
371
|
+
c: undefined,
|
|
372
|
+
m: undefined,
|
|
373
|
+
d: await generateProperties(ctx, items),
|
|
374
|
+
a: undefined,
|
|
375
|
+
f: undefined,
|
|
376
|
+
b: undefined,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async function generateFormDataNode(
|
|
381
|
+
ctx: ParserContext,
|
|
382
|
+
id: number,
|
|
383
|
+
current: FormData,
|
|
384
|
+
): Promise<SerovalFormDataNode> {
|
|
385
|
+
assert(ctx.features & Feature.WebAPI, 'Unsupported type "FormData"');
|
|
386
|
+
const items: Record<string, FormDataEntryValue> = {};
|
|
387
|
+
current.forEach((value, key) => {
|
|
388
|
+
items[key] = value;
|
|
389
|
+
});
|
|
390
|
+
return {
|
|
391
|
+
t: SerovalNodeType.FormData,
|
|
392
|
+
i: id,
|
|
393
|
+
s: undefined,
|
|
394
|
+
l: undefined,
|
|
395
|
+
c: undefined,
|
|
396
|
+
m: undefined,
|
|
397
|
+
d: await generateProperties(ctx, items),
|
|
398
|
+
a: undefined,
|
|
399
|
+
f: undefined,
|
|
400
|
+
b: undefined,
|
|
331
401
|
};
|
|
332
402
|
}
|
|
333
403
|
|
|
334
|
-
async function parse(
|
|
404
|
+
async function parse<T>(
|
|
335
405
|
ctx: ParserContext,
|
|
336
|
-
current:
|
|
406
|
+
current: T,
|
|
337
407
|
): Promise<SerovalNode> {
|
|
338
408
|
switch (typeof current) {
|
|
339
409
|
case 'boolean':
|
|
@@ -346,16 +416,16 @@ async function parse(
|
|
|
346
416
|
switch (current) {
|
|
347
417
|
case Infinity: return INFINITY_NODE;
|
|
348
418
|
case -Infinity: return NEG_INFINITY_NODE;
|
|
349
|
-
default:
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
419
|
+
default:
|
|
420
|
+
// eslint-disable-next-line no-self-compare
|
|
421
|
+
if (current !== current) {
|
|
422
|
+
return NAN_NODE;
|
|
423
|
+
}
|
|
424
|
+
if (Object.is(current, -0)) {
|
|
425
|
+
return NEG_ZERO_NODE;
|
|
426
|
+
}
|
|
427
|
+
return createNumberNode(current);
|
|
357
428
|
}
|
|
358
|
-
return createNumberNode(current);
|
|
359
429
|
case 'bigint':
|
|
360
430
|
return createBigIntNode(ctx, current);
|
|
361
431
|
case 'object': {
|
|
@@ -364,20 +434,25 @@ async function parse(
|
|
|
364
434
|
}
|
|
365
435
|
// Non-primitive values needs a reference ID
|
|
366
436
|
// mostly because the values themselves are stateful
|
|
367
|
-
const id =
|
|
437
|
+
const id = createIndexedValue(ctx, current);
|
|
368
438
|
if (ctx.markedRefs.has(id)) {
|
|
369
|
-
return
|
|
439
|
+
return createIndexedValueNode(id);
|
|
440
|
+
}
|
|
441
|
+
if (hasReferenceID(current)) {
|
|
442
|
+
return createReferenceNode(id, current);
|
|
370
443
|
}
|
|
371
444
|
if (Array.isArray(current)) {
|
|
372
445
|
return generateArrayNode(ctx, id, current);
|
|
373
446
|
}
|
|
374
447
|
switch (current.constructor) {
|
|
375
448
|
case Date:
|
|
376
|
-
return createDateNode(id, current as Date);
|
|
449
|
+
return createDateNode(id, current as unknown as Date);
|
|
377
450
|
case RegExp:
|
|
378
|
-
return createRegExpNode(id, current as RegExp);
|
|
451
|
+
return createRegExpNode(id, current as unknown as RegExp);
|
|
379
452
|
case Promise:
|
|
380
|
-
return generatePromiseNode(ctx, id, current as Promise<
|
|
453
|
+
return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
|
|
454
|
+
case ArrayBuffer:
|
|
455
|
+
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
381
456
|
case Int8Array:
|
|
382
457
|
case Int16Array:
|
|
383
458
|
case Int32Array:
|
|
@@ -387,41 +462,43 @@ async function parse(
|
|
|
387
462
|
case Uint8ClampedArray:
|
|
388
463
|
case Float32Array:
|
|
389
464
|
case Float64Array:
|
|
390
|
-
return createTypedArrayNode(ctx, id, current as TypedArrayValue);
|
|
465
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
391
466
|
case BigInt64Array:
|
|
392
467
|
case BigUint64Array:
|
|
393
|
-
return createBigIntTypedArrayNode(ctx, id, current as BigIntTypedArrayValue);
|
|
468
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
469
|
+
case DataView:
|
|
470
|
+
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
394
471
|
case Map:
|
|
395
472
|
return generateMapNode(
|
|
396
473
|
ctx,
|
|
397
474
|
id,
|
|
398
|
-
current as Map<
|
|
475
|
+
current as unknown as Map<unknown, unknown>,
|
|
399
476
|
);
|
|
400
477
|
case Set:
|
|
401
478
|
return generateSetNode(
|
|
402
479
|
ctx,
|
|
403
480
|
id,
|
|
404
|
-
current as Set<
|
|
481
|
+
current as unknown as Set<unknown>,
|
|
405
482
|
);
|
|
406
483
|
case Object:
|
|
407
484
|
return generateObjectNode(
|
|
408
485
|
ctx,
|
|
409
486
|
id,
|
|
410
|
-
current as Record<string,
|
|
487
|
+
current as Record<string, unknown>,
|
|
411
488
|
false,
|
|
412
489
|
);
|
|
413
490
|
case undefined:
|
|
414
491
|
return generateObjectNode(
|
|
415
492
|
ctx,
|
|
416
493
|
id,
|
|
417
|
-
current as Record<string,
|
|
494
|
+
current as Record<string, unknown>,
|
|
418
495
|
true,
|
|
419
496
|
);
|
|
420
497
|
case AggregateError:
|
|
421
498
|
if (ctx.features & Feature.AggregateError) {
|
|
422
|
-
return generateAggregateErrorNode(ctx, id, current as AggregateError);
|
|
499
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
423
500
|
}
|
|
424
|
-
return generateErrorNode(ctx, id, current as AggregateError);
|
|
501
|
+
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
425
502
|
case Error:
|
|
426
503
|
case EvalError:
|
|
427
504
|
case RangeError:
|
|
@@ -429,7 +506,19 @@ async function parse(
|
|
|
429
506
|
case SyntaxError:
|
|
430
507
|
case TypeError:
|
|
431
508
|
case URIError:
|
|
432
|
-
return generateErrorNode(ctx, id, current as Error);
|
|
509
|
+
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
510
|
+
case URL:
|
|
511
|
+
return createURLNode(ctx, id, current as unknown as URL);
|
|
512
|
+
case URLSearchParams:
|
|
513
|
+
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
514
|
+
case Blob:
|
|
515
|
+
return createBlobNode(ctx, id, current as unknown as Blob);
|
|
516
|
+
case File:
|
|
517
|
+
return createFileNode(ctx, id, current as unknown as File);
|
|
518
|
+
case Headers:
|
|
519
|
+
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
520
|
+
case FormData:
|
|
521
|
+
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
433
522
|
default:
|
|
434
523
|
break;
|
|
435
524
|
}
|
|
@@ -447,26 +536,39 @@ async function parse(
|
|
|
447
536
|
}
|
|
448
537
|
// Generator functions don't have a global constructor
|
|
449
538
|
if (Symbol.iterator in current) {
|
|
450
|
-
return generateIterableNode(ctx, id, current);
|
|
539
|
+
return generateIterableNode(ctx, id, current as Iterable<unknown>);
|
|
451
540
|
}
|
|
452
541
|
// For Promise-like objects
|
|
453
542
|
if ('then' in current && typeof current.then === 'function') {
|
|
454
|
-
return generatePromiseNode(ctx, id, current as PromiseLike<
|
|
543
|
+
return generatePromiseNode(ctx, id, current as PromiseLike<unknown>);
|
|
455
544
|
}
|
|
456
545
|
throw new Error('Unsupported type');
|
|
457
546
|
}
|
|
458
547
|
case 'symbol':
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
548
|
+
if (hasReferenceID(current)) {
|
|
549
|
+
const id = createIndexedValue(ctx, current);
|
|
550
|
+
if (ctx.markedRefs.has(id)) {
|
|
551
|
+
return createIndexedValueNode(id);
|
|
552
|
+
}
|
|
553
|
+
return createReferenceNode(id, current);
|
|
554
|
+
}
|
|
555
|
+
return createWKSymbolNode(ctx, current as WellKnownSymbols);
|
|
556
|
+
case 'function': {
|
|
557
|
+
assert(hasReferenceID(current), 'Cannot serialize function without reference ID.');
|
|
558
|
+
const id = createIndexedValue(ctx, current);
|
|
559
|
+
if (ctx.markedRefs.has(id)) {
|
|
560
|
+
return createIndexedValueNode(id);
|
|
561
|
+
}
|
|
562
|
+
return createReferenceNode(id, current);
|
|
563
|
+
}
|
|
462
564
|
default:
|
|
463
565
|
throw new Error('Unsupported type');
|
|
464
566
|
}
|
|
465
567
|
}
|
|
466
568
|
|
|
467
|
-
export default async function parseAsync(
|
|
569
|
+
export default async function parseAsync<T>(
|
|
468
570
|
ctx: ParserContext,
|
|
469
|
-
current:
|
|
571
|
+
current: T,
|
|
470
572
|
) {
|
|
471
573
|
const result = await parse(ctx, current);
|
|
472
574
|
const isObject = result.t === SerovalNodeType.Object
|