seroval 0.7.0 → 0.9.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/dist/cjs/development/index.cjs +1247 -1069
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +1247 -1069
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/assert.d.ts +1 -1
- package/dist/types/context.d.ts +8 -2
- package/dist/types/index.d.ts +3 -4
- package/dist/types/string.d.ts +1 -1
- package/dist/types/tree/UnsupportedTypeError.d.ts +3 -0
- package/dist/types/tree/async.d.ts +3 -3
- package/dist/types/tree/constants.d.ts +11 -0
- package/dist/types/tree/deserialize.d.ts +2 -2
- package/dist/types/tree/primitives.d.ts +9 -15
- package/dist/types/tree/serialize.d.ts +2 -2
- package/dist/types/tree/shared.d.ts +12 -8
- package/dist/types/tree/sync.d.ts +3 -3
- package/dist/types/tree/types.d.ts +74 -71
- package/dist/types/tree/web-api.d.ts +2 -2
- package/dist/types/types.d.ts +4 -4
- package/package.json +11 -9
- package/src/assert.ts +2 -2
- package/src/compat.ts +0 -1
- package/src/context.ts +20 -7
- package/src/get-identifier.ts +1 -1
- package/src/index.ts +35 -26
- package/src/string.ts +2 -2
- package/src/tree/UnsupportedTypeError.ts +8 -0
- package/src/tree/async.ts +256 -233
- package/src/tree/constants.ts +73 -0
- package/src/tree/deserialize.ts +112 -93
- package/src/tree/primitives.ts +93 -134
- package/src/tree/reference.ts +3 -3
- package/src/tree/serialize.ts +307 -201
- package/src/tree/shared.ts +45 -22
- package/src/tree/symbols.ts +13 -13
- package/src/tree/sync.ts +236 -198
- package/src/tree/types.ts +87 -94
- package/src/tree/web-api.ts +14 -7
- package/src/types.ts +7 -3
- package/src/tree/iterator.ts +0 -14
package/src/tree/sync.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
import assert from '../assert';
|
|
3
3
|
import { Feature } from '../compat';
|
|
4
|
-
import {
|
|
4
|
+
import type { ParserContext } from '../context';
|
|
5
|
+
import { createIndexedValue } from '../context';
|
|
5
6
|
import { serializeString } from '../string';
|
|
6
|
-
import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
|
|
7
|
+
import type { BigIntTypedArrayValue, TypedArrayValue } from '../types';
|
|
8
|
+
import UnsupportedTypeError from './UnsupportedTypeError';
|
|
9
|
+
import {
|
|
10
|
+
TRUE_NODE,
|
|
11
|
+
FALSE_NODE,
|
|
12
|
+
UNDEFINED_NODE,
|
|
13
|
+
NULL_NODE,
|
|
14
|
+
} from './constants';
|
|
7
15
|
import {
|
|
8
16
|
createBigIntNode,
|
|
9
17
|
createBigIntTypedArrayNode,
|
|
@@ -13,18 +21,11 @@ import {
|
|
|
13
21
|
createRegExpNode,
|
|
14
22
|
createStringNode,
|
|
15
23
|
createTypedArrayNode,
|
|
16
|
-
createWKSymbolNode,
|
|
17
|
-
FALSE_NODE,
|
|
18
|
-
INFINITY_NODE,
|
|
19
|
-
NAN_NODE,
|
|
20
|
-
NEG_INFINITY_NODE,
|
|
21
|
-
NEG_ZERO_NODE,
|
|
22
|
-
NULL_NODE,
|
|
23
|
-
TRUE_NODE,
|
|
24
|
-
UNDEFINED_NODE,
|
|
25
24
|
createReferenceNode,
|
|
26
25
|
createArrayBufferNode,
|
|
27
26
|
createDataViewNode,
|
|
27
|
+
createSymbolNode,
|
|
28
|
+
createFunctionNode,
|
|
28
29
|
} from './primitives';
|
|
29
30
|
import {
|
|
30
31
|
hasReferenceID,
|
|
@@ -32,30 +33,34 @@ import {
|
|
|
32
33
|
import {
|
|
33
34
|
getErrorConstructorName,
|
|
34
35
|
getErrorOptions,
|
|
35
|
-
|
|
36
|
+
getObjectFlag,
|
|
36
37
|
isIterable,
|
|
37
38
|
} from './shared';
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
39
|
+
import type {
|
|
40
40
|
SerovalAggregateErrorNode,
|
|
41
41
|
SerovalArrayNode,
|
|
42
|
+
SerovalBoxedNode,
|
|
42
43
|
SerovalErrorNode,
|
|
43
44
|
SerovalFormDataNode,
|
|
44
45
|
SerovalHeadersNode,
|
|
45
|
-
SerovalIterableNode,
|
|
46
46
|
SerovalMapNode,
|
|
47
47
|
SerovalNode,
|
|
48
|
-
SerovalNodeType,
|
|
49
48
|
SerovalNullConstructorNode,
|
|
50
49
|
SerovalObjectNode,
|
|
50
|
+
SerovalObjectRecordKey,
|
|
51
51
|
SerovalObjectRecordNode,
|
|
52
|
+
SerovalPlainRecordNode,
|
|
52
53
|
SerovalSetNode,
|
|
53
54
|
} from './types';
|
|
55
|
+
import {
|
|
56
|
+
SerovalNodeType,
|
|
57
|
+
SerovalObjectRecordSpecialKey,
|
|
58
|
+
} from './types';
|
|
54
59
|
import { createURLNode, createURLSearchParamsNode } from './web-api';
|
|
55
60
|
|
|
56
|
-
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode
|
|
61
|
+
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
|
|
57
62
|
|
|
58
|
-
function generateNodeList(ctx: ParserContext, current: unknown[]) {
|
|
63
|
+
function generateNodeList(ctx: ParserContext, current: unknown[]): SerovalNode[] {
|
|
59
64
|
const size = current.length;
|
|
60
65
|
const nodes = new Array<SerovalNode>(size);
|
|
61
66
|
const deferred = new Array<unknown>(size);
|
|
@@ -66,13 +71,13 @@ function generateNodeList(ctx: ParserContext, current: unknown[]) {
|
|
|
66
71
|
if (isIterable(item)) {
|
|
67
72
|
deferred[i] = item;
|
|
68
73
|
} else {
|
|
69
|
-
nodes[i] =
|
|
74
|
+
nodes[i] = parseSync(ctx, item);
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
78
|
for (let i = 0; i < size; i++) {
|
|
74
79
|
if (i in deferred) {
|
|
75
|
-
nodes[i] =
|
|
80
|
+
nodes[i] = parseSync(ctx, deferred[i]);
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
return nodes;
|
|
@@ -94,6 +99,7 @@ function generateArrayNode(
|
|
|
94
99
|
a: generateNodeList(ctx, current),
|
|
95
100
|
f: undefined,
|
|
96
101
|
b: undefined,
|
|
102
|
+
o: getObjectFlag(current),
|
|
97
103
|
};
|
|
98
104
|
}
|
|
99
105
|
|
|
@@ -102,7 +108,7 @@ function generateMapNode(
|
|
|
102
108
|
id: number,
|
|
103
109
|
current: Map<unknown, unknown>,
|
|
104
110
|
): SerovalMapNode {
|
|
105
|
-
assert(ctx.features & Feature.Map,
|
|
111
|
+
assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
|
|
106
112
|
const len = current.size;
|
|
107
113
|
const keyNodes = new Array<SerovalNode>(len);
|
|
108
114
|
const valueNodes = new Array<SerovalNode>(len);
|
|
@@ -117,14 +123,14 @@ function generateMapNode(
|
|
|
117
123
|
deferredValue[deferredSize] = value;
|
|
118
124
|
deferredSize++;
|
|
119
125
|
} else {
|
|
120
|
-
keyNodes[nodeSize] =
|
|
121
|
-
valueNodes[nodeSize] =
|
|
126
|
+
keyNodes[nodeSize] = parseSync(ctx, key);
|
|
127
|
+
valueNodes[nodeSize] = parseSync(ctx, value);
|
|
122
128
|
nodeSize++;
|
|
123
129
|
}
|
|
124
130
|
}
|
|
125
131
|
for (let i = 0; i < deferredSize; i++) {
|
|
126
|
-
keyNodes[nodeSize + i] =
|
|
127
|
-
valueNodes[nodeSize + i] =
|
|
132
|
+
keyNodes[nodeSize + i] = parseSync(ctx, deferredKey[i]);
|
|
133
|
+
valueNodes[nodeSize + i] = parseSync(ctx, deferredValue[i]);
|
|
128
134
|
}
|
|
129
135
|
return {
|
|
130
136
|
t: SerovalNodeType.Map,
|
|
@@ -137,6 +143,7 @@ function generateMapNode(
|
|
|
137
143
|
a: undefined,
|
|
138
144
|
f: undefined,
|
|
139
145
|
b: undefined,
|
|
146
|
+
o: undefined,
|
|
140
147
|
};
|
|
141
148
|
}
|
|
142
149
|
|
|
@@ -145,7 +152,7 @@ function generateSetNode(
|
|
|
145
152
|
id: number,
|
|
146
153
|
current: Set<unknown>,
|
|
147
154
|
): SerovalSetNode {
|
|
148
|
-
assert(ctx.features & Feature.Set,
|
|
155
|
+
assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
|
|
149
156
|
const len = current.size;
|
|
150
157
|
const nodes = new Array<SerovalNode>(len);
|
|
151
158
|
const deferred = new Array<unknown>(len);
|
|
@@ -156,12 +163,12 @@ function generateSetNode(
|
|
|
156
163
|
if (isIterable(item)) {
|
|
157
164
|
deferred[deferredSize++] = item;
|
|
158
165
|
} else {
|
|
159
|
-
nodes[nodeSize++] =
|
|
166
|
+
nodes[nodeSize++] = parseSync(ctx, item);
|
|
160
167
|
}
|
|
161
168
|
}
|
|
162
169
|
// Parse deferred items
|
|
163
170
|
for (let i = 0; i < deferredSize; i++) {
|
|
164
|
-
nodes[nodeSize + i] =
|
|
171
|
+
nodes[nodeSize + i] = parseSync(ctx, deferred[i]);
|
|
165
172
|
}
|
|
166
173
|
return {
|
|
167
174
|
t: SerovalNodeType.Set,
|
|
@@ -174,6 +181,7 @@ function generateSetNode(
|
|
|
174
181
|
a: nodes,
|
|
175
182
|
f: undefined,
|
|
176
183
|
b: undefined,
|
|
184
|
+
o: undefined,
|
|
177
185
|
};
|
|
178
186
|
}
|
|
179
187
|
|
|
@@ -182,15 +190,15 @@ function generateProperties(
|
|
|
182
190
|
properties: Record<string, unknown>,
|
|
183
191
|
): SerovalObjectRecordNode {
|
|
184
192
|
const keys = Object.keys(properties);
|
|
185
|
-
|
|
186
|
-
const keyNodes = new Array<
|
|
193
|
+
let size = keys.length;
|
|
194
|
+
const keyNodes = new Array<SerovalObjectRecordKey>(size);
|
|
187
195
|
const valueNodes = new Array<SerovalNode>(size);
|
|
188
|
-
const deferredKeys = new Array<
|
|
196
|
+
const deferredKeys = new Array<SerovalObjectRecordKey>(size);
|
|
189
197
|
const deferredValues = new Array<unknown>(size);
|
|
190
198
|
let deferredSize = 0;
|
|
191
199
|
let nodesSize = 0;
|
|
192
200
|
let item: unknown;
|
|
193
|
-
let escaped:
|
|
201
|
+
let escaped: SerovalObjectRecordKey;
|
|
194
202
|
for (const key of keys) {
|
|
195
203
|
item = properties[key];
|
|
196
204
|
escaped = serializeString(key);
|
|
@@ -200,13 +208,22 @@ function generateProperties(
|
|
|
200
208
|
deferredSize++;
|
|
201
209
|
} else {
|
|
202
210
|
keyNodes[nodesSize] = escaped;
|
|
203
|
-
valueNodes[nodesSize] =
|
|
211
|
+
valueNodes[nodesSize] = parseSync(ctx, item);
|
|
204
212
|
nodesSize++;
|
|
205
213
|
}
|
|
206
214
|
}
|
|
207
215
|
for (let i = 0; i < deferredSize; i++) {
|
|
208
216
|
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
209
|
-
valueNodes[nodesSize + i] =
|
|
217
|
+
valueNodes[nodesSize + i] = parseSync(ctx, deferredValues[i]);
|
|
218
|
+
}
|
|
219
|
+
if (ctx.features & Feature.Symbol) {
|
|
220
|
+
if (Symbol.iterator in properties) {
|
|
221
|
+
keyNodes[size] = SerovalObjectRecordSpecialKey.SymbolIterator;
|
|
222
|
+
const items = Array.from(properties as Iterable<unknown>);
|
|
223
|
+
const id = createIndexedValue(ctx, items);
|
|
224
|
+
valueNodes[size] = generateArrayNode(ctx, id, items);
|
|
225
|
+
size++;
|
|
226
|
+
}
|
|
210
227
|
}
|
|
211
228
|
return {
|
|
212
229
|
k: keyNodes,
|
|
@@ -215,40 +232,50 @@ function generateProperties(
|
|
|
215
232
|
};
|
|
216
233
|
}
|
|
217
234
|
|
|
218
|
-
function
|
|
235
|
+
function generatePlainProperties(
|
|
219
236
|
ctx: ParserContext,
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const
|
|
225
|
-
const
|
|
237
|
+
properties: Record<string, unknown>,
|
|
238
|
+
): SerovalPlainRecordNode {
|
|
239
|
+
const keys = Object.keys(properties);
|
|
240
|
+
const size = keys.length;
|
|
241
|
+
const keyNodes = new Array<string>(size);
|
|
242
|
+
const valueNodes = new Array<SerovalNode>(size);
|
|
243
|
+
const deferredKeys = new Array<string>(size);
|
|
244
|
+
const deferredValues = new Array<unknown>(size);
|
|
245
|
+
let deferredSize = 0;
|
|
246
|
+
let nodesSize = 0;
|
|
247
|
+
let item: unknown;
|
|
248
|
+
let escaped: string;
|
|
249
|
+
for (const key of keys) {
|
|
250
|
+
item = properties[key];
|
|
251
|
+
escaped = serializeString(key);
|
|
252
|
+
if (isIterable(item)) {
|
|
253
|
+
deferredKeys[deferredSize] = escaped;
|
|
254
|
+
deferredValues[deferredSize] = item;
|
|
255
|
+
deferredSize++;
|
|
256
|
+
} else {
|
|
257
|
+
keyNodes[nodesSize] = escaped;
|
|
258
|
+
valueNodes[nodesSize] = parseSync(ctx, item);
|
|
259
|
+
nodesSize++;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
for (let i = 0; i < deferredSize; i++) {
|
|
263
|
+
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
264
|
+
valueNodes[nodesSize + i] = parseSync(ctx, deferredValues[i]);
|
|
265
|
+
}
|
|
226
266
|
return {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
s:
|
|
230
|
-
l: array.length,
|
|
231
|
-
c: undefined,
|
|
232
|
-
m: undefined,
|
|
233
|
-
// Parse options first before the items
|
|
234
|
-
d: options
|
|
235
|
-
? generateProperties(ctx, options)
|
|
236
|
-
: undefined,
|
|
237
|
-
a: generateNodeList(ctx, array),
|
|
238
|
-
f: undefined,
|
|
239
|
-
b: undefined,
|
|
267
|
+
k: keyNodes,
|
|
268
|
+
v: valueNodes,
|
|
269
|
+
s: size,
|
|
240
270
|
};
|
|
241
271
|
}
|
|
242
272
|
|
|
243
273
|
function generateObjectNode(
|
|
244
274
|
ctx: ParserContext,
|
|
245
275
|
id: number,
|
|
246
|
-
current: Record<string, unknown
|
|
276
|
+
current: Record<string, unknown>,
|
|
247
277
|
empty: boolean,
|
|
248
278
|
): ObjectLikeNode {
|
|
249
|
-
if (Symbol.iterator in current) {
|
|
250
|
-
return generateIterableNode(ctx, id, current);
|
|
251
|
-
}
|
|
252
279
|
return {
|
|
253
280
|
t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
254
281
|
i: id,
|
|
@@ -260,6 +287,7 @@ function generateObjectNode(
|
|
|
260
287
|
a: undefined,
|
|
261
288
|
f: undefined,
|
|
262
289
|
b: undefined,
|
|
290
|
+
o: getObjectFlag(current),
|
|
263
291
|
};
|
|
264
292
|
}
|
|
265
293
|
|
|
@@ -283,6 +311,7 @@ function generateAggregateErrorNode(
|
|
|
283
311
|
a: undefined,
|
|
284
312
|
f: undefined,
|
|
285
313
|
b: undefined,
|
|
314
|
+
o: undefined,
|
|
286
315
|
};
|
|
287
316
|
}
|
|
288
317
|
|
|
@@ -306,6 +335,7 @@ function generateErrorNode(
|
|
|
306
335
|
a: undefined,
|
|
307
336
|
f: undefined,
|
|
308
337
|
b: undefined,
|
|
338
|
+
o: undefined,
|
|
309
339
|
};
|
|
310
340
|
}
|
|
311
341
|
|
|
@@ -314,8 +344,9 @@ function generateHeadersNode(
|
|
|
314
344
|
id: number,
|
|
315
345
|
current: Headers,
|
|
316
346
|
): SerovalHeadersNode {
|
|
317
|
-
assert(ctx.features & Feature.WebAPI,
|
|
347
|
+
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
318
348
|
const items: Record<string, string> = {};
|
|
349
|
+
// TS Headers not an Iterable
|
|
319
350
|
current.forEach((value, key) => {
|
|
320
351
|
items[key] = value;
|
|
321
352
|
});
|
|
@@ -326,10 +357,11 @@ function generateHeadersNode(
|
|
|
326
357
|
l: undefined,
|
|
327
358
|
c: undefined,
|
|
328
359
|
m: undefined,
|
|
329
|
-
d:
|
|
360
|
+
d: generatePlainProperties(ctx, items),
|
|
330
361
|
a: undefined,
|
|
331
362
|
f: undefined,
|
|
332
363
|
b: undefined,
|
|
364
|
+
o: undefined,
|
|
333
365
|
};
|
|
334
366
|
}
|
|
335
367
|
|
|
@@ -338,8 +370,9 @@ function generateFormDataNode(
|
|
|
338
370
|
id: number,
|
|
339
371
|
current: FormData,
|
|
340
372
|
): SerovalFormDataNode {
|
|
341
|
-
assert(ctx.features & Feature.WebAPI,
|
|
373
|
+
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
342
374
|
const items: Record<string, FormDataEntryValue> = {};
|
|
375
|
+
// TS FormData isn't an Iterable sadly
|
|
343
376
|
current.forEach((value, key) => {
|
|
344
377
|
items[key] = value;
|
|
345
378
|
});
|
|
@@ -350,14 +383,147 @@ function generateFormDataNode(
|
|
|
350
383
|
l: undefined,
|
|
351
384
|
c: undefined,
|
|
352
385
|
m: undefined,
|
|
353
|
-
d:
|
|
386
|
+
d: generatePlainProperties(ctx, items),
|
|
354
387
|
a: undefined,
|
|
355
388
|
f: undefined,
|
|
356
389
|
b: undefined,
|
|
390
|
+
o: undefined,
|
|
357
391
|
};
|
|
358
392
|
}
|
|
359
393
|
|
|
360
|
-
function
|
|
394
|
+
function generateBoxedNode(
|
|
395
|
+
ctx: ParserContext,
|
|
396
|
+
id: number,
|
|
397
|
+
current: object,
|
|
398
|
+
): SerovalBoxedNode {
|
|
399
|
+
return {
|
|
400
|
+
t: SerovalNodeType.Boxed,
|
|
401
|
+
i: id,
|
|
402
|
+
s: undefined,
|
|
403
|
+
l: undefined,
|
|
404
|
+
c: undefined,
|
|
405
|
+
m: undefined,
|
|
406
|
+
d: undefined,
|
|
407
|
+
a: undefined,
|
|
408
|
+
f: parseSync(ctx, current.valueOf()),
|
|
409
|
+
b: undefined,
|
|
410
|
+
o: undefined,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function parseObject(
|
|
415
|
+
ctx: ParserContext,
|
|
416
|
+
current: object | null,
|
|
417
|
+
): SerovalNode {
|
|
418
|
+
if (!current) {
|
|
419
|
+
return NULL_NODE;
|
|
420
|
+
}
|
|
421
|
+
// Non-primitive values needs a reference ID
|
|
422
|
+
// mostly because the values themselves are stateful
|
|
423
|
+
const id = createIndexedValue(ctx, current);
|
|
424
|
+
if (ctx.markedRefs.has(id)) {
|
|
425
|
+
return createIndexedValueNode(id);
|
|
426
|
+
}
|
|
427
|
+
if (hasReferenceID(current)) {
|
|
428
|
+
return createReferenceNode(id, current);
|
|
429
|
+
}
|
|
430
|
+
// Well well well
|
|
431
|
+
if (Array.isArray(current)) {
|
|
432
|
+
return generateArrayNode(ctx, id, current);
|
|
433
|
+
}
|
|
434
|
+
// Fast path
|
|
435
|
+
switch (current.constructor) {
|
|
436
|
+
case Number:
|
|
437
|
+
case Boolean:
|
|
438
|
+
case String:
|
|
439
|
+
case BigInt:
|
|
440
|
+
case Function:
|
|
441
|
+
case Symbol:
|
|
442
|
+
return generateBoxedNode(ctx, id, current);
|
|
443
|
+
case Date:
|
|
444
|
+
return createDateNode(id, current as unknown as Date);
|
|
445
|
+
case RegExp:
|
|
446
|
+
return createRegExpNode(id, current as unknown as RegExp);
|
|
447
|
+
case ArrayBuffer:
|
|
448
|
+
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
449
|
+
case Int8Array:
|
|
450
|
+
case Int16Array:
|
|
451
|
+
case Int32Array:
|
|
452
|
+
case Uint8Array:
|
|
453
|
+
case Uint16Array:
|
|
454
|
+
case Uint32Array:
|
|
455
|
+
case Uint8ClampedArray:
|
|
456
|
+
case Float32Array:
|
|
457
|
+
case Float64Array:
|
|
458
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
459
|
+
case BigInt64Array:
|
|
460
|
+
case BigUint64Array:
|
|
461
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
462
|
+
case DataView:
|
|
463
|
+
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
464
|
+
case Map:
|
|
465
|
+
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
466
|
+
case Set:
|
|
467
|
+
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
468
|
+
case Object:
|
|
469
|
+
return generateObjectNode(
|
|
470
|
+
ctx,
|
|
471
|
+
id,
|
|
472
|
+
current as unknown as Record<string, unknown>,
|
|
473
|
+
false,
|
|
474
|
+
);
|
|
475
|
+
case undefined:
|
|
476
|
+
return generateObjectNode(
|
|
477
|
+
ctx,
|
|
478
|
+
id,
|
|
479
|
+
current as unknown as Record<string, unknown>,
|
|
480
|
+
true,
|
|
481
|
+
);
|
|
482
|
+
case AggregateError:
|
|
483
|
+
// Compile-down AggregateError to Error if disabled
|
|
484
|
+
if (ctx.features & Feature.AggregateError) {
|
|
485
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
486
|
+
}
|
|
487
|
+
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
488
|
+
case Error:
|
|
489
|
+
case EvalError:
|
|
490
|
+
case RangeError:
|
|
491
|
+
case ReferenceError:
|
|
492
|
+
case SyntaxError:
|
|
493
|
+
case TypeError:
|
|
494
|
+
case URIError:
|
|
495
|
+
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
496
|
+
case URL:
|
|
497
|
+
return createURLNode(ctx, id, current as unknown as URL);
|
|
498
|
+
case URLSearchParams:
|
|
499
|
+
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
500
|
+
case Headers:
|
|
501
|
+
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
502
|
+
case FormData:
|
|
503
|
+
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
504
|
+
default:
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
// Slow path. We only need to handle Errors and Iterators
|
|
508
|
+
// since they have very broad implementations.
|
|
509
|
+
if (current instanceof AggregateError) {
|
|
510
|
+
if (ctx.features & Feature.AggregateError) {
|
|
511
|
+
return generateAggregateErrorNode(ctx, id, current);
|
|
512
|
+
}
|
|
513
|
+
return generateErrorNode(ctx, id, current);
|
|
514
|
+
}
|
|
515
|
+
if (current instanceof Error) {
|
|
516
|
+
return generateErrorNode(ctx, id, current);
|
|
517
|
+
}
|
|
518
|
+
// Generator functions don't have a global constructor
|
|
519
|
+
// despite existing
|
|
520
|
+
if (Symbol.iterator in current) {
|
|
521
|
+
return generateObjectNode(ctx, id, current, !!current.constructor);
|
|
522
|
+
}
|
|
523
|
+
throw new UnsupportedTypeError(current);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
export default function parseSync<T>(
|
|
361
527
|
ctx: ParserContext,
|
|
362
528
|
current: T,
|
|
363
529
|
): SerovalNode {
|
|
@@ -369,144 +535,16 @@ function parse<T>(
|
|
|
369
535
|
case 'string':
|
|
370
536
|
return createStringNode(current);
|
|
371
537
|
case 'number':
|
|
372
|
-
|
|
373
|
-
case Infinity: return INFINITY_NODE;
|
|
374
|
-
case -Infinity: return NEG_INFINITY_NODE;
|
|
375
|
-
default:
|
|
376
|
-
// eslint-disable-next-line no-self-compare
|
|
377
|
-
if (current !== current) {
|
|
378
|
-
return NAN_NODE;
|
|
379
|
-
}
|
|
380
|
-
if (Object.is(current, -0)) {
|
|
381
|
-
return NEG_ZERO_NODE;
|
|
382
|
-
}
|
|
383
|
-
return createNumberNode(current);
|
|
384
|
-
}
|
|
538
|
+
return createNumberNode(current);
|
|
385
539
|
case 'bigint':
|
|
386
540
|
return createBigIntNode(ctx, current);
|
|
387
|
-
case 'object':
|
|
388
|
-
|
|
389
|
-
return NULL_NODE;
|
|
390
|
-
}
|
|
391
|
-
// Non-primitive values needs a reference ID
|
|
392
|
-
// mostly because the values themselves are stateful
|
|
393
|
-
const id = createIndexedValue(ctx, current);
|
|
394
|
-
if (ctx.markedRefs.has(id)) {
|
|
395
|
-
return createIndexedValueNode(id);
|
|
396
|
-
}
|
|
397
|
-
if (hasReferenceID(current)) {
|
|
398
|
-
return createReferenceNode(id, current);
|
|
399
|
-
}
|
|
400
|
-
if (Array.isArray(current)) {
|
|
401
|
-
return generateArrayNode(ctx, id, current);
|
|
402
|
-
}
|
|
403
|
-
switch (current.constructor) {
|
|
404
|
-
case Date:
|
|
405
|
-
return createDateNode(id, current as unknown as Date);
|
|
406
|
-
case RegExp:
|
|
407
|
-
return createRegExpNode(id, current as unknown as RegExp);
|
|
408
|
-
case ArrayBuffer:
|
|
409
|
-
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
410
|
-
case Int8Array:
|
|
411
|
-
case Int16Array:
|
|
412
|
-
case Int32Array:
|
|
413
|
-
case Uint8Array:
|
|
414
|
-
case Uint16Array:
|
|
415
|
-
case Uint32Array:
|
|
416
|
-
case Uint8ClampedArray:
|
|
417
|
-
case Float32Array:
|
|
418
|
-
case Float64Array:
|
|
419
|
-
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
420
|
-
case BigInt64Array:
|
|
421
|
-
case BigUint64Array:
|
|
422
|
-
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
423
|
-
case DataView:
|
|
424
|
-
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
425
|
-
case Map:
|
|
426
|
-
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
427
|
-
case Set:
|
|
428
|
-
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
429
|
-
case Object:
|
|
430
|
-
return generateObjectNode(
|
|
431
|
-
ctx,
|
|
432
|
-
id,
|
|
433
|
-
current as unknown as Record<string, unknown>,
|
|
434
|
-
false,
|
|
435
|
-
);
|
|
436
|
-
case undefined:
|
|
437
|
-
return generateObjectNode(
|
|
438
|
-
ctx,
|
|
439
|
-
id,
|
|
440
|
-
current as unknown as Record<string, unknown>,
|
|
441
|
-
true,
|
|
442
|
-
);
|
|
443
|
-
case AggregateError:
|
|
444
|
-
if (ctx.features & Feature.AggregateError) {
|
|
445
|
-
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
446
|
-
}
|
|
447
|
-
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
448
|
-
case Error:
|
|
449
|
-
case EvalError:
|
|
450
|
-
case RangeError:
|
|
451
|
-
case ReferenceError:
|
|
452
|
-
case SyntaxError:
|
|
453
|
-
case TypeError:
|
|
454
|
-
case URIError:
|
|
455
|
-
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
456
|
-
case URL:
|
|
457
|
-
return createURLNode(ctx, id, current as unknown as URL);
|
|
458
|
-
case URLSearchParams:
|
|
459
|
-
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
460
|
-
case Headers:
|
|
461
|
-
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
462
|
-
case FormData:
|
|
463
|
-
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
464
|
-
default:
|
|
465
|
-
break;
|
|
466
|
-
}
|
|
467
|
-
if (current instanceof AggregateError) {
|
|
468
|
-
if (ctx.features & Feature.AggregateError) {
|
|
469
|
-
return generateAggregateErrorNode(ctx, id, current);
|
|
470
|
-
}
|
|
471
|
-
return generateErrorNode(ctx, id, current);
|
|
472
|
-
}
|
|
473
|
-
if (current instanceof Error) {
|
|
474
|
-
return generateErrorNode(ctx, id, current);
|
|
475
|
-
}
|
|
476
|
-
// Generator functions don't have a global constructor
|
|
477
|
-
if (Symbol.iterator in current) {
|
|
478
|
-
return generateIterableNode(ctx, id, current as Iterable<unknown>);
|
|
479
|
-
}
|
|
480
|
-
throw new Error('Unsupported type');
|
|
481
|
-
}
|
|
541
|
+
case 'object':
|
|
542
|
+
return parseObject(ctx, current);
|
|
482
543
|
case 'symbol':
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
return createIndexedValueNode(id);
|
|
487
|
-
}
|
|
488
|
-
return createReferenceNode(id, current);
|
|
489
|
-
}
|
|
490
|
-
return createWKSymbolNode(ctx, current as WellKnownSymbols);
|
|
491
|
-
case 'function': {
|
|
492
|
-
assert(hasReferenceID(current), 'Cannot serialize function without reference ID.');
|
|
493
|
-
const id = createIndexedValue(ctx, current);
|
|
494
|
-
if (ctx.markedRefs.has(id)) {
|
|
495
|
-
return createIndexedValueNode(id);
|
|
496
|
-
}
|
|
497
|
-
return createReferenceNode(id, current);
|
|
498
|
-
}
|
|
544
|
+
return createSymbolNode(ctx, current);
|
|
545
|
+
case 'function':
|
|
546
|
+
return createFunctionNode(ctx, current);
|
|
499
547
|
default:
|
|
500
|
-
throw new
|
|
548
|
+
throw new UnsupportedTypeError(current);
|
|
501
549
|
}
|
|
502
550
|
}
|
|
503
|
-
|
|
504
|
-
export default function parseSync<T>(
|
|
505
|
-
ctx: ParserContext,
|
|
506
|
-
current: T,
|
|
507
|
-
) {
|
|
508
|
-
const result = parse(ctx, current);
|
|
509
|
-
const isObject = result.t === SerovalNodeType.Object
|
|
510
|
-
|| result.t === SerovalNodeType.Iterable;
|
|
511
|
-
return [result, getRootID(ctx, current), isObject] as const;
|
|
512
|
-
}
|