seroval 0.5.1 → 0.6.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 +38 -0
- package/dist/cjs/development/index.cjs +236 -72
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +236 -72
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/compat.d.ts +3 -2
- package/dist/types/context.d.ts +3 -4
- package/dist/types/index.d.ts +9 -9
- package/dist/types/tree/async.d.ts +1 -2
- package/dist/types/tree/deserialize.d.ts +1 -2
- package/dist/types/tree/primitives.d.ts +4 -3
- package/dist/types/tree/reference.d.ts +6 -0
- package/dist/types/tree/sync.d.ts +1 -2
- package/dist/types/tree/types.d.ts +23 -5
- package/dist/types/tree/web-api.d.ts +4 -0
- package/dist/types/types.d.ts +2 -1
- package/package.json +3 -3
- package/src/compat.ts +2 -1
- package/src/context.ts +5 -6
- package/src/index.ts +10 -16
- package/src/tree/async.ts +82 -59
- package/src/tree/deserialize.ts +31 -20
- package/src/tree/primitives.ts +25 -3
- package/src/tree/reference.ts +61 -0
- package/src/tree/serialize.ts +30 -23
- package/src/tree/sync.ts +88 -52
- package/src/tree/types.ts +29 -5
- package/src/tree/web-api.ts +42 -0
- package/src/types.ts +6 -1
package/src/tree/serialize.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
markRef,
|
|
8
8
|
} from '../context';
|
|
9
9
|
import quote from '../quote';
|
|
10
|
+
import { GLOBAL_KEY } from './reference';
|
|
10
11
|
import { isValidIdentifier } from './shared';
|
|
11
12
|
import { SYMBOL_STRING } from './symbols';
|
|
12
13
|
import {
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
SerovalObjectNode,
|
|
23
24
|
SerovalObjectRecordNode,
|
|
24
25
|
SerovalPromiseNode,
|
|
25
|
-
|
|
26
|
+
SerovalIndexedValueNode,
|
|
26
27
|
SerovalSetNode,
|
|
27
28
|
SerovalTypedArrayNode,
|
|
28
29
|
} from './types';
|
|
@@ -194,7 +195,7 @@ function createObjectAssign(
|
|
|
194
195
|
createAssignment(ctx, getRefParam(ctx, ref) + '.' + key, value);
|
|
195
196
|
}
|
|
196
197
|
|
|
197
|
-
function
|
|
198
|
+
function assignIndexedValue(
|
|
198
199
|
ctx: SerializationContext,
|
|
199
200
|
index: number,
|
|
200
201
|
value: string,
|
|
@@ -205,11 +206,11 @@ function assignRef(
|
|
|
205
206
|
return value;
|
|
206
207
|
}
|
|
207
208
|
|
|
208
|
-
function
|
|
209
|
+
function isIndexedValueInStack(
|
|
209
210
|
ctx: SerializationContext,
|
|
210
211
|
node: SerovalNode,
|
|
211
|
-
): node is
|
|
212
|
-
return node.t === SerovalNodeType.
|
|
212
|
+
): node is SerovalIndexedValueNode {
|
|
213
|
+
return node.t === SerovalNodeType.IndexedValue && ctx.stack.includes(node.i);
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
function serializeNodeList(
|
|
@@ -232,7 +233,7 @@ function serializeNodeList(
|
|
|
232
233
|
// Check if index is a hole
|
|
233
234
|
if (item) {
|
|
234
235
|
// Check if item is a parent
|
|
235
|
-
if (
|
|
236
|
+
if (isIndexedValueInStack(ctx, item)) {
|
|
236
237
|
createArrayAssign(ctx, node.i, i, getRefParam(ctx, item.i));
|
|
237
238
|
isHoley = true;
|
|
238
239
|
} else {
|
|
@@ -253,7 +254,7 @@ function serializeArray(
|
|
|
253
254
|
ctx.stack.push(node.i);
|
|
254
255
|
const result = serializeNodeList(ctx, node);
|
|
255
256
|
ctx.stack.pop();
|
|
256
|
-
return
|
|
257
|
+
return assignIndexedValue(ctx, node.i, result);
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
function serializeProperties(
|
|
@@ -279,7 +280,7 @@ function serializeProperties(
|
|
|
279
280
|
// Test if key is a valid number or JS identifier
|
|
280
281
|
// so that we don't have to serialize the key and wrap with brackets
|
|
281
282
|
isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
282
|
-
if (
|
|
283
|
+
if (isIndexedValueInStack(ctx, val)) {
|
|
283
284
|
refParam = getRefParam(ctx, val.i);
|
|
284
285
|
if (isIdentifier && Number.isNaN(check)) {
|
|
285
286
|
createObjectAssign(ctx, sourceID, key, refParam);
|
|
@@ -359,11 +360,11 @@ function serializeDictionary(
|
|
|
359
360
|
markRef(ctx, i);
|
|
360
361
|
const assignments = serializeAssignments(ctx, i, d);
|
|
361
362
|
if (assignments) {
|
|
362
|
-
return '(' +
|
|
363
|
+
return '(' + assignIndexedValue(ctx, i, init) + ',' + assignments + getRefParam(ctx, i) + ')';
|
|
363
364
|
}
|
|
364
365
|
}
|
|
365
366
|
}
|
|
366
|
-
return
|
|
367
|
+
return assignIndexedValue(ctx, i, init);
|
|
367
368
|
}
|
|
368
369
|
|
|
369
370
|
function serializeNullConstructor(
|
|
@@ -377,7 +378,7 @@ function serializeObject(
|
|
|
377
378
|
ctx: SerializationContext,
|
|
378
379
|
node: SerovalObjectNode,
|
|
379
380
|
) {
|
|
380
|
-
return
|
|
381
|
+
return assignIndexedValue(ctx, node.i, serializeProperties(ctx, node.i, node.d));
|
|
381
382
|
}
|
|
382
383
|
|
|
383
384
|
function serializeSet(
|
|
@@ -393,7 +394,7 @@ function serializeSet(
|
|
|
393
394
|
let hasPrev = false;
|
|
394
395
|
for (let i = 0; i < size; i++) {
|
|
395
396
|
item = node.a[i];
|
|
396
|
-
if (
|
|
397
|
+
if (isIndexedValueInStack(ctx, item)) {
|
|
397
398
|
createSetAdd(ctx, node.i, getRefParam(ctx, item.i));
|
|
398
399
|
} else {
|
|
399
400
|
// Push directly
|
|
@@ -406,7 +407,7 @@ function serializeSet(
|
|
|
406
407
|
serialized += '([' + result + '])';
|
|
407
408
|
}
|
|
408
409
|
}
|
|
409
|
-
return
|
|
410
|
+
return assignIndexedValue(ctx, node.i, serialized);
|
|
410
411
|
}
|
|
411
412
|
|
|
412
413
|
function serializeMap(
|
|
@@ -427,11 +428,11 @@ function serializeMap(
|
|
|
427
428
|
// Check if key is a parent
|
|
428
429
|
key = node.d.k[i];
|
|
429
430
|
val = node.d.v[i];
|
|
430
|
-
if (
|
|
431
|
+
if (isIndexedValueInStack(ctx, key)) {
|
|
431
432
|
// Create reference for the map instance
|
|
432
433
|
keyRef = getRefParam(ctx, key.i);
|
|
433
434
|
// Check if value is a parent
|
|
434
|
-
if (
|
|
435
|
+
if (isIndexedValueInStack(ctx, val)) {
|
|
435
436
|
valueRef = getRefParam(ctx, val.i);
|
|
436
437
|
// Register an assignment since
|
|
437
438
|
// both key and value are a parent of this
|
|
@@ -448,7 +449,7 @@ function serializeMap(
|
|
|
448
449
|
createMapSet(ctx, node.i, keyRef, serializeTree(ctx, val));
|
|
449
450
|
ctx.stack = parent;
|
|
450
451
|
}
|
|
451
|
-
} else if (
|
|
452
|
+
} else if (isIndexedValueInStack(ctx, val)) {
|
|
452
453
|
// Create ref for the Map instance
|
|
453
454
|
valueRef = getRefParam(ctx, val.i);
|
|
454
455
|
// Reset stack for the key serialization
|
|
@@ -469,7 +470,7 @@ function serializeMap(
|
|
|
469
470
|
serialized += '([' + result + '])';
|
|
470
471
|
}
|
|
471
472
|
}
|
|
472
|
-
return
|
|
473
|
+
return assignIndexedValue(ctx, node.i, serialized);
|
|
473
474
|
}
|
|
474
475
|
|
|
475
476
|
function serializeAggregateError(
|
|
@@ -500,7 +501,7 @@ function serializePromise(
|
|
|
500
501
|
) {
|
|
501
502
|
let serialized: string;
|
|
502
503
|
// Check if resolved value is a parent expression
|
|
503
|
-
if (
|
|
504
|
+
if (isIndexedValueInStack(ctx, node.f)) {
|
|
504
505
|
// A Promise trick, reference the value
|
|
505
506
|
// inside the `then` expression so that
|
|
506
507
|
// the Promise evaluates after the parent
|
|
@@ -518,7 +519,7 @@ function serializePromise(
|
|
|
518
519
|
// just inline the value/reference here
|
|
519
520
|
serialized = 'Promise.resolve(' + result + ')';
|
|
520
521
|
}
|
|
521
|
-
return
|
|
522
|
+
return assignIndexedValue(ctx, node.i, serialized);
|
|
522
523
|
}
|
|
523
524
|
|
|
524
525
|
function serializeTypedArray(
|
|
@@ -531,7 +532,7 @@ function serializeTypedArray(
|
|
|
531
532
|
result += (i !== 0 ? ',' : '') + node.s[i] + (isBigInt ? 'n' : '');
|
|
532
533
|
}
|
|
533
534
|
const args = '[' + result + ']' + (node.l !== 0 ? (',' + node.l) : '');
|
|
534
|
-
return
|
|
535
|
+
return assignIndexedValue(ctx, node.i, 'new ' + node.c + '(' + args + ')');
|
|
535
536
|
}
|
|
536
537
|
|
|
537
538
|
function serializeIterable(
|
|
@@ -583,7 +584,7 @@ export default function serializeTree(
|
|
|
583
584
|
return 'NaN';
|
|
584
585
|
case SerovalNodeType.BigInt:
|
|
585
586
|
return node.s + 'n';
|
|
586
|
-
case SerovalNodeType.
|
|
587
|
+
case SerovalNodeType.IndexedValue:
|
|
587
588
|
return getRefParam(ctx, node.i);
|
|
588
589
|
case SerovalNodeType.Array:
|
|
589
590
|
return serializeArray(ctx, node);
|
|
@@ -592,9 +593,9 @@ export default function serializeTree(
|
|
|
592
593
|
case SerovalNodeType.NullConstructor:
|
|
593
594
|
return serializeNullConstructor(ctx, node);
|
|
594
595
|
case SerovalNodeType.Date:
|
|
595
|
-
return
|
|
596
|
+
return assignIndexedValue(ctx, node.i, 'new Date("' + node.s + '")');
|
|
596
597
|
case SerovalNodeType.RegExp:
|
|
597
|
-
return
|
|
598
|
+
return assignIndexedValue(ctx, node.i, '/' + node.c + '/' + node.m);
|
|
598
599
|
case SerovalNodeType.Set:
|
|
599
600
|
return serializeSet(ctx, node);
|
|
600
601
|
case SerovalNodeType.Map:
|
|
@@ -612,6 +613,12 @@ export default function serializeTree(
|
|
|
612
613
|
return serializePromise(ctx, node);
|
|
613
614
|
case SerovalNodeType.WKSymbol:
|
|
614
615
|
return SYMBOL_STRING[node.s];
|
|
616
|
+
case SerovalNodeType.URL:
|
|
617
|
+
return assignIndexedValue(ctx, node.i, 'new URL("' + node.s + '")');
|
|
618
|
+
case SerovalNodeType.URLSearchParams:
|
|
619
|
+
return assignIndexedValue(ctx, node.i, node.s ? 'new URLSearchParams("' + node.s + '")' : 'new URLSearchParams');
|
|
620
|
+
case SerovalNodeType.Reference:
|
|
621
|
+
return assignIndexedValue(ctx, node.i, GLOBAL_KEY + '.get("' + node.s + '")');
|
|
615
622
|
default:
|
|
616
623
|
throw new Error('Unsupported type');
|
|
617
624
|
}
|
package/src/tree/sync.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
import assert from '../assert';
|
|
3
3
|
import { Feature } from '../compat';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
4
|
+
import { createIndexedValue, getRootID, ParserContext } from '../context';
|
|
5
|
+
import quote from '../quote';
|
|
6
|
+
import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
|
|
6
7
|
import {
|
|
7
8
|
createBigIntNode,
|
|
8
9
|
createBigIntTypedArrayNode,
|
|
9
10
|
createDateNode,
|
|
10
11
|
createNumberNode,
|
|
11
|
-
|
|
12
|
+
createIndexedValueNode,
|
|
12
13
|
createRegExpNode,
|
|
13
14
|
createStringNode,
|
|
14
15
|
createTypedArrayNode,
|
|
@@ -21,14 +22,18 @@ import {
|
|
|
21
22
|
NULL_NODE,
|
|
22
23
|
TRUE_NODE,
|
|
23
24
|
UNDEFINED_NODE,
|
|
25
|
+
createReferenceNode,
|
|
24
26
|
} from './primitives';
|
|
27
|
+
import {
|
|
28
|
+
hasReferenceID,
|
|
29
|
+
} from './reference';
|
|
25
30
|
import {
|
|
26
31
|
getErrorConstructorName,
|
|
27
32
|
getErrorOptions,
|
|
28
33
|
getIterableOptions,
|
|
29
34
|
isIterable,
|
|
30
35
|
} from './shared';
|
|
31
|
-
import {
|
|
36
|
+
import { WellKnownSymbols } from './symbols';
|
|
32
37
|
import {
|
|
33
38
|
SerovalAggregateErrorNode,
|
|
34
39
|
SerovalArrayNode,
|
|
@@ -42,14 +47,15 @@ import {
|
|
|
42
47
|
SerovalObjectRecordNode,
|
|
43
48
|
SerovalSetNode,
|
|
44
49
|
} from './types';
|
|
50
|
+
import { createURLNode, createURLSearchParamsNode } from './web-api';
|
|
45
51
|
|
|
46
52
|
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode | SerovalIterableNode;
|
|
47
53
|
|
|
48
|
-
function generateNodeList(ctx: ParserContext, current:
|
|
54
|
+
function generateNodeList(ctx: ParserContext, current: unknown[]) {
|
|
49
55
|
const size = current.length;
|
|
50
56
|
const nodes = new Array<SerovalNode>(size);
|
|
51
|
-
const deferred = new Array<
|
|
52
|
-
let item:
|
|
57
|
+
const deferred = new Array<unknown>(size);
|
|
58
|
+
let item: unknown;
|
|
53
59
|
for (let i = 0; i < size; i++) {
|
|
54
60
|
if (i in current) {
|
|
55
61
|
item = current[i];
|
|
@@ -71,7 +77,7 @@ function generateNodeList(ctx: ParserContext, current: ServerValue[]) {
|
|
|
71
77
|
function generateArrayNode(
|
|
72
78
|
ctx: ParserContext,
|
|
73
79
|
id: number,
|
|
74
|
-
current:
|
|
80
|
+
current: unknown[],
|
|
75
81
|
): SerovalArrayNode {
|
|
76
82
|
return {
|
|
77
83
|
t: SerovalNodeType.Array,
|
|
@@ -89,14 +95,14 @@ function generateArrayNode(
|
|
|
89
95
|
function generateMapNode(
|
|
90
96
|
ctx: ParserContext,
|
|
91
97
|
id: number,
|
|
92
|
-
current: Map<
|
|
98
|
+
current: Map<unknown, unknown>,
|
|
93
99
|
): SerovalMapNode {
|
|
94
100
|
assert(ctx.features & Feature.Map, 'Unsupported type "Map"');
|
|
95
101
|
const len = current.size;
|
|
96
102
|
const keyNodes = new Array<SerovalNode>(len);
|
|
97
103
|
const valueNodes = new Array<SerovalNode>(len);
|
|
98
|
-
const deferredKey = new Array<
|
|
99
|
-
const deferredValue = new Array<
|
|
104
|
+
const deferredKey = new Array<unknown>(len);
|
|
105
|
+
const deferredValue = new Array<unknown>(len);
|
|
100
106
|
let deferredSize = 0;
|
|
101
107
|
let nodeSize = 0;
|
|
102
108
|
for (const [key, value] of current.entries()) {
|
|
@@ -131,12 +137,12 @@ function generateMapNode(
|
|
|
131
137
|
function generateSetNode(
|
|
132
138
|
ctx: ParserContext,
|
|
133
139
|
id: number,
|
|
134
|
-
current: Set<
|
|
140
|
+
current: Set<unknown>,
|
|
135
141
|
): SerovalSetNode {
|
|
136
142
|
assert(ctx.features & Feature.Set, 'Unsupported type "Set"');
|
|
137
143
|
const len = current.size;
|
|
138
144
|
const nodes = new Array<SerovalNode>(len);
|
|
139
|
-
const deferred = new Array<
|
|
145
|
+
const deferred = new Array<unknown>(len);
|
|
140
146
|
let deferredSize = 0;
|
|
141
147
|
let nodeSize = 0;
|
|
142
148
|
for (const item of current.keys()) {
|
|
@@ -166,17 +172,17 @@ function generateSetNode(
|
|
|
166
172
|
|
|
167
173
|
function generateProperties(
|
|
168
174
|
ctx: ParserContext,
|
|
169
|
-
properties: Record<string,
|
|
175
|
+
properties: Record<string, unknown>,
|
|
170
176
|
): SerovalObjectRecordNode {
|
|
171
177
|
const keys = Object.keys(properties);
|
|
172
178
|
const size = keys.length;
|
|
173
179
|
const keyNodes = new Array<string>(size);
|
|
174
180
|
const valueNodes = new Array<SerovalNode>(size);
|
|
175
181
|
const deferredKeys = new Array<string>(size);
|
|
176
|
-
const deferredValues = new Array<
|
|
182
|
+
const deferredValues = new Array<unknown>(size);
|
|
177
183
|
let deferredSize = 0;
|
|
178
184
|
let nodesSize = 0;
|
|
179
|
-
let item:
|
|
185
|
+
let item: unknown;
|
|
180
186
|
for (const key of keys) {
|
|
181
187
|
item = properties[key];
|
|
182
188
|
if (isIterable(item)) {
|
|
@@ -203,7 +209,7 @@ function generateProperties(
|
|
|
203
209
|
function generateIterableNode(
|
|
204
210
|
ctx: ParserContext,
|
|
205
211
|
id: number,
|
|
206
|
-
current: Iterable<
|
|
212
|
+
current: Iterable<unknown>,
|
|
207
213
|
): SerovalIterableNode {
|
|
208
214
|
assert(ctx.features & Feature.Symbol, 'Unsupported type "Iterable"');
|
|
209
215
|
const options = getIterableOptions(current);
|
|
@@ -217,7 +223,7 @@ function generateIterableNode(
|
|
|
217
223
|
m: undefined,
|
|
218
224
|
// Parse options first before the items
|
|
219
225
|
d: options
|
|
220
|
-
? generateProperties(ctx, options
|
|
226
|
+
? generateProperties(ctx, options)
|
|
221
227
|
: undefined,
|
|
222
228
|
a: generateNodeList(ctx, array),
|
|
223
229
|
f: undefined,
|
|
@@ -227,7 +233,7 @@ function generateIterableNode(
|
|
|
227
233
|
function generateObjectNode(
|
|
228
234
|
ctx: ParserContext,
|
|
229
235
|
id: number,
|
|
230
|
-
current: Record<string,
|
|
236
|
+
current: Record<string, unknown> | Iterable<unknown>,
|
|
231
237
|
empty: boolean,
|
|
232
238
|
): ObjectLikeNode {
|
|
233
239
|
if (Symbol.iterator in current) {
|
|
@@ -261,9 +267,9 @@ function generateAggregateErrorNode(
|
|
|
261
267
|
s: undefined,
|
|
262
268
|
l: current.errors.length,
|
|
263
269
|
c: undefined,
|
|
264
|
-
m: current.message,
|
|
270
|
+
m: quote(current.message),
|
|
265
271
|
d: optionsNode,
|
|
266
|
-
a: generateNodeList(ctx, current.errors as
|
|
272
|
+
a: generateNodeList(ctx, current.errors as unknown[]),
|
|
267
273
|
f: undefined,
|
|
268
274
|
};
|
|
269
275
|
}
|
|
@@ -283,16 +289,16 @@ function generateErrorNode(
|
|
|
283
289
|
s: undefined,
|
|
284
290
|
l: undefined,
|
|
285
291
|
c: getErrorConstructorName(current),
|
|
286
|
-
m: current.message,
|
|
292
|
+
m: quote(current.message),
|
|
287
293
|
d: optionsNode,
|
|
288
294
|
a: undefined,
|
|
289
295
|
f: undefined,
|
|
290
296
|
};
|
|
291
297
|
}
|
|
292
298
|
|
|
293
|
-
function parse(
|
|
299
|
+
function parse<T>(
|
|
294
300
|
ctx: ParserContext,
|
|
295
|
-
current:
|
|
301
|
+
current: T,
|
|
296
302
|
): SerovalNode {
|
|
297
303
|
switch (typeof current) {
|
|
298
304
|
case 'boolean':
|
|
@@ -305,16 +311,16 @@ function parse(
|
|
|
305
311
|
switch (current) {
|
|
306
312
|
case Infinity: return INFINITY_NODE;
|
|
307
313
|
case -Infinity: return NEG_INFINITY_NODE;
|
|
308
|
-
default:
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
314
|
+
default:
|
|
315
|
+
// eslint-disable-next-line no-self-compare
|
|
316
|
+
if (current !== current) {
|
|
317
|
+
return NAN_NODE;
|
|
318
|
+
}
|
|
319
|
+
if (Object.is(current, -0)) {
|
|
320
|
+
return NEG_ZERO_NODE;
|
|
321
|
+
}
|
|
322
|
+
return createNumberNode(current);
|
|
316
323
|
}
|
|
317
|
-
return createNumberNode(current);
|
|
318
324
|
case 'bigint':
|
|
319
325
|
return createBigIntNode(ctx, current);
|
|
320
326
|
case 'object': {
|
|
@@ -323,18 +329,21 @@ function parse(
|
|
|
323
329
|
}
|
|
324
330
|
// Non-primitive values needs a reference ID
|
|
325
331
|
// mostly because the values themselves are stateful
|
|
326
|
-
const id =
|
|
332
|
+
const id = createIndexedValue(ctx, current);
|
|
327
333
|
if (ctx.markedRefs.has(id)) {
|
|
328
|
-
return
|
|
334
|
+
return createIndexedValueNode(id);
|
|
335
|
+
}
|
|
336
|
+
if (hasReferenceID(current)) {
|
|
337
|
+
return createReferenceNode(id, current);
|
|
329
338
|
}
|
|
330
339
|
if (Array.isArray(current)) {
|
|
331
340
|
return generateArrayNode(ctx, id, current);
|
|
332
341
|
}
|
|
333
342
|
switch (current.constructor) {
|
|
334
343
|
case Date:
|
|
335
|
-
return createDateNode(id, current as Date);
|
|
344
|
+
return createDateNode(id, current as unknown as Date);
|
|
336
345
|
case RegExp:
|
|
337
|
-
return createRegExpNode(id, current as RegExp);
|
|
346
|
+
return createRegExpNode(id, current as unknown as RegExp);
|
|
338
347
|
case Int8Array:
|
|
339
348
|
case Int16Array:
|
|
340
349
|
case Int32Array:
|
|
@@ -344,23 +353,33 @@ function parse(
|
|
|
344
353
|
case Uint8ClampedArray:
|
|
345
354
|
case Float32Array:
|
|
346
355
|
case Float64Array:
|
|
347
|
-
return createTypedArrayNode(ctx, id, current as TypedArrayValue);
|
|
356
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
348
357
|
case BigInt64Array:
|
|
349
358
|
case BigUint64Array:
|
|
350
|
-
return createBigIntTypedArrayNode(ctx, id, current as BigIntTypedArrayValue);
|
|
359
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
351
360
|
case Map:
|
|
352
|
-
return generateMapNode(ctx, id, current as Map<
|
|
361
|
+
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
353
362
|
case Set:
|
|
354
|
-
return generateSetNode(ctx, id, current as Set<
|
|
363
|
+
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
355
364
|
case Object:
|
|
356
|
-
return generateObjectNode(
|
|
365
|
+
return generateObjectNode(
|
|
366
|
+
ctx,
|
|
367
|
+
id,
|
|
368
|
+
current as unknown as Record<string, unknown>,
|
|
369
|
+
false,
|
|
370
|
+
);
|
|
357
371
|
case undefined:
|
|
358
|
-
return generateObjectNode(
|
|
372
|
+
return generateObjectNode(
|
|
373
|
+
ctx,
|
|
374
|
+
id,
|
|
375
|
+
current as unknown as Record<string, unknown>,
|
|
376
|
+
true,
|
|
377
|
+
);
|
|
359
378
|
case AggregateError:
|
|
360
379
|
if (ctx.features & Feature.AggregateError) {
|
|
361
|
-
return generateAggregateErrorNode(ctx, id, current as AggregateError);
|
|
380
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
362
381
|
}
|
|
363
|
-
return generateErrorNode(ctx, id, current as AggregateError);
|
|
382
|
+
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
364
383
|
case Error:
|
|
365
384
|
case EvalError:
|
|
366
385
|
case RangeError:
|
|
@@ -368,7 +387,11 @@ function parse(
|
|
|
368
387
|
case SyntaxError:
|
|
369
388
|
case TypeError:
|
|
370
389
|
case URIError:
|
|
371
|
-
return generateErrorNode(ctx, id, current as Error);
|
|
390
|
+
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
391
|
+
case URL:
|
|
392
|
+
return createURLNode(ctx, id, current as unknown as URL);
|
|
393
|
+
case URLSearchParams:
|
|
394
|
+
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
372
395
|
default:
|
|
373
396
|
break;
|
|
374
397
|
}
|
|
@@ -383,22 +406,35 @@ function parse(
|
|
|
383
406
|
}
|
|
384
407
|
// Generator functions don't have a global constructor
|
|
385
408
|
if (Symbol.iterator in current) {
|
|
386
|
-
return generateIterableNode(ctx, id, current);
|
|
409
|
+
return generateIterableNode(ctx, id, current as Iterable<unknown>);
|
|
387
410
|
}
|
|
388
411
|
throw new Error('Unsupported type');
|
|
389
412
|
}
|
|
390
413
|
case 'symbol':
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
414
|
+
if (hasReferenceID(current)) {
|
|
415
|
+
const id = createIndexedValue(ctx, current);
|
|
416
|
+
if (ctx.markedRefs.has(id)) {
|
|
417
|
+
return createIndexedValueNode(id);
|
|
418
|
+
}
|
|
419
|
+
return createReferenceNode(id, current);
|
|
420
|
+
}
|
|
421
|
+
return createWKSymbolNode(ctx, current as WellKnownSymbols);
|
|
422
|
+
case 'function': {
|
|
423
|
+
assert(hasReferenceID(current), 'Cannot serialize function without reference ID.');
|
|
424
|
+
const id = createIndexedValue(ctx, current);
|
|
425
|
+
if (ctx.markedRefs.has(id)) {
|
|
426
|
+
return createIndexedValueNode(id);
|
|
427
|
+
}
|
|
428
|
+
return createReferenceNode(id, current);
|
|
429
|
+
}
|
|
394
430
|
default:
|
|
395
431
|
throw new Error('Unsupported type');
|
|
396
432
|
}
|
|
397
433
|
}
|
|
398
434
|
|
|
399
|
-
export default function parseSync(
|
|
435
|
+
export default function parseSync<T>(
|
|
400
436
|
ctx: ParserContext,
|
|
401
|
-
current:
|
|
437
|
+
current: T,
|
|
402
438
|
) {
|
|
403
439
|
const result = parse(ctx, current);
|
|
404
440
|
const isObject = result.t === SerovalNodeType.Object
|
package/src/tree/types.ts
CHANGED
|
@@ -11,7 +11,7 @@ export const enum SerovalNodeType {
|
|
|
11
11
|
NegativeInfinity,
|
|
12
12
|
NaN,
|
|
13
13
|
BigInt,
|
|
14
|
-
|
|
14
|
+
IndexedValue,
|
|
15
15
|
Date,
|
|
16
16
|
RegExp,
|
|
17
17
|
Set,
|
|
@@ -26,6 +26,9 @@ export const enum SerovalNodeType {
|
|
|
26
26
|
TypedArray,
|
|
27
27
|
BigIntTypedArray,
|
|
28
28
|
WKSymbol,
|
|
29
|
+
URL,
|
|
30
|
+
URLSearchParams,
|
|
31
|
+
Reference,
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
export interface SerovalBaseNode {
|
|
@@ -115,8 +118,8 @@ export type SerovalPrimitiveNode =
|
|
|
115
118
|
| SerovalInfinityNode
|
|
116
119
|
| SerovalNaNNode;
|
|
117
120
|
|
|
118
|
-
export interface
|
|
119
|
-
t: SerovalNodeType.
|
|
121
|
+
export interface SerovalIndexedValueNode extends SerovalBaseNode {
|
|
122
|
+
t: SerovalNodeType.IndexedValue;
|
|
120
123
|
i: number;
|
|
121
124
|
}
|
|
122
125
|
|
|
@@ -231,9 +234,27 @@ export interface SerovalWKSymbolNode extends SerovalBaseNode {
|
|
|
231
234
|
s: Symbols;
|
|
232
235
|
}
|
|
233
236
|
|
|
237
|
+
export interface SerovalURLNode extends SerovalBaseNode {
|
|
238
|
+
t: SerovalNodeType.URL;
|
|
239
|
+
i: number;
|
|
240
|
+
s: string;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export interface SerovalURLSearchParamsNode extends SerovalBaseNode {
|
|
244
|
+
t: SerovalNodeType.URLSearchParams;
|
|
245
|
+
i: number;
|
|
246
|
+
s: string;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface SerovalReferenceNode extends SerovalBaseNode {
|
|
250
|
+
t: SerovalNodeType.Reference;
|
|
251
|
+
i: number;
|
|
252
|
+
s: string;
|
|
253
|
+
}
|
|
254
|
+
|
|
234
255
|
export type SerovalNode =
|
|
235
256
|
| SerovalPrimitiveNode
|
|
236
|
-
|
|
|
257
|
+
| SerovalIndexedValueNode
|
|
237
258
|
| SerovalSemiPrimitiveNode
|
|
238
259
|
| SerovalSetNode
|
|
239
260
|
| SerovalMapNode
|
|
@@ -244,4 +265,7 @@ export type SerovalNode =
|
|
|
244
265
|
| SerovalErrorNode
|
|
245
266
|
| SerovalAggregateErrorNode
|
|
246
267
|
| SerovalIterableNode
|
|
247
|
-
| SerovalWKSymbolNode
|
|
268
|
+
| SerovalWKSymbolNode
|
|
269
|
+
| SerovalURLNode
|
|
270
|
+
| SerovalURLSearchParamsNode
|
|
271
|
+
| SerovalReferenceNode;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import assert from '../assert';
|
|
2
|
+
import { Feature } from '../compat';
|
|
3
|
+
import { ParserContext } from '../context';
|
|
4
|
+
import { SerovalNodeType, SerovalURLNode, SerovalURLSearchParamsNode } from './types';
|
|
5
|
+
|
|
6
|
+
export function createURLNode(
|
|
7
|
+
ctx: ParserContext,
|
|
8
|
+
id: number,
|
|
9
|
+
current: URL,
|
|
10
|
+
): SerovalURLNode {
|
|
11
|
+
assert(ctx.features & Feature.WebAPI, 'Unsupported type "URL"');
|
|
12
|
+
return {
|
|
13
|
+
t: SerovalNodeType.URL,
|
|
14
|
+
i: id,
|
|
15
|
+
s: current.href,
|
|
16
|
+
l: undefined,
|
|
17
|
+
c: undefined,
|
|
18
|
+
m: undefined,
|
|
19
|
+
d: undefined,
|
|
20
|
+
f: undefined,
|
|
21
|
+
a: undefined,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function createURLSearchParamsNode(
|
|
26
|
+
ctx: ParserContext,
|
|
27
|
+
id: number,
|
|
28
|
+
current: URLSearchParams,
|
|
29
|
+
): SerovalURLSearchParamsNode {
|
|
30
|
+
assert(ctx.features & Feature.WebAPI, 'Unsupported type "URLSearchParams"');
|
|
31
|
+
return {
|
|
32
|
+
t: SerovalNodeType.URLSearchParams,
|
|
33
|
+
i: id,
|
|
34
|
+
s: current.toString(),
|
|
35
|
+
l: undefined,
|
|
36
|
+
c: undefined,
|
|
37
|
+
m: undefined,
|
|
38
|
+
d: undefined,
|
|
39
|
+
f: undefined,
|
|
40
|
+
a: undefined,
|
|
41
|
+
};
|
|
42
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -34,12 +34,17 @@ export type BigIntTypedArrayValue =
|
|
|
34
34
|
| BigInt64Array
|
|
35
35
|
| BigUint64Array;
|
|
36
36
|
|
|
37
|
+
export type WebAPIValue =
|
|
38
|
+
| URL
|
|
39
|
+
| URLSearchParams;
|
|
40
|
+
|
|
37
41
|
export type SemiPrimitiveValue =
|
|
38
42
|
| RegExp
|
|
39
43
|
| Date
|
|
40
44
|
| TypedArrayValue
|
|
41
45
|
| BigIntTypedArrayValue
|
|
42
|
-
| bigint
|
|
46
|
+
| bigint
|
|
47
|
+
| WebAPIValue;
|
|
43
48
|
|
|
44
49
|
export type CommonServerValue =
|
|
45
50
|
| PrimitiveValue
|