seroval 0.4.1 → 0.5.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 +569 -118
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -2
- package/dist/esm/development/index.mjs +569 -118
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -2
- package/dist/types/compat.d.ts +1 -1
- package/dist/types/context.d.ts +2 -0
- package/dist/types/quote.d.ts +1 -0
- package/dist/types/tree/deserialize.d.ts +4 -0
- package/dist/types/tree/primitives.d.ts +13 -9
- package/dist/types/tree/shared.d.ts +4 -1
- package/dist/types/tree/symbols.d.ts +33 -0
- package/dist/types/tree/types.d.ts +73 -27
- package/dist/types/types.d.ts +2 -1
- package/package.json +4 -4
- package/src/compat.ts +1 -1
- package/src/context.ts +4 -0
- package/src/index.ts +6 -1
- package/src/quote.ts +12 -1
- package/src/tree/async.ts +30 -16
- package/src/tree/deserialize.ts +288 -0
- package/src/tree/iterator.ts +14 -0
- package/src/tree/primitives.ts +147 -24
- package/src/tree/serialize.ts +55 -19
- package/src/tree/shared.ts +46 -2
- package/src/tree/symbols.ts +65 -0
- package/src/tree/sync.ts +30 -16
- package/src/tree/types.ts +84 -16
- package/src/types.ts +4 -1
package/src/tree/serialize.ts
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
markRef,
|
|
8
8
|
} from '../context';
|
|
9
9
|
import quote from '../quote';
|
|
10
|
+
import { isValidIdentifier } from './shared';
|
|
11
|
+
import { SYMBOL_STRING } from './symbols';
|
|
10
12
|
import {
|
|
11
13
|
SerovalAggregateErrorNode,
|
|
12
14
|
SerovalArrayNode,
|
|
@@ -17,6 +19,7 @@ import {
|
|
|
17
19
|
SerovalNode,
|
|
18
20
|
SerovalNodeType,
|
|
19
21
|
SerovalNullConstructorNode,
|
|
22
|
+
SerovalObjectNode,
|
|
20
23
|
SerovalObjectRecordNode,
|
|
21
24
|
SerovalPromiseNode,
|
|
22
25
|
SerovalReferenceNode,
|
|
@@ -189,16 +192,14 @@ function isReferenceInStack(
|
|
|
189
192
|
return node.t === SerovalNodeType.Reference && ctx.stack.includes(node.i);
|
|
190
193
|
}
|
|
191
194
|
|
|
192
|
-
const IDENTIFIER_CHECK = /^([$A-Z_][0-9A-Z_$]*)$/i;
|
|
193
|
-
|
|
194
195
|
function serializeNodeList(
|
|
195
196
|
ctx: SerializationContext,
|
|
196
|
-
node: SerovalArrayNode | SerovalIterableNode,
|
|
197
|
+
node: SerovalArrayNode | SerovalIterableNode | SerovalAggregateErrorNode,
|
|
197
198
|
) {
|
|
198
199
|
// This is different than Map and Set
|
|
199
200
|
// because we also need to serialize
|
|
200
201
|
// the holes of the Array
|
|
201
|
-
const size = node.
|
|
202
|
+
const size = node.l;
|
|
202
203
|
let values = '';
|
|
203
204
|
let item: SerovalNode;
|
|
204
205
|
let isHoley = false;
|
|
@@ -238,7 +239,7 @@ function serializeArray(
|
|
|
238
239
|
return assignRef(ctx, node.i, result);
|
|
239
240
|
}
|
|
240
241
|
|
|
241
|
-
function
|
|
242
|
+
function serializeProperties(
|
|
242
243
|
ctx: SerializationContext,
|
|
243
244
|
sourceID: number,
|
|
244
245
|
node: SerovalObjectRecordNode,
|
|
@@ -260,19 +261,19 @@ function serializeObject(
|
|
|
260
261
|
check = Number(key);
|
|
261
262
|
// Test if key is a valid number or JS identifier
|
|
262
263
|
// so that we don't have to serialize the key and wrap with brackets
|
|
263
|
-
isIdentifier = check >= 0 ||
|
|
264
|
+
isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
264
265
|
if (isReferenceInStack(ctx, val)) {
|
|
265
266
|
refParam = getRefParam(ctx, val.i);
|
|
266
267
|
if (isIdentifier && Number.isNaN(check)) {
|
|
267
268
|
createObjectAssign(ctx, sourceID, key, refParam);
|
|
268
269
|
} else {
|
|
269
|
-
createArrayAssign(ctx, sourceID, isIdentifier ? key : quote(key), refParam);
|
|
270
|
+
createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
|
|
270
271
|
}
|
|
271
272
|
} else {
|
|
272
273
|
if (hasPrev) {
|
|
273
274
|
result += ',';
|
|
274
275
|
}
|
|
275
|
-
result += isIdentifier ? key : quote(key);
|
|
276
|
+
result += isIdentifier ? key : ('"' + quote(key) + '"');
|
|
276
277
|
result += ':' + serializeTree(ctx, val);
|
|
277
278
|
hasPrev = true;
|
|
278
279
|
}
|
|
@@ -287,7 +288,7 @@ function serializeWithObjectAssign(
|
|
|
287
288
|
id: number,
|
|
288
289
|
serialized: string,
|
|
289
290
|
) {
|
|
290
|
-
const fields =
|
|
291
|
+
const fields = serializeProperties(ctx, id, value);
|
|
291
292
|
if (fields !== '{}') {
|
|
292
293
|
return 'Object.assign(' + serialized + ',' + fields + ')';
|
|
293
294
|
}
|
|
@@ -318,11 +319,11 @@ function serializeAssignments(
|
|
|
318
319
|
ctx.assignments = mainAssignments;
|
|
319
320
|
// Test if key is a valid number or JS identifier
|
|
320
321
|
// so that we don't have to serialize the key and wrap with brackets
|
|
321
|
-
isIdentifier = check >= 0 ||
|
|
322
|
+
isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
322
323
|
if (isIdentifier && Number.isNaN(check)) {
|
|
323
324
|
createObjectAssign(ctx, sourceID, key, refParam);
|
|
324
325
|
} else {
|
|
325
|
-
createArrayAssign(ctx, sourceID, isIdentifier ? key : quote(key), refParam);
|
|
326
|
+
createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
|
|
326
327
|
}
|
|
327
328
|
ctx.assignments = parentAssignment;
|
|
328
329
|
}
|
|
@@ -358,12 +359,19 @@ function serializeNullConstructor(
|
|
|
358
359
|
return serializeDictionary(ctx, node.i, node.d, 'Object.create(null)');
|
|
359
360
|
}
|
|
360
361
|
|
|
362
|
+
function serializeObject(
|
|
363
|
+
ctx: SerializationContext,
|
|
364
|
+
node: SerovalObjectNode,
|
|
365
|
+
) {
|
|
366
|
+
return assignRef(ctx, node.i, serializeProperties(ctx, node.i, node.d));
|
|
367
|
+
}
|
|
368
|
+
|
|
361
369
|
function serializeSet(
|
|
362
370
|
ctx: SerializationContext,
|
|
363
371
|
node: SerovalSetNode,
|
|
364
372
|
) {
|
|
365
373
|
let serialized = 'new Set';
|
|
366
|
-
const size = node.
|
|
374
|
+
const size = node.l;
|
|
367
375
|
if (size) {
|
|
368
376
|
let result = '';
|
|
369
377
|
ctx.stack.push(node.i);
|
|
@@ -462,7 +470,7 @@ function serializeAggregateError(
|
|
|
462
470
|
) {
|
|
463
471
|
// Serialize the required arguments
|
|
464
472
|
ctx.stack.push(node.i);
|
|
465
|
-
const serialized = 'new AggregateError(' +
|
|
473
|
+
const serialized = 'new AggregateError(' + serializeNodeList(ctx, node) + ',"' + quote(node.m) + '")';
|
|
466
474
|
ctx.stack.pop();
|
|
467
475
|
// `AggregateError` might've been extended
|
|
468
476
|
// either through class or custom properties
|
|
@@ -474,7 +482,7 @@ function serializeError(
|
|
|
474
482
|
ctx: SerializationContext,
|
|
475
483
|
node: SerovalErrorNode,
|
|
476
484
|
) {
|
|
477
|
-
const serialized = 'new ' + node.c + '(' + quote(node.m) + ')';
|
|
485
|
+
const serialized = 'new ' + node.c + '("' + quote(node.m) + '")';
|
|
478
486
|
return serializeDictionary(ctx, node.i, node.d, serialized);
|
|
479
487
|
}
|
|
480
488
|
|
|
@@ -509,7 +517,17 @@ function serializeTypedArray(
|
|
|
509
517
|
ctx: SerializationContext,
|
|
510
518
|
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
|
|
511
519
|
) {
|
|
512
|
-
let
|
|
520
|
+
let result = '';
|
|
521
|
+
for (let i = 0, len = node.s.length; i < len; i++) {
|
|
522
|
+
if (i !== 0) {
|
|
523
|
+
result += ',';
|
|
524
|
+
}
|
|
525
|
+
result += node.s[i];
|
|
526
|
+
if (node.t === SerovalNodeType.BigIntTypedArray) {
|
|
527
|
+
result += 'n';
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
let args = '[' + result + ']';
|
|
513
531
|
if (node.l !== 0) {
|
|
514
532
|
args += ',' + node.l.toString();
|
|
515
533
|
}
|
|
@@ -545,22 +563,38 @@ export default function serializeTree(
|
|
|
545
563
|
node: SerovalNode,
|
|
546
564
|
): string {
|
|
547
565
|
switch (node.t) {
|
|
548
|
-
case SerovalNodeType.
|
|
566
|
+
case SerovalNodeType.Number:
|
|
549
567
|
return String(node.s);
|
|
568
|
+
case SerovalNodeType.String:
|
|
569
|
+
return '"' + node.s + '"';
|
|
570
|
+
case SerovalNodeType.Boolean:
|
|
571
|
+
return node.s ? '!0' : '!1';
|
|
572
|
+
case SerovalNodeType.Undefined:
|
|
573
|
+
return 'undefined';
|
|
574
|
+
case SerovalNodeType.Null:
|
|
575
|
+
return 'null';
|
|
576
|
+
case SerovalNodeType.NegativeZero:
|
|
577
|
+
return '-0';
|
|
578
|
+
case SerovalNodeType.Infinity:
|
|
579
|
+
return '1/0';
|
|
580
|
+
case SerovalNodeType.NegativeInfinity:
|
|
581
|
+
return '-1/0';
|
|
582
|
+
case SerovalNodeType.NaN:
|
|
583
|
+
return 'NaN';
|
|
550
584
|
case SerovalNodeType.BigInt:
|
|
551
|
-
return node.s;
|
|
585
|
+
return node.s + 'n';
|
|
552
586
|
case SerovalNodeType.Reference:
|
|
553
587
|
return getRefParam(ctx, node.i);
|
|
554
588
|
case SerovalNodeType.Array:
|
|
555
589
|
return serializeArray(ctx, node);
|
|
556
590
|
case SerovalNodeType.Object:
|
|
557
|
-
return
|
|
591
|
+
return serializeObject(ctx, node);
|
|
558
592
|
case SerovalNodeType.NullConstructor:
|
|
559
593
|
return serializeNullConstructor(ctx, node);
|
|
560
594
|
case SerovalNodeType.Date:
|
|
561
595
|
return assignRef(ctx, node.i, 'new Date("' + node.s + '")');
|
|
562
596
|
case SerovalNodeType.RegExp:
|
|
563
|
-
return assignRef(ctx, node.i, node.
|
|
597
|
+
return assignRef(ctx, node.i, '/' + node.c + '/' + node.m);
|
|
564
598
|
case SerovalNodeType.Set:
|
|
565
599
|
return serializeSet(ctx, node);
|
|
566
600
|
case SerovalNodeType.Map:
|
|
@@ -576,6 +610,8 @@ export default function serializeTree(
|
|
|
576
610
|
return serializeIterable(ctx, node);
|
|
577
611
|
case SerovalNodeType.Promise:
|
|
578
612
|
return serializePromise(ctx, node);
|
|
613
|
+
case SerovalNodeType.WKSymbol:
|
|
614
|
+
return SYMBOL_STRING[node.s];
|
|
579
615
|
default:
|
|
580
616
|
throw new Error('Unsupported type');
|
|
581
617
|
}
|
package/src/tree/shared.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
ErrorValue,
|
|
6
6
|
} from '../types';
|
|
7
7
|
|
|
8
|
-
export function
|
|
8
|
+
export function getErrorConstructorName(error: ErrorValue) {
|
|
9
9
|
if (error instanceof EvalError) {
|
|
10
10
|
return 'EvalError';
|
|
11
11
|
}
|
|
@@ -27,12 +27,26 @@ export function getErrorConstructor(error: ErrorValue) {
|
|
|
27
27
|
return 'Error';
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export function getErrorConstructor(errorName: string) {
|
|
31
|
+
switch (errorName) {
|
|
32
|
+
case 'Error': return Error;
|
|
33
|
+
case 'EvalError': return EvalError;
|
|
34
|
+
case 'RangeError': return RangeError;
|
|
35
|
+
case 'ReferenceError': return ReferenceError;
|
|
36
|
+
case 'SyntaxError': return SyntaxError;
|
|
37
|
+
case 'TypeError': return TypeError;
|
|
38
|
+
case 'URIError': return URIError;
|
|
39
|
+
default:
|
|
40
|
+
throw new Error(`Unknown Error constructor "${errorName}"`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
30
44
|
export function getErrorOptions(
|
|
31
45
|
ctx: ParserContext,
|
|
32
46
|
error: Error,
|
|
33
47
|
) {
|
|
34
48
|
let options: Record<string, any> | undefined;
|
|
35
|
-
const constructor =
|
|
49
|
+
const constructor = getErrorConstructorName(error);
|
|
36
50
|
// Name has been modified
|
|
37
51
|
if (error.name !== constructor) {
|
|
38
52
|
options = { name: error.name };
|
|
@@ -99,3 +113,33 @@ export function isIterable(
|
|
|
99
113
|
}
|
|
100
114
|
return Symbol.iterator in value;
|
|
101
115
|
}
|
|
116
|
+
|
|
117
|
+
export function getTypedArrayConstructor(name: string) {
|
|
118
|
+
switch (name) {
|
|
119
|
+
case 'Int8Array': return Int8Array;
|
|
120
|
+
case 'Int16Array': return Int16Array;
|
|
121
|
+
case 'Int32Array': return Int32Array;
|
|
122
|
+
case 'Uint8Array': return Uint8Array;
|
|
123
|
+
case 'Uint16Array': return Uint16Array;
|
|
124
|
+
case 'Uint32Array': return Uint32Array;
|
|
125
|
+
case 'Uint8ClampedArray': return Uint8ClampedArray;
|
|
126
|
+
case 'Float32Array': return Float32Array;
|
|
127
|
+
case 'Float64Array': return Float64Array;
|
|
128
|
+
case 'BigInt64Array': return BigInt64Array;
|
|
129
|
+
case 'BigUint64Array': return BigUint64Array;
|
|
130
|
+
default:
|
|
131
|
+
throw new Error(`Unknown TypedArray "${name}"`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const IDENTIFIER_CHECK = /^[$A-Z_][0-9A-Z_$]*$/i;
|
|
136
|
+
|
|
137
|
+
export function isValidIdentifier(name: string) {
|
|
138
|
+
const char = name[0];
|
|
139
|
+
return (
|
|
140
|
+
char === '$'
|
|
141
|
+
|| char === '_'
|
|
142
|
+
|| (char >= 'A' && char <= 'Z')
|
|
143
|
+
|| (char >= 'a' && char <= 'z')
|
|
144
|
+
) && IDENTIFIER_CHECK.test(name);
|
|
145
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export const enum Symbols {
|
|
2
|
+
AsyncIterator,
|
|
3
|
+
HasInstance,
|
|
4
|
+
IsConcatSpreadable,
|
|
5
|
+
Iterator,
|
|
6
|
+
Match,
|
|
7
|
+
MatchAll,
|
|
8
|
+
Replace,
|
|
9
|
+
Search,
|
|
10
|
+
Species,
|
|
11
|
+
Split,
|
|
12
|
+
ToPrimitive,
|
|
13
|
+
ToStringTag,
|
|
14
|
+
Unscopables
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const SYMBOL_STRING: Record<Symbols, string> = {
|
|
18
|
+
[Symbols.AsyncIterator]: 'Symbol.asyncIterator',
|
|
19
|
+
[Symbols.HasInstance]: 'Symbol.hasInstance',
|
|
20
|
+
[Symbols.IsConcatSpreadable]: 'Symbol.isConcatSpreadable',
|
|
21
|
+
[Symbols.Iterator]: 'Symbol.iterator',
|
|
22
|
+
[Symbols.Match]: 'Symbol.match',
|
|
23
|
+
[Symbols.MatchAll]: 'Symbol.matchAll',
|
|
24
|
+
[Symbols.Replace]: 'Symbol.replace',
|
|
25
|
+
[Symbols.Search]: 'Symbol.search',
|
|
26
|
+
[Symbols.Species]: 'Symbol.species',
|
|
27
|
+
[Symbols.Split]: 'Symbol.split',
|
|
28
|
+
[Symbols.ToPrimitive]: 'Symbol.toPrimitive',
|
|
29
|
+
[Symbols.ToStringTag]: 'Symbol.toStringTag',
|
|
30
|
+
[Symbols.Unscopables]: 'Symbol.unscopables',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const INV_SYMBOL_REF = {
|
|
34
|
+
[Symbol.asyncIterator]: Symbols.AsyncIterator,
|
|
35
|
+
[Symbol.hasInstance]: Symbols.HasInstance,
|
|
36
|
+
[Symbol.isConcatSpreadable]: Symbols.IsConcatSpreadable,
|
|
37
|
+
[Symbol.iterator]: Symbols.Iterator,
|
|
38
|
+
[Symbol.match]: Symbols.Match,
|
|
39
|
+
[Symbol.matchAll]: Symbols.MatchAll,
|
|
40
|
+
[Symbol.replace]: Symbols.Replace,
|
|
41
|
+
[Symbol.search]: Symbols.Search,
|
|
42
|
+
[Symbol.species]: Symbols.Species,
|
|
43
|
+
[Symbol.split]: Symbols.Split,
|
|
44
|
+
[Symbol.toPrimitive]: Symbols.ToPrimitive,
|
|
45
|
+
[Symbol.toStringTag]: Symbols.ToStringTag,
|
|
46
|
+
[Symbol.unscopables]: Symbols.Unscopables,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type WellKnownSymbols = keyof typeof INV_SYMBOL_REF;
|
|
50
|
+
|
|
51
|
+
export const SYMBOL_REF: Record<Symbols, WellKnownSymbols> = {
|
|
52
|
+
[Symbols.AsyncIterator]: Symbol.asyncIterator,
|
|
53
|
+
[Symbols.HasInstance]: Symbol.hasInstance,
|
|
54
|
+
[Symbols.IsConcatSpreadable]: Symbol.isConcatSpreadable,
|
|
55
|
+
[Symbols.Iterator]: Symbol.iterator,
|
|
56
|
+
[Symbols.Match]: Symbol.match,
|
|
57
|
+
[Symbols.MatchAll]: Symbol.matchAll,
|
|
58
|
+
[Symbols.Replace]: Symbol.replace,
|
|
59
|
+
[Symbols.Search]: Symbol.search,
|
|
60
|
+
[Symbols.Species]: Symbol.species,
|
|
61
|
+
[Symbols.Split]: Symbol.split,
|
|
62
|
+
[Symbols.ToPrimitive]: Symbol.toPrimitive,
|
|
63
|
+
[Symbols.ToStringTag]: Symbol.toStringTag,
|
|
64
|
+
[Symbols.Unscopables]: Symbol.unscopables,
|
|
65
|
+
};
|
package/src/tree/sync.ts
CHANGED
|
@@ -2,28 +2,33 @@
|
|
|
2
2
|
import assert from '../assert';
|
|
3
3
|
import { Feature } from '../compat';
|
|
4
4
|
import { createRef, ParserContext } from '../context';
|
|
5
|
-
import quote from '../quote';
|
|
6
5
|
import { BigIntTypedArrayValue, ServerValue, TypedArrayValue } from '../types';
|
|
7
6
|
import {
|
|
8
7
|
createBigIntNode,
|
|
9
8
|
createBigIntTypedArrayNode,
|
|
10
9
|
createDateNode,
|
|
11
|
-
|
|
10
|
+
createNumberNode,
|
|
12
11
|
createReferenceNode,
|
|
13
12
|
createRegExpNode,
|
|
13
|
+
createStringNode,
|
|
14
14
|
createTypedArrayNode,
|
|
15
|
+
createWKSymbolNode,
|
|
15
16
|
FALSE_NODE,
|
|
17
|
+
INFINITY_NODE,
|
|
18
|
+
NAN_NODE,
|
|
19
|
+
NEG_INFINITY_NODE,
|
|
16
20
|
NEG_ZERO_NODE,
|
|
17
21
|
NULL_NODE,
|
|
18
22
|
TRUE_NODE,
|
|
19
23
|
UNDEFINED_NODE,
|
|
20
24
|
} from './primitives';
|
|
21
25
|
import {
|
|
22
|
-
|
|
26
|
+
getErrorConstructorName,
|
|
23
27
|
getErrorOptions,
|
|
24
28
|
getIterableOptions,
|
|
25
29
|
isIterable,
|
|
26
30
|
} from './shared';
|
|
31
|
+
import { INV_SYMBOL_REF } from './symbols';
|
|
27
32
|
import {
|
|
28
33
|
SerovalAggregateErrorNode,
|
|
29
34
|
SerovalArrayNode,
|
|
@@ -72,7 +77,7 @@ function generateArrayNode(
|
|
|
72
77
|
t: SerovalNodeType.Array,
|
|
73
78
|
i: id,
|
|
74
79
|
s: undefined,
|
|
75
|
-
l:
|
|
80
|
+
l: current.length,
|
|
76
81
|
c: undefined,
|
|
77
82
|
m: undefined,
|
|
78
83
|
d: undefined,
|
|
@@ -150,7 +155,7 @@ function generateSetNode(
|
|
|
150
155
|
t: SerovalNodeType.Set,
|
|
151
156
|
i: id,
|
|
152
157
|
s: undefined,
|
|
153
|
-
l:
|
|
158
|
+
l: len,
|
|
154
159
|
c: undefined,
|
|
155
160
|
m: undefined,
|
|
156
161
|
d: undefined,
|
|
@@ -200,20 +205,21 @@ function generateIterableNode(
|
|
|
200
205
|
id: number,
|
|
201
206
|
current: Iterable<ServerValue>,
|
|
202
207
|
): SerovalIterableNode {
|
|
203
|
-
assert(ctx.features & Feature.
|
|
208
|
+
assert(ctx.features & Feature.Symbol, 'Unsupported type "Iterable"');
|
|
204
209
|
const options = getIterableOptions(current);
|
|
210
|
+
const array = Array.from(current);
|
|
205
211
|
return {
|
|
206
212
|
t: SerovalNodeType.Iterable,
|
|
207
213
|
i: id,
|
|
208
214
|
s: undefined,
|
|
209
|
-
l:
|
|
215
|
+
l: array.length,
|
|
210
216
|
c: undefined,
|
|
211
217
|
m: undefined,
|
|
212
218
|
// Parse options first before the items
|
|
213
219
|
d: options
|
|
214
220
|
? generateProperties(ctx, options as Record<string, ServerValue>)
|
|
215
221
|
: undefined,
|
|
216
|
-
a: generateNodeList(ctx,
|
|
222
|
+
a: generateNodeList(ctx, array),
|
|
217
223
|
n: undefined,
|
|
218
224
|
};
|
|
219
225
|
}
|
|
@@ -253,12 +259,12 @@ function generateAggregateErrorNode(
|
|
|
253
259
|
t: SerovalNodeType.AggregateError,
|
|
254
260
|
i: id,
|
|
255
261
|
s: undefined,
|
|
256
|
-
l:
|
|
262
|
+
l: current.errors.length,
|
|
257
263
|
c: undefined,
|
|
258
264
|
m: current.message,
|
|
259
265
|
d: optionsNode,
|
|
260
|
-
a:
|
|
261
|
-
n:
|
|
266
|
+
a: generateNodeList(ctx, current.errors as ServerValue[]),
|
|
267
|
+
n: undefined,
|
|
262
268
|
};
|
|
263
269
|
}
|
|
264
270
|
|
|
@@ -276,7 +282,7 @@ function generateErrorNode(
|
|
|
276
282
|
i: id,
|
|
277
283
|
s: undefined,
|
|
278
284
|
l: undefined,
|
|
279
|
-
c:
|
|
285
|
+
c: getErrorConstructorName(current),
|
|
280
286
|
m: current.message,
|
|
281
287
|
d: optionsNode,
|
|
282
288
|
a: undefined,
|
|
@@ -294,18 +300,22 @@ function parse(
|
|
|
294
300
|
case 'undefined':
|
|
295
301
|
return UNDEFINED_NODE;
|
|
296
302
|
case 'string':
|
|
297
|
-
return
|
|
303
|
+
return createStringNode(current);
|
|
298
304
|
case 'number':
|
|
305
|
+
// eslint-disable-next-line no-self-compare
|
|
306
|
+
if (current !== current) {
|
|
307
|
+
return NAN_NODE;
|
|
308
|
+
}
|
|
299
309
|
if (Object.is(current, -0)) {
|
|
300
310
|
return NEG_ZERO_NODE;
|
|
301
311
|
}
|
|
302
312
|
if (Object.is(current, Infinity)) {
|
|
303
|
-
return
|
|
313
|
+
return INFINITY_NODE;
|
|
304
314
|
}
|
|
305
315
|
if (Object.is(current, -Infinity)) {
|
|
306
|
-
return
|
|
316
|
+
return NEG_INFINITY_NODE;
|
|
307
317
|
}
|
|
308
|
-
return
|
|
318
|
+
return createNumberNode(current);
|
|
309
319
|
case 'bigint':
|
|
310
320
|
return createBigIntNode(ctx, current);
|
|
311
321
|
case 'object': {
|
|
@@ -375,6 +385,10 @@ function parse(
|
|
|
375
385
|
}
|
|
376
386
|
throw new Error('Unsupported type');
|
|
377
387
|
}
|
|
388
|
+
case 'symbol':
|
|
389
|
+
assert(ctx.features & Feature.Symbol, 'Unsupported type "symbol"');
|
|
390
|
+
assert(current in INV_SYMBOL_REF, 'seroval only supports well-known symbols');
|
|
391
|
+
return createWKSymbolNode(current);
|
|
378
392
|
default:
|
|
379
393
|
throw new Error('Unsupported type');
|
|
380
394
|
}
|
package/src/tree/types.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Symbols } from './symbols';
|
|
2
2
|
|
|
3
3
|
export const enum SerovalNodeType {
|
|
4
|
-
|
|
4
|
+
Number,
|
|
5
|
+
String,
|
|
6
|
+
Boolean,
|
|
7
|
+
Null,
|
|
8
|
+
Undefined,
|
|
9
|
+
NegativeZero,
|
|
10
|
+
Infinity,
|
|
11
|
+
NegativeInfinity,
|
|
12
|
+
NaN,
|
|
5
13
|
BigInt,
|
|
6
14
|
Reference,
|
|
7
15
|
Date,
|
|
@@ -17,27 +25,28 @@ export const enum SerovalNodeType {
|
|
|
17
25
|
Iterable,
|
|
18
26
|
TypedArray,
|
|
19
27
|
BigIntTypedArray,
|
|
28
|
+
WKSymbol,
|
|
20
29
|
}
|
|
21
30
|
|
|
22
31
|
export interface SerovalBaseNode {
|
|
23
32
|
// Type of the node
|
|
24
33
|
t: SerovalNodeType;
|
|
25
|
-
// Serialized value
|
|
26
|
-
s: PrimitiveValue | undefined;
|
|
27
34
|
// Reference ID
|
|
28
35
|
i: number | undefined;
|
|
36
|
+
// Serialized value
|
|
37
|
+
s: any;
|
|
29
38
|
// Size/Byte offset
|
|
30
39
|
l: number | undefined;
|
|
31
|
-
// Constructor name
|
|
40
|
+
// Constructor name / RegExp source
|
|
32
41
|
c: string | undefined;
|
|
42
|
+
// message /flags
|
|
43
|
+
m: string | undefined;
|
|
33
44
|
// dictionary
|
|
34
45
|
d: SerovalDictionaryNode | undefined;
|
|
35
|
-
// message
|
|
36
|
-
m: string | undefined;
|
|
37
|
-
// next node
|
|
38
|
-
n: SerovalNode | undefined;
|
|
39
46
|
// array of nodes
|
|
40
47
|
a: SerovalNode[] | undefined;
|
|
48
|
+
// next node
|
|
49
|
+
n: SerovalNode | undefined;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
52
|
export interface SerovalObjectRecordNode {
|
|
@@ -56,10 +65,56 @@ export type SerovalDictionaryNode =
|
|
|
56
65
|
| SerovalObjectRecordNode
|
|
57
66
|
| SerovalMapRecordNode;
|
|
58
67
|
|
|
59
|
-
export interface
|
|
60
|
-
t: SerovalNodeType.
|
|
68
|
+
export interface SerovalNumberNode extends SerovalBaseNode {
|
|
69
|
+
t: SerovalNodeType.Number;
|
|
70
|
+
s: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface SerovalStringNode extends SerovalBaseNode {
|
|
74
|
+
t: SerovalNodeType.String;
|
|
75
|
+
s: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface SerovalBooleanNode extends SerovalBaseNode {
|
|
79
|
+
t: SerovalNodeType.Boolean;
|
|
80
|
+
s: boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface SerovalNullNode extends SerovalBaseNode {
|
|
84
|
+
t: SerovalNodeType.Null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface SerovalUndefinedNode extends SerovalBaseNode {
|
|
88
|
+
t: SerovalNodeType.Undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface SerovalNegativeZeroNode extends SerovalBaseNode {
|
|
92
|
+
t: SerovalNodeType.NegativeZero;
|
|
61
93
|
}
|
|
62
94
|
|
|
95
|
+
export interface SerovalInfinityNode extends SerovalBaseNode {
|
|
96
|
+
t: SerovalNodeType.Infinity;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface SerovalNegativeInfinityNode extends SerovalBaseNode {
|
|
100
|
+
t: SerovalNodeType.NegativeInfinity;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface SerovalNaNNode extends SerovalBaseNode {
|
|
104
|
+
t: SerovalNodeType.NaN;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export type SerovalPrimitiveNode =
|
|
108
|
+
| SerovalNumberNode
|
|
109
|
+
| SerovalStringNode
|
|
110
|
+
| SerovalBooleanNode
|
|
111
|
+
| SerovalNullNode
|
|
112
|
+
| SerovalUndefinedNode
|
|
113
|
+
| SerovalNegativeZeroNode
|
|
114
|
+
| SerovalNegativeInfinityNode
|
|
115
|
+
| SerovalInfinityNode
|
|
116
|
+
| SerovalNaNNode;
|
|
117
|
+
|
|
63
118
|
export interface SerovalReferenceNode extends SerovalBaseNode {
|
|
64
119
|
t: SerovalNodeType.Reference;
|
|
65
120
|
i: number;
|
|
@@ -79,13 +134,16 @@ export interface SerovalDateNode extends SerovalBaseNode {
|
|
|
79
134
|
export interface SerovalRegExpNode extends SerovalBaseNode {
|
|
80
135
|
t: SerovalNodeType.RegExp;
|
|
81
136
|
i: number;
|
|
82
|
-
|
|
137
|
+
// source
|
|
138
|
+
c: string;
|
|
139
|
+
// flags
|
|
140
|
+
m: string;
|
|
83
141
|
}
|
|
84
142
|
|
|
85
143
|
export interface SerovalTypedArrayNode extends SerovalBaseNode {
|
|
86
144
|
t: SerovalNodeType.TypedArray;
|
|
87
145
|
i: number;
|
|
88
|
-
s: string;
|
|
146
|
+
s: string[];
|
|
89
147
|
l: number;
|
|
90
148
|
c: string;
|
|
91
149
|
}
|
|
@@ -93,7 +151,7 @@ export interface SerovalTypedArrayNode extends SerovalBaseNode {
|
|
|
93
151
|
export interface SerovalBigIntTypedArrayNode extends SerovalBaseNode {
|
|
94
152
|
t: SerovalNodeType.BigIntTypedArray;
|
|
95
153
|
i: number;
|
|
96
|
-
s: string;
|
|
154
|
+
s: string[];
|
|
97
155
|
l: number;
|
|
98
156
|
c: string;
|
|
99
157
|
}
|
|
@@ -107,6 +165,7 @@ export type SerovalSemiPrimitiveNode =
|
|
|
107
165
|
|
|
108
166
|
export interface SerovalSetNode extends SerovalBaseNode {
|
|
109
167
|
t: SerovalNodeType.Set;
|
|
168
|
+
l: number;
|
|
110
169
|
a: SerovalNode[];
|
|
111
170
|
i: number;
|
|
112
171
|
}
|
|
@@ -119,6 +178,7 @@ export interface SerovalMapNode extends SerovalBaseNode {
|
|
|
119
178
|
|
|
120
179
|
export interface SerovalArrayNode extends SerovalBaseNode {
|
|
121
180
|
t: SerovalNodeType.Array;
|
|
181
|
+
l: number;
|
|
122
182
|
a: SerovalNode[];
|
|
123
183
|
i: number;
|
|
124
184
|
}
|
|
@@ -153,17 +213,24 @@ export interface SerovalAggregateErrorNode extends SerovalBaseNode {
|
|
|
153
213
|
t: SerovalNodeType.AggregateError;
|
|
154
214
|
m: string;
|
|
155
215
|
d: SerovalObjectRecordNode | undefined;
|
|
156
|
-
|
|
216
|
+
l: number;
|
|
217
|
+
a: SerovalNode[];
|
|
157
218
|
i: number;
|
|
158
219
|
}
|
|
159
220
|
|
|
160
221
|
export interface SerovalIterableNode extends SerovalBaseNode {
|
|
161
222
|
t: SerovalNodeType.Iterable;
|
|
162
223
|
d: SerovalObjectRecordNode | undefined;
|
|
224
|
+
l: number;
|
|
163
225
|
a: SerovalNode[];
|
|
164
226
|
i: number;
|
|
165
227
|
}
|
|
166
228
|
|
|
229
|
+
export interface SerovalWKSymbolNode extends SerovalBaseNode {
|
|
230
|
+
t: SerovalNodeType.WKSymbol;
|
|
231
|
+
s: Symbols;
|
|
232
|
+
}
|
|
233
|
+
|
|
167
234
|
export type SerovalNode =
|
|
168
235
|
| SerovalPrimitiveNode
|
|
169
236
|
| SerovalReferenceNode
|
|
@@ -176,4 +243,5 @@ export type SerovalNode =
|
|
|
176
243
|
| SerovalPromiseNode
|
|
177
244
|
| SerovalErrorNode
|
|
178
245
|
| SerovalAggregateErrorNode
|
|
179
|
-
| SerovalIterableNode
|
|
246
|
+
| SerovalIterableNode
|
|
247
|
+
| SerovalWKSymbolNode;
|
package/src/types.ts
CHANGED