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