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/async.ts
CHANGED
|
@@ -2,12 +2,22 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
3
3
|
import assert from '../assert';
|
|
4
4
|
import { Feature } from '../compat';
|
|
5
|
-
import {
|
|
6
|
-
import { serializeString } from '../string';
|
|
5
|
+
import type { ParserContext } from '../context';
|
|
7
6
|
import {
|
|
7
|
+
createIndexedValue,
|
|
8
|
+
} from '../context';
|
|
9
|
+
import { serializeString } from '../string';
|
|
10
|
+
import type {
|
|
8
11
|
BigIntTypedArrayValue,
|
|
9
12
|
TypedArrayValue,
|
|
10
13
|
} from '../types';
|
|
14
|
+
import UnsupportedTypeError from './UnsupportedTypeError';
|
|
15
|
+
import {
|
|
16
|
+
TRUE_NODE,
|
|
17
|
+
FALSE_NODE,
|
|
18
|
+
UNDEFINED_NODE,
|
|
19
|
+
NULL_NODE,
|
|
20
|
+
} from './constants';
|
|
11
21
|
import {
|
|
12
22
|
createBigIntNode,
|
|
13
23
|
createBigIntTypedArrayNode,
|
|
@@ -17,43 +27,40 @@ import {
|
|
|
17
27
|
createRegExpNode,
|
|
18
28
|
createStringNode,
|
|
19
29
|
createTypedArrayNode,
|
|
20
|
-
createWKSymbolNode,
|
|
21
|
-
FALSE_NODE,
|
|
22
|
-
INFINITY_NODE,
|
|
23
|
-
NAN_NODE,
|
|
24
|
-
NEG_INFINITY_NODE,
|
|
25
|
-
NEG_ZERO_NODE,
|
|
26
|
-
NULL_NODE,
|
|
27
|
-
TRUE_NODE,
|
|
28
|
-
UNDEFINED_NODE,
|
|
29
30
|
createReferenceNode,
|
|
30
31
|
createArrayBufferNode,
|
|
31
32
|
createDataViewNode,
|
|
33
|
+
createSymbolNode,
|
|
34
|
+
createFunctionNode,
|
|
32
35
|
} from './primitives';
|
|
33
36
|
import { hasReferenceID } from './reference';
|
|
34
37
|
import {
|
|
35
38
|
getErrorConstructorName,
|
|
36
39
|
getErrorOptions,
|
|
37
|
-
|
|
40
|
+
getObjectFlag,
|
|
38
41
|
isIterable,
|
|
39
42
|
} from './shared';
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
43
|
+
import type {
|
|
42
44
|
SerovalAggregateErrorNode,
|
|
43
45
|
SerovalArrayNode,
|
|
46
|
+
SerovalBoxedNode,
|
|
44
47
|
SerovalErrorNode,
|
|
45
48
|
SerovalFormDataNode,
|
|
46
49
|
SerovalHeadersNode,
|
|
47
|
-
SerovalIterableNode,
|
|
48
50
|
SerovalMapNode,
|
|
49
51
|
SerovalNode,
|
|
50
|
-
SerovalNodeType,
|
|
51
52
|
SerovalNullConstructorNode,
|
|
52
53
|
SerovalObjectNode,
|
|
54
|
+
SerovalObjectRecordKey,
|
|
53
55
|
SerovalObjectRecordNode,
|
|
56
|
+
SerovalPlainRecordNode,
|
|
54
57
|
SerovalPromiseNode,
|
|
55
58
|
SerovalSetNode,
|
|
56
59
|
} from './types';
|
|
60
|
+
import {
|
|
61
|
+
SerovalNodeType,
|
|
62
|
+
SerovalObjectRecordSpecialKey,
|
|
63
|
+
} from './types';
|
|
57
64
|
import {
|
|
58
65
|
createBlobNode,
|
|
59
66
|
createFileNode,
|
|
@@ -64,18 +71,12 @@ import {
|
|
|
64
71
|
type ObjectLikeNode =
|
|
65
72
|
| SerovalObjectNode
|
|
66
73
|
| SerovalNullConstructorNode
|
|
67
|
-
| SerovalIterableNode
|
|
68
74
|
| SerovalPromiseNode;
|
|
69
75
|
|
|
70
|
-
type ObjectLikeValue =
|
|
71
|
-
| Record<string, unknown>
|
|
72
|
-
| Iterable<unknown>
|
|
73
|
-
| PromiseLike<unknown>;
|
|
74
|
-
|
|
75
76
|
async function generateNodeList(
|
|
76
77
|
ctx: ParserContext,
|
|
77
78
|
current: unknown[],
|
|
78
|
-
) {
|
|
79
|
+
): Promise<SerovalNode[]> {
|
|
79
80
|
const size = current.length;
|
|
80
81
|
const nodes = new Array<SerovalNode>(size);
|
|
81
82
|
const deferred = new Array<unknown>(size);
|
|
@@ -86,13 +87,13 @@ async function generateNodeList(
|
|
|
86
87
|
if (isIterable(item)) {
|
|
87
88
|
deferred[i] = item;
|
|
88
89
|
} else {
|
|
89
|
-
nodes[i] = await
|
|
90
|
+
nodes[i] = await parseAsync(ctx, item);
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
for (let i = 0; i < size; i++) {
|
|
94
95
|
if (i in deferred) {
|
|
95
|
-
nodes[i] = await
|
|
96
|
+
nodes[i] = await parseAsync(ctx, deferred[i]);
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
return nodes;
|
|
@@ -114,6 +115,7 @@ async function generateArrayNode(
|
|
|
114
115
|
a: await generateNodeList(ctx, current),
|
|
115
116
|
f: undefined,
|
|
116
117
|
b: undefined,
|
|
118
|
+
o: getObjectFlag(current),
|
|
117
119
|
};
|
|
118
120
|
}
|
|
119
121
|
|
|
@@ -122,7 +124,7 @@ async function generateMapNode(
|
|
|
122
124
|
id: number,
|
|
123
125
|
current: Map<unknown, unknown>,
|
|
124
126
|
): Promise<SerovalMapNode> {
|
|
125
|
-
assert(ctx.features & Feature.Map,
|
|
127
|
+
assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
|
|
126
128
|
const len = current.size;
|
|
127
129
|
const keyNodes = new Array<SerovalNode>(len);
|
|
128
130
|
const valueNodes = new Array<SerovalNode>(len);
|
|
@@ -137,14 +139,14 @@ async function generateMapNode(
|
|
|
137
139
|
deferredValue[deferredSize] = value;
|
|
138
140
|
deferredSize++;
|
|
139
141
|
} else {
|
|
140
|
-
keyNodes[nodeSize] = await
|
|
141
|
-
valueNodes[nodeSize] = await
|
|
142
|
+
keyNodes[nodeSize] = await parseAsync(ctx, key);
|
|
143
|
+
valueNodes[nodeSize] = await parseAsync(ctx, value);
|
|
142
144
|
nodeSize++;
|
|
143
145
|
}
|
|
144
146
|
}
|
|
145
147
|
for (let i = 0; i < deferredSize; i++) {
|
|
146
|
-
keyNodes[nodeSize + i] = await
|
|
147
|
-
valueNodes[nodeSize + i] = await
|
|
148
|
+
keyNodes[nodeSize + i] = await parseAsync(ctx, deferredKey[i]);
|
|
149
|
+
valueNodes[nodeSize + i] = await parseAsync(ctx, deferredValue[i]);
|
|
148
150
|
}
|
|
149
151
|
return {
|
|
150
152
|
t: SerovalNodeType.Map,
|
|
@@ -157,6 +159,7 @@ async function generateMapNode(
|
|
|
157
159
|
a: undefined,
|
|
158
160
|
f: undefined,
|
|
159
161
|
b: undefined,
|
|
162
|
+
o: undefined,
|
|
160
163
|
};
|
|
161
164
|
}
|
|
162
165
|
|
|
@@ -165,7 +168,7 @@ async function generateSetNode(
|
|
|
165
168
|
id: number,
|
|
166
169
|
current: Set<unknown>,
|
|
167
170
|
): Promise<SerovalSetNode> {
|
|
168
|
-
assert(ctx.features & Feature.Set,
|
|
171
|
+
assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
|
|
169
172
|
const len = current.size;
|
|
170
173
|
const nodes = new Array<SerovalNode>(len);
|
|
171
174
|
const deferred = new Array<unknown>(len);
|
|
@@ -176,12 +179,12 @@ async function generateSetNode(
|
|
|
176
179
|
if (isIterable(item)) {
|
|
177
180
|
deferred[deferredSize++] = item;
|
|
178
181
|
} else {
|
|
179
|
-
nodes[nodeSize++] = await
|
|
182
|
+
nodes[nodeSize++] = await parseAsync(ctx, item);
|
|
180
183
|
}
|
|
181
184
|
}
|
|
182
185
|
// Parse deferred items
|
|
183
186
|
for (let i = 0; i < deferredSize; i++) {
|
|
184
|
-
nodes[nodeSize + i] = await
|
|
187
|
+
nodes[nodeSize + i] = await parseAsync(ctx, deferred[i]);
|
|
185
188
|
}
|
|
186
189
|
return {
|
|
187
190
|
t: SerovalNodeType.Set,
|
|
@@ -194,6 +197,7 @@ async function generateSetNode(
|
|
|
194
197
|
a: nodes,
|
|
195
198
|
f: undefined,
|
|
196
199
|
b: undefined,
|
|
200
|
+
o: undefined,
|
|
197
201
|
};
|
|
198
202
|
}
|
|
199
203
|
|
|
@@ -202,15 +206,15 @@ async function generateProperties(
|
|
|
202
206
|
properties: Record<string, unknown>,
|
|
203
207
|
): Promise<SerovalObjectRecordNode> {
|
|
204
208
|
const keys = Object.keys(properties);
|
|
205
|
-
|
|
206
|
-
const keyNodes = new Array<
|
|
209
|
+
let size = keys.length;
|
|
210
|
+
const keyNodes = new Array<SerovalObjectRecordKey>(size);
|
|
207
211
|
const valueNodes = new Array<SerovalNode>(size);
|
|
208
|
-
const deferredKeys = new Array<
|
|
212
|
+
const deferredKeys = new Array<SerovalObjectRecordKey>(size);
|
|
209
213
|
const deferredValues = new Array<unknown>(size);
|
|
210
214
|
let deferredSize = 0;
|
|
211
215
|
let nodesSize = 0;
|
|
212
216
|
let item: unknown;
|
|
213
|
-
let escaped:
|
|
217
|
+
let escaped: SerovalObjectRecordKey;
|
|
214
218
|
for (const key of keys) {
|
|
215
219
|
item = properties[key];
|
|
216
220
|
escaped = serializeString(key);
|
|
@@ -220,13 +224,25 @@ async function generateProperties(
|
|
|
220
224
|
deferredSize++;
|
|
221
225
|
} else {
|
|
222
226
|
keyNodes[nodesSize] = escaped;
|
|
223
|
-
valueNodes[nodesSize] = await
|
|
227
|
+
valueNodes[nodesSize] = await parseAsync(ctx, item);
|
|
224
228
|
nodesSize++;
|
|
225
229
|
}
|
|
226
230
|
}
|
|
227
231
|
for (let i = 0; i < deferredSize; i++) {
|
|
228
232
|
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
229
|
-
valueNodes[nodesSize + i] = await
|
|
233
|
+
valueNodes[nodesSize + i] = await parseAsync(ctx, deferredValues[i]);
|
|
234
|
+
}
|
|
235
|
+
if (ctx.features & Feature.Symbol) {
|
|
236
|
+
if (Symbol.iterator in properties) {
|
|
237
|
+
keyNodes[size] = SerovalObjectRecordSpecialKey.SymbolIterator;
|
|
238
|
+
const items = Array.from(properties as Iterable<unknown>);
|
|
239
|
+
valueNodes[size] = await generateArrayNode(
|
|
240
|
+
ctx,
|
|
241
|
+
createIndexedValue(ctx, items),
|
|
242
|
+
items,
|
|
243
|
+
);
|
|
244
|
+
size++;
|
|
245
|
+
}
|
|
230
246
|
}
|
|
231
247
|
return {
|
|
232
248
|
k: keyNodes,
|
|
@@ -235,38 +251,51 @@ async function generateProperties(
|
|
|
235
251
|
};
|
|
236
252
|
}
|
|
237
253
|
|
|
238
|
-
async function
|
|
254
|
+
async function generatePlainProperties(
|
|
239
255
|
ctx: ParserContext,
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
const
|
|
256
|
+
properties: Record<string, unknown>,
|
|
257
|
+
): Promise<SerovalPlainRecordNode> {
|
|
258
|
+
const keys = Object.keys(properties);
|
|
259
|
+
const size = keys.length;
|
|
260
|
+
const keyNodes = new Array<string>(size);
|
|
261
|
+
const valueNodes = new Array<SerovalNode>(size);
|
|
262
|
+
const deferredKeys = new Array<string>(size);
|
|
263
|
+
const deferredValues = new Array<unknown>(size);
|
|
264
|
+
let deferredSize = 0;
|
|
265
|
+
let nodesSize = 0;
|
|
266
|
+
let item: unknown;
|
|
267
|
+
let escaped: string;
|
|
268
|
+
for (const key of keys) {
|
|
269
|
+
item = properties[key];
|
|
270
|
+
escaped = serializeString(key);
|
|
271
|
+
if (isIterable(item)) {
|
|
272
|
+
deferredKeys[deferredSize] = escaped;
|
|
273
|
+
deferredValues[deferredSize] = item;
|
|
274
|
+
deferredSize++;
|
|
275
|
+
} else {
|
|
276
|
+
keyNodes[nodesSize] = escaped;
|
|
277
|
+
valueNodes[nodesSize] = await parseAsync(ctx, item);
|
|
278
|
+
nodesSize++;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
for (let i = 0; i < deferredSize; i++) {
|
|
282
|
+
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
283
|
+
valueNodes[nodesSize + i] = await parseAsync(ctx, deferredValues[i]);
|
|
284
|
+
}
|
|
246
285
|
return {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
s:
|
|
250
|
-
l: array.length,
|
|
251
|
-
c: undefined,
|
|
252
|
-
m: undefined,
|
|
253
|
-
// Parse options first before the items
|
|
254
|
-
d: options
|
|
255
|
-
? await generateProperties(ctx, options)
|
|
256
|
-
: undefined,
|
|
257
|
-
a: await generateNodeList(ctx, array),
|
|
258
|
-
f: undefined,
|
|
259
|
-
b: undefined,
|
|
286
|
+
k: keyNodes,
|
|
287
|
+
v: valueNodes,
|
|
288
|
+
s: size,
|
|
260
289
|
};
|
|
261
290
|
}
|
|
262
291
|
|
|
263
292
|
async function generatePromiseNode(
|
|
264
293
|
ctx: ParserContext,
|
|
265
294
|
id: number,
|
|
266
|
-
current:
|
|
295
|
+
current: Promise<unknown>,
|
|
267
296
|
): Promise<SerovalPromiseNode> {
|
|
268
|
-
assert(ctx.features & Feature.Promise,
|
|
269
|
-
return
|
|
297
|
+
assert(ctx.features & Feature.Promise, new UnsupportedTypeError(current));
|
|
298
|
+
return {
|
|
270
299
|
t: SerovalNodeType.Promise,
|
|
271
300
|
i: id,
|
|
272
301
|
s: undefined,
|
|
@@ -276,23 +305,18 @@ async function generatePromiseNode(
|
|
|
276
305
|
// Parse options first before the items
|
|
277
306
|
d: undefined,
|
|
278
307
|
a: undefined,
|
|
279
|
-
f: await
|
|
308
|
+
f: await parseAsync(ctx, await current),
|
|
280
309
|
b: undefined,
|
|
281
|
-
|
|
310
|
+
o: undefined,
|
|
311
|
+
};
|
|
282
312
|
}
|
|
283
313
|
|
|
284
314
|
async function generateObjectNode(
|
|
285
315
|
ctx: ParserContext,
|
|
286
316
|
id: number,
|
|
287
|
-
current:
|
|
317
|
+
current: Record<string, unknown>,
|
|
288
318
|
empty: boolean,
|
|
289
319
|
): Promise<ObjectLikeNode> {
|
|
290
|
-
if (Symbol.iterator in current) {
|
|
291
|
-
return generateIterableNode(ctx, id, current);
|
|
292
|
-
}
|
|
293
|
-
if ('then' in current && typeof current.then === 'function') {
|
|
294
|
-
return generatePromiseNode(ctx, id, current as PromiseLike<unknown>);
|
|
295
|
-
}
|
|
296
320
|
return {
|
|
297
321
|
t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
298
322
|
i: id,
|
|
@@ -300,10 +324,11 @@ async function generateObjectNode(
|
|
|
300
324
|
l: undefined,
|
|
301
325
|
c: undefined,
|
|
302
326
|
m: undefined,
|
|
303
|
-
d: await generateProperties(ctx, current
|
|
327
|
+
d: await generateProperties(ctx, current),
|
|
304
328
|
a: undefined,
|
|
305
329
|
f: undefined,
|
|
306
330
|
b: undefined,
|
|
331
|
+
o: getObjectFlag(current),
|
|
307
332
|
};
|
|
308
333
|
}
|
|
309
334
|
|
|
@@ -327,6 +352,7 @@ async function generateAggregateErrorNode(
|
|
|
327
352
|
a: undefined,
|
|
328
353
|
f: undefined,
|
|
329
354
|
b: undefined,
|
|
355
|
+
o: undefined,
|
|
330
356
|
};
|
|
331
357
|
}
|
|
332
358
|
|
|
@@ -350,6 +376,7 @@ async function generateErrorNode(
|
|
|
350
376
|
a: undefined,
|
|
351
377
|
f: undefined,
|
|
352
378
|
b: undefined,
|
|
379
|
+
o: undefined,
|
|
353
380
|
};
|
|
354
381
|
}
|
|
355
382
|
|
|
@@ -358,7 +385,7 @@ async function generateHeadersNode(
|
|
|
358
385
|
id: number,
|
|
359
386
|
current: Headers,
|
|
360
387
|
): Promise<SerovalHeadersNode> {
|
|
361
|
-
assert(ctx.features & Feature.WebAPI,
|
|
388
|
+
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
362
389
|
const items: Record<string, string> = {};
|
|
363
390
|
current.forEach((value, key) => {
|
|
364
391
|
items[key] = value;
|
|
@@ -370,10 +397,11 @@ async function generateHeadersNode(
|
|
|
370
397
|
l: undefined,
|
|
371
398
|
c: undefined,
|
|
372
399
|
m: undefined,
|
|
373
|
-
d: await
|
|
400
|
+
d: await generatePlainProperties(ctx, items),
|
|
374
401
|
a: undefined,
|
|
375
402
|
f: undefined,
|
|
376
403
|
b: undefined,
|
|
404
|
+
o: undefined,
|
|
377
405
|
};
|
|
378
406
|
}
|
|
379
407
|
|
|
@@ -382,7 +410,7 @@ async function generateFormDataNode(
|
|
|
382
410
|
id: number,
|
|
383
411
|
current: FormData,
|
|
384
412
|
): Promise<SerovalFormDataNode> {
|
|
385
|
-
assert(ctx.features & Feature.WebAPI,
|
|
413
|
+
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
386
414
|
const items: Record<string, FormDataEntryValue> = {};
|
|
387
415
|
current.forEach((value, key) => {
|
|
388
416
|
items[key] = value;
|
|
@@ -394,14 +422,158 @@ async function generateFormDataNode(
|
|
|
394
422
|
l: undefined,
|
|
395
423
|
c: undefined,
|
|
396
424
|
m: undefined,
|
|
397
|
-
d: await
|
|
425
|
+
d: await generatePlainProperties(ctx, items),
|
|
398
426
|
a: undefined,
|
|
399
427
|
f: undefined,
|
|
400
428
|
b: undefined,
|
|
429
|
+
o: undefined,
|
|
401
430
|
};
|
|
402
431
|
}
|
|
403
432
|
|
|
404
|
-
async function
|
|
433
|
+
async function generateBoxedNode(
|
|
434
|
+
ctx: ParserContext,
|
|
435
|
+
id: number,
|
|
436
|
+
current: object,
|
|
437
|
+
): Promise<SerovalBoxedNode> {
|
|
438
|
+
return {
|
|
439
|
+
t: SerovalNodeType.Boxed,
|
|
440
|
+
i: id,
|
|
441
|
+
s: undefined,
|
|
442
|
+
l: undefined,
|
|
443
|
+
c: undefined,
|
|
444
|
+
m: undefined,
|
|
445
|
+
d: undefined,
|
|
446
|
+
a: undefined,
|
|
447
|
+
f: await parseAsync(ctx, current.valueOf()),
|
|
448
|
+
b: undefined,
|
|
449
|
+
o: undefined,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
async function parseObject(
|
|
454
|
+
ctx: ParserContext,
|
|
455
|
+
current: object | null,
|
|
456
|
+
): Promise<SerovalNode> {
|
|
457
|
+
if (!current) {
|
|
458
|
+
return NULL_NODE;
|
|
459
|
+
}
|
|
460
|
+
// Non-primitive values needs a reference ID
|
|
461
|
+
// mostly because the values themselves are stateful
|
|
462
|
+
const id = createIndexedValue(ctx, current);
|
|
463
|
+
if (ctx.markedRefs.has(id)) {
|
|
464
|
+
return createIndexedValueNode(id);
|
|
465
|
+
}
|
|
466
|
+
if (hasReferenceID(current)) {
|
|
467
|
+
return createReferenceNode(id, current);
|
|
468
|
+
}
|
|
469
|
+
if (Array.isArray(current)) {
|
|
470
|
+
return generateArrayNode(ctx, id, current);
|
|
471
|
+
}
|
|
472
|
+
switch (current.constructor) {
|
|
473
|
+
case Number:
|
|
474
|
+
case Boolean:
|
|
475
|
+
case String:
|
|
476
|
+
case BigInt:
|
|
477
|
+
case Function:
|
|
478
|
+
case Symbol:
|
|
479
|
+
return generateBoxedNode(ctx, id, current);
|
|
480
|
+
case Date:
|
|
481
|
+
return createDateNode(id, current as unknown as Date);
|
|
482
|
+
case RegExp:
|
|
483
|
+
return createRegExpNode(id, current as unknown as RegExp);
|
|
484
|
+
case Promise:
|
|
485
|
+
return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
|
|
486
|
+
case ArrayBuffer:
|
|
487
|
+
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
488
|
+
case Int8Array:
|
|
489
|
+
case Int16Array:
|
|
490
|
+
case Int32Array:
|
|
491
|
+
case Uint8Array:
|
|
492
|
+
case Uint16Array:
|
|
493
|
+
case Uint32Array:
|
|
494
|
+
case Uint8ClampedArray:
|
|
495
|
+
case Float32Array:
|
|
496
|
+
case Float64Array:
|
|
497
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
498
|
+
case BigInt64Array:
|
|
499
|
+
case BigUint64Array:
|
|
500
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
501
|
+
case DataView:
|
|
502
|
+
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
503
|
+
case Map:
|
|
504
|
+
return generateMapNode(
|
|
505
|
+
ctx,
|
|
506
|
+
id,
|
|
507
|
+
current as unknown as Map<unknown, unknown>,
|
|
508
|
+
);
|
|
509
|
+
case Set:
|
|
510
|
+
return generateSetNode(
|
|
511
|
+
ctx,
|
|
512
|
+
id,
|
|
513
|
+
current as unknown as Set<unknown>,
|
|
514
|
+
);
|
|
515
|
+
case Object:
|
|
516
|
+
return generateObjectNode(
|
|
517
|
+
ctx,
|
|
518
|
+
id,
|
|
519
|
+
current as Record<string, unknown>,
|
|
520
|
+
false,
|
|
521
|
+
);
|
|
522
|
+
case undefined:
|
|
523
|
+
return generateObjectNode(
|
|
524
|
+
ctx,
|
|
525
|
+
id,
|
|
526
|
+
current as Record<string, unknown>,
|
|
527
|
+
true,
|
|
528
|
+
);
|
|
529
|
+
case AggregateError:
|
|
530
|
+
if (ctx.features & Feature.AggregateError) {
|
|
531
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
532
|
+
}
|
|
533
|
+
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
534
|
+
case Error:
|
|
535
|
+
case EvalError:
|
|
536
|
+
case RangeError:
|
|
537
|
+
case ReferenceError:
|
|
538
|
+
case SyntaxError:
|
|
539
|
+
case TypeError:
|
|
540
|
+
case URIError:
|
|
541
|
+
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
542
|
+
case URL:
|
|
543
|
+
return createURLNode(ctx, id, current as unknown as URL);
|
|
544
|
+
case URLSearchParams:
|
|
545
|
+
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
546
|
+
case Blob:
|
|
547
|
+
return createBlobNode(ctx, id, current as unknown as Blob);
|
|
548
|
+
case File:
|
|
549
|
+
return createFileNode(ctx, id, current as unknown as File);
|
|
550
|
+
case Headers:
|
|
551
|
+
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
552
|
+
case FormData:
|
|
553
|
+
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
554
|
+
default:
|
|
555
|
+
break;
|
|
556
|
+
}
|
|
557
|
+
if (current instanceof AggregateError) {
|
|
558
|
+
if (ctx.features & Feature.AggregateError) {
|
|
559
|
+
return generateAggregateErrorNode(ctx, id, current);
|
|
560
|
+
}
|
|
561
|
+
return generateErrorNode(ctx, id, current);
|
|
562
|
+
}
|
|
563
|
+
if (current instanceof Error) {
|
|
564
|
+
return generateErrorNode(ctx, id, current);
|
|
565
|
+
}
|
|
566
|
+
if (current instanceof Promise) {
|
|
567
|
+
return generatePromiseNode(ctx, id, current);
|
|
568
|
+
}
|
|
569
|
+
// Generator functions don't have a global constructor
|
|
570
|
+
if (Symbol.iterator in current) {
|
|
571
|
+
return generateObjectNode(ctx, id, current, !!current.constructor);
|
|
572
|
+
}
|
|
573
|
+
throw new UnsupportedTypeError(current);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export default async function parseAsync<T>(
|
|
405
577
|
ctx: ParserContext,
|
|
406
578
|
current: T,
|
|
407
579
|
): Promise<SerovalNode> {
|
|
@@ -413,165 +585,16 @@ async function parse<T>(
|
|
|
413
585
|
case 'string':
|
|
414
586
|
return createStringNode(current);
|
|
415
587
|
case 'number':
|
|
416
|
-
|
|
417
|
-
case Infinity: return INFINITY_NODE;
|
|
418
|
-
case -Infinity: return NEG_INFINITY_NODE;
|
|
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);
|
|
428
|
-
}
|
|
588
|
+
return createNumberNode(current);
|
|
429
589
|
case 'bigint':
|
|
430
590
|
return createBigIntNode(ctx, current);
|
|
431
|
-
case 'object':
|
|
432
|
-
|
|
433
|
-
return NULL_NODE;
|
|
434
|
-
}
|
|
435
|
-
// Non-primitive values needs a reference ID
|
|
436
|
-
// mostly because the values themselves are stateful
|
|
437
|
-
const id = createIndexedValue(ctx, current);
|
|
438
|
-
if (ctx.markedRefs.has(id)) {
|
|
439
|
-
return createIndexedValueNode(id);
|
|
440
|
-
}
|
|
441
|
-
if (hasReferenceID(current)) {
|
|
442
|
-
return createReferenceNode(id, current);
|
|
443
|
-
}
|
|
444
|
-
if (Array.isArray(current)) {
|
|
445
|
-
return generateArrayNode(ctx, id, current);
|
|
446
|
-
}
|
|
447
|
-
switch (current.constructor) {
|
|
448
|
-
case Date:
|
|
449
|
-
return createDateNode(id, current as unknown as Date);
|
|
450
|
-
case RegExp:
|
|
451
|
-
return createRegExpNode(id, current as unknown as RegExp);
|
|
452
|
-
case Promise:
|
|
453
|
-
return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
|
|
454
|
-
case ArrayBuffer:
|
|
455
|
-
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
456
|
-
case Int8Array:
|
|
457
|
-
case Int16Array:
|
|
458
|
-
case Int32Array:
|
|
459
|
-
case Uint8Array:
|
|
460
|
-
case Uint16Array:
|
|
461
|
-
case Uint32Array:
|
|
462
|
-
case Uint8ClampedArray:
|
|
463
|
-
case Float32Array:
|
|
464
|
-
case Float64Array:
|
|
465
|
-
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
466
|
-
case BigInt64Array:
|
|
467
|
-
case BigUint64Array:
|
|
468
|
-
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
469
|
-
case DataView:
|
|
470
|
-
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
471
|
-
case Map:
|
|
472
|
-
return generateMapNode(
|
|
473
|
-
ctx,
|
|
474
|
-
id,
|
|
475
|
-
current as unknown as Map<unknown, unknown>,
|
|
476
|
-
);
|
|
477
|
-
case Set:
|
|
478
|
-
return generateSetNode(
|
|
479
|
-
ctx,
|
|
480
|
-
id,
|
|
481
|
-
current as unknown as Set<unknown>,
|
|
482
|
-
);
|
|
483
|
-
case Object:
|
|
484
|
-
return generateObjectNode(
|
|
485
|
-
ctx,
|
|
486
|
-
id,
|
|
487
|
-
current as Record<string, unknown>,
|
|
488
|
-
false,
|
|
489
|
-
);
|
|
490
|
-
case undefined:
|
|
491
|
-
return generateObjectNode(
|
|
492
|
-
ctx,
|
|
493
|
-
id,
|
|
494
|
-
current as Record<string, unknown>,
|
|
495
|
-
true,
|
|
496
|
-
);
|
|
497
|
-
case AggregateError:
|
|
498
|
-
if (ctx.features & Feature.AggregateError) {
|
|
499
|
-
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
500
|
-
}
|
|
501
|
-
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
502
|
-
case Error:
|
|
503
|
-
case EvalError:
|
|
504
|
-
case RangeError:
|
|
505
|
-
case ReferenceError:
|
|
506
|
-
case SyntaxError:
|
|
507
|
-
case TypeError:
|
|
508
|
-
case URIError:
|
|
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);
|
|
522
|
-
default:
|
|
523
|
-
break;
|
|
524
|
-
}
|
|
525
|
-
if (current instanceof AggregateError) {
|
|
526
|
-
if (ctx.features & Feature.AggregateError) {
|
|
527
|
-
return generateAggregateErrorNode(ctx, id, current);
|
|
528
|
-
}
|
|
529
|
-
return generateErrorNode(ctx, id, current);
|
|
530
|
-
}
|
|
531
|
-
if (current instanceof Error) {
|
|
532
|
-
return generateErrorNode(ctx, id, current);
|
|
533
|
-
}
|
|
534
|
-
if (current instanceof Promise) {
|
|
535
|
-
return generatePromiseNode(ctx, id, current);
|
|
536
|
-
}
|
|
537
|
-
// Generator functions don't have a global constructor
|
|
538
|
-
if (Symbol.iterator in current) {
|
|
539
|
-
return generateIterableNode(ctx, id, current as Iterable<unknown>);
|
|
540
|
-
}
|
|
541
|
-
// For Promise-like objects
|
|
542
|
-
if ('then' in current && typeof current.then === 'function') {
|
|
543
|
-
return generatePromiseNode(ctx, id, current as PromiseLike<unknown>);
|
|
544
|
-
}
|
|
545
|
-
throw new Error('Unsupported type');
|
|
546
|
-
}
|
|
591
|
+
case 'object':
|
|
592
|
+
return parseObject(ctx, current);
|
|
547
593
|
case 'symbol':
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
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
|
-
}
|
|
594
|
+
return createSymbolNode(ctx, current);
|
|
595
|
+
case 'function':
|
|
596
|
+
return createFunctionNode(ctx, current);
|
|
564
597
|
default:
|
|
565
|
-
throw new
|
|
598
|
+
throw new UnsupportedTypeError(current);
|
|
566
599
|
}
|
|
567
600
|
}
|
|
568
|
-
|
|
569
|
-
export default async function parseAsync<T>(
|
|
570
|
-
ctx: ParserContext,
|
|
571
|
-
current: T,
|
|
572
|
-
) {
|
|
573
|
-
const result = await parse(ctx, current);
|
|
574
|
-
const isObject = result.t === SerovalNodeType.Object
|
|
575
|
-
|| result.t === SerovalNodeType.Iterable;
|
|
576
|
-
return [result, getRootID(ctx, current), isObject] as const;
|
|
577
|
-
}
|