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