seroval 1.4.0 → 1.4.2
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 +553 -350
- package/dist/cjs/development/index.cjs.map +3 -3
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +553 -350
- package/dist/esm/development/index.mjs.map +3 -3
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/core/base-primitives.d.ts +2 -2
- package/dist/types/core/base-primitives.d.ts.map +1 -1
- package/dist/types/core/compat.d.ts +2 -1
- package/dist/types/core/compat.d.ts.map +1 -1
- package/dist/types/core/constants.d.ts +2 -2
- package/dist/types/core/constants.d.ts.map +1 -1
- package/dist/types/core/constructors.d.ts +1 -1
- package/dist/types/core/constructors.d.ts.map +1 -1
- package/dist/types/core/context/async-parser.d.ts +5 -4
- package/dist/types/core/context/async-parser.d.ts.map +1 -1
- package/dist/types/core/context/deserializer.d.ts +7 -2
- package/dist/types/core/context/deserializer.d.ts.map +1 -1
- package/dist/types/core/context/parser.d.ts +3 -1
- package/dist/types/core/context/parser.d.ts.map +1 -1
- package/dist/types/core/context/serializer.d.ts.map +1 -1
- package/dist/types/core/context/sync-parser.d.ts +5 -5
- package/dist/types/core/context/sync-parser.d.ts.map +1 -1
- package/dist/types/core/cross/index.d.ts.map +1 -1
- package/dist/types/core/errors.d.ts +9 -0
- package/dist/types/core/errors.d.ts.map +1 -1
- package/dist/types/core/node.d.ts +1 -1
- package/dist/types/core/string.d.ts.map +1 -1
- package/dist/types/core/tree/index.d.ts +4 -1
- package/dist/types/core/tree/index.d.ts.map +1 -1
- package/dist/types/core/types.d.ts +6 -11
- package/dist/types/core/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/base-primitives.ts +17 -18
- package/src/core/compat.ts +3 -1
- package/src/core/constants.ts +18 -4
- package/src/core/constructors.ts +2 -1
- package/src/core/context/async-parser.ts +102 -50
- package/src/core/context/deserializer.ts +269 -105
- package/src/core/context/parser.ts +12 -10
- package/src/core/context/serializer.ts +31 -36
- package/src/core/context/sync-parser.ts +149 -75
- package/src/core/cross/index.ts +2 -0
- package/src/core/errors.ts +33 -0
- package/src/core/node.ts +2 -2
- package/src/core/string.ts +3 -1
- package/src/core/tree/index.ts +10 -1
- package/src/core/types.ts +10 -19
|
@@ -22,7 +22,11 @@ import {
|
|
|
22
22
|
} from '../base-primitives';
|
|
23
23
|
import { Feature } from '../compat';
|
|
24
24
|
import { NIL, SerovalNodeType } from '../constants';
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
SerovalDepthLimitError,
|
|
27
|
+
SerovalParserError,
|
|
28
|
+
SerovalUnsupportedTypeError,
|
|
29
|
+
} from '../errors';
|
|
26
30
|
import { FALSE_NODE, NULL_NODE, TRUE_NODE, UNDEFINED_NODE } from '../literals';
|
|
27
31
|
import { createSerovalNode } from '../node';
|
|
28
32
|
import { OpaqueReference } from '../opaque-reference';
|
|
@@ -103,15 +107,18 @@ export function createSyncParserContext(
|
|
|
103
107
|
return {
|
|
104
108
|
type: ParserMode.Sync,
|
|
105
109
|
base: createBaseParserContext(mode, options),
|
|
106
|
-
child:
|
|
110
|
+
child: NIL,
|
|
107
111
|
};
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
export class SyncParsePluginContext {
|
|
111
|
-
constructor(
|
|
115
|
+
constructor(
|
|
116
|
+
private _p: SyncParserContext,
|
|
117
|
+
private depth: number,
|
|
118
|
+
) {}
|
|
112
119
|
|
|
113
120
|
parse<T>(current: T): SerovalNode {
|
|
114
|
-
return parseSOS(this._p, current);
|
|
121
|
+
return parseSOS(this._p, this.depth, current);
|
|
115
122
|
}
|
|
116
123
|
}
|
|
117
124
|
|
|
@@ -124,18 +131,20 @@ export interface StreamParserContextOptions extends SyncParserContextOptions {
|
|
|
124
131
|
export interface StreamParserContext {
|
|
125
132
|
type: ParserMode.Stream;
|
|
126
133
|
base: BaseParserContext;
|
|
127
|
-
child: StreamParsePluginContext | undefined;
|
|
128
134
|
state: StreamParserState;
|
|
129
135
|
}
|
|
130
136
|
export class StreamParsePluginContext {
|
|
131
|
-
constructor(
|
|
137
|
+
constructor(
|
|
138
|
+
private _p: StreamParserContext,
|
|
139
|
+
private depth: number,
|
|
140
|
+
) {}
|
|
132
141
|
|
|
133
142
|
parse<T>(current: T): SerovalNode {
|
|
134
|
-
return parseSOS(this._p, current);
|
|
143
|
+
return parseSOS(this._p, this.depth, current);
|
|
135
144
|
}
|
|
136
145
|
|
|
137
146
|
parseWithError<T>(current: T): SerovalNode | undefined {
|
|
138
|
-
return parseWithError(this._p, current);
|
|
147
|
+
return parseWithError(this._p, this.depth, current);
|
|
139
148
|
}
|
|
140
149
|
|
|
141
150
|
isAlive(): boolean {
|
|
@@ -194,18 +203,23 @@ export function createStreamParserContext(
|
|
|
194
203
|
return {
|
|
195
204
|
type: ParserMode.Stream,
|
|
196
205
|
base: createBaseParserContext(SerovalMode.Cross, options),
|
|
197
|
-
child: undefined,
|
|
198
206
|
state: createStreamParserState(options),
|
|
199
207
|
};
|
|
200
208
|
}
|
|
201
209
|
|
|
202
210
|
type SOSParserContext = SyncParserContext | StreamParserContext;
|
|
203
211
|
|
|
204
|
-
function parseItems(
|
|
205
|
-
|
|
212
|
+
function parseItems(
|
|
213
|
+
ctx: SOSParserContext,
|
|
214
|
+
depth: number,
|
|
215
|
+
current: unknown[],
|
|
216
|
+
): (SerovalNode | 0)[] {
|
|
217
|
+
const nodes: (SerovalNode | 0)[] = [];
|
|
206
218
|
for (let i = 0, len = current.length; i < len; i++) {
|
|
207
219
|
if (i in current) {
|
|
208
|
-
nodes[i] = parseSOS(ctx, current[i]);
|
|
220
|
+
nodes[i] = parseSOS(ctx, depth, current[i]);
|
|
221
|
+
} else {
|
|
222
|
+
nodes[i] = 0;
|
|
209
223
|
}
|
|
210
224
|
}
|
|
211
225
|
return nodes;
|
|
@@ -213,14 +227,16 @@ function parseItems(ctx: SOSParserContext, current: unknown[]): SerovalNode[] {
|
|
|
213
227
|
|
|
214
228
|
function parseArray(
|
|
215
229
|
ctx: SOSParserContext,
|
|
230
|
+
depth: number,
|
|
216
231
|
id: number,
|
|
217
232
|
current: unknown[],
|
|
218
233
|
): SerovalArrayNode {
|
|
219
|
-
return createArrayNode(id, current, parseItems(ctx, current));
|
|
234
|
+
return createArrayNode(id, current, parseItems(ctx, depth, current));
|
|
220
235
|
}
|
|
221
236
|
|
|
222
237
|
function parseProperties(
|
|
223
238
|
ctx: SOSParserContext,
|
|
239
|
+
depth: number,
|
|
224
240
|
properties: Record<string | symbol, unknown>,
|
|
225
241
|
): SerovalObjectRecordNode {
|
|
226
242
|
const entries = Object.entries(properties);
|
|
@@ -228,7 +244,7 @@ function parseProperties(
|
|
|
228
244
|
const valueNodes: SerovalNode[] = [];
|
|
229
245
|
for (let i = 0, len = entries.length; i < len; i++) {
|
|
230
246
|
keyNodes.push(serializeString(entries[i][0]));
|
|
231
|
-
valueNodes.push(parseSOS(ctx, entries[i][1]));
|
|
247
|
+
valueNodes.push(parseSOS(ctx, depth, entries[i][1]));
|
|
232
248
|
}
|
|
233
249
|
// Check special properties, symbols in this case
|
|
234
250
|
if (SYM_ITERATOR in properties) {
|
|
@@ -238,6 +254,7 @@ function parseProperties(
|
|
|
238
254
|
parseIteratorFactory(ctx.base),
|
|
239
255
|
parseSOS(
|
|
240
256
|
ctx,
|
|
257
|
+
depth,
|
|
241
258
|
iteratorToSequence(properties as unknown as Iterable<unknown>),
|
|
242
259
|
),
|
|
243
260
|
),
|
|
@@ -250,6 +267,7 @@ function parseProperties(
|
|
|
250
267
|
parseAsyncIteratorFactory(ctx.base),
|
|
251
268
|
parseSOS(
|
|
252
269
|
ctx,
|
|
270
|
+
depth,
|
|
253
271
|
ctx.type === ParserMode.Sync
|
|
254
272
|
? createStream()
|
|
255
273
|
: createStreamFromAsyncIterable(
|
|
@@ -272,53 +290,71 @@ function parseProperties(
|
|
|
272
290
|
return {
|
|
273
291
|
k: keyNodes,
|
|
274
292
|
v: valueNodes,
|
|
275
|
-
s: keyNodes.length,
|
|
276
293
|
};
|
|
277
294
|
}
|
|
278
295
|
|
|
279
296
|
function parsePlainObject(
|
|
280
297
|
ctx: SOSParserContext,
|
|
298
|
+
depth: number,
|
|
281
299
|
id: number,
|
|
282
300
|
current: Record<string, unknown>,
|
|
283
301
|
empty: boolean,
|
|
284
302
|
): ObjectLikeNode {
|
|
285
|
-
return createObjectNode(
|
|
303
|
+
return createObjectNode(
|
|
304
|
+
id,
|
|
305
|
+
current,
|
|
306
|
+
empty,
|
|
307
|
+
parseProperties(ctx, depth, current),
|
|
308
|
+
);
|
|
286
309
|
}
|
|
287
310
|
|
|
288
311
|
function parseBoxed(
|
|
289
312
|
ctx: SOSParserContext,
|
|
313
|
+
depth: number,
|
|
290
314
|
id: number,
|
|
291
315
|
current: object,
|
|
292
316
|
): SerovalBoxedNode {
|
|
293
|
-
return createBoxedNode(id, parseSOS(ctx, current.valueOf()));
|
|
317
|
+
return createBoxedNode(id, parseSOS(ctx, depth, current.valueOf()));
|
|
294
318
|
}
|
|
295
319
|
|
|
296
320
|
function parseTypedArray(
|
|
297
321
|
ctx: SOSParserContext,
|
|
322
|
+
depth: number,
|
|
298
323
|
id: number,
|
|
299
324
|
current: TypedArrayValue,
|
|
300
325
|
): SerovalTypedArrayNode {
|
|
301
|
-
return createTypedArrayNode(
|
|
326
|
+
return createTypedArrayNode(
|
|
327
|
+
id,
|
|
328
|
+
current,
|
|
329
|
+
parseSOS(ctx, depth, current.buffer),
|
|
330
|
+
);
|
|
302
331
|
}
|
|
303
332
|
|
|
304
333
|
function parseBigIntTypedArray(
|
|
305
334
|
ctx: SOSParserContext,
|
|
335
|
+
depth: number,
|
|
306
336
|
id: number,
|
|
307
337
|
current: BigIntTypedArrayValue,
|
|
308
338
|
): SerovalBigIntTypedArrayNode {
|
|
309
|
-
return createBigIntTypedArrayNode(
|
|
339
|
+
return createBigIntTypedArrayNode(
|
|
340
|
+
id,
|
|
341
|
+
current,
|
|
342
|
+
parseSOS(ctx, depth, current.buffer),
|
|
343
|
+
);
|
|
310
344
|
}
|
|
311
345
|
|
|
312
346
|
function parseDataView(
|
|
313
347
|
ctx: SOSParserContext,
|
|
348
|
+
depth: number,
|
|
314
349
|
id: number,
|
|
315
350
|
current: DataView,
|
|
316
351
|
): SerovalDataViewNode {
|
|
317
|
-
return createDataViewNode(id, current, parseSOS(ctx, current.buffer));
|
|
352
|
+
return createDataViewNode(id, current, parseSOS(ctx, depth, current.buffer));
|
|
318
353
|
}
|
|
319
354
|
|
|
320
355
|
function parseError(
|
|
321
356
|
ctx: SOSParserContext,
|
|
357
|
+
depth: number,
|
|
322
358
|
id: number,
|
|
323
359
|
current: Error,
|
|
324
360
|
): SerovalErrorNode {
|
|
@@ -326,12 +362,13 @@ function parseError(
|
|
|
326
362
|
return createErrorNode(
|
|
327
363
|
id,
|
|
328
364
|
current,
|
|
329
|
-
options ? parseProperties(ctx, options) : NIL,
|
|
365
|
+
options ? parseProperties(ctx, depth, options) : NIL,
|
|
330
366
|
);
|
|
331
367
|
}
|
|
332
368
|
|
|
333
369
|
function parseAggregateError(
|
|
334
370
|
ctx: SOSParserContext,
|
|
371
|
+
depth: number,
|
|
335
372
|
id: number,
|
|
336
373
|
current: AggregateError,
|
|
337
374
|
): SerovalAggregateErrorNode {
|
|
@@ -339,38 +376,41 @@ function parseAggregateError(
|
|
|
339
376
|
return createAggregateErrorNode(
|
|
340
377
|
id,
|
|
341
378
|
current,
|
|
342
|
-
options ? parseProperties(ctx, options) : NIL,
|
|
379
|
+
options ? parseProperties(ctx, depth, options) : NIL,
|
|
343
380
|
);
|
|
344
381
|
}
|
|
345
382
|
|
|
346
383
|
function parseMap(
|
|
347
384
|
ctx: SOSParserContext,
|
|
385
|
+
depth: number,
|
|
348
386
|
id: number,
|
|
349
387
|
current: Map<unknown, unknown>,
|
|
350
388
|
): SerovalMapNode {
|
|
351
389
|
const keyNodes: SerovalNode[] = [];
|
|
352
390
|
const valueNodes: SerovalNode[] = [];
|
|
353
391
|
for (const [key, value] of current.entries()) {
|
|
354
|
-
keyNodes.push(parseSOS(ctx, key));
|
|
355
|
-
valueNodes.push(parseSOS(ctx, value));
|
|
392
|
+
keyNodes.push(parseSOS(ctx, depth, key));
|
|
393
|
+
valueNodes.push(parseSOS(ctx, depth, value));
|
|
356
394
|
}
|
|
357
|
-
return createMapNode(ctx.base, id, keyNodes, valueNodes
|
|
395
|
+
return createMapNode(ctx.base, id, keyNodes, valueNodes);
|
|
358
396
|
}
|
|
359
397
|
|
|
360
398
|
function parseSet(
|
|
361
399
|
ctx: SOSParserContext,
|
|
400
|
+
depth: number,
|
|
362
401
|
id: number,
|
|
363
402
|
current: Set<unknown>,
|
|
364
403
|
): SerovalSetNode {
|
|
365
404
|
const items: SerovalNode[] = [];
|
|
366
405
|
for (const item of current.keys()) {
|
|
367
|
-
items.push(parseSOS(ctx, item));
|
|
406
|
+
items.push(parseSOS(ctx, depth, item));
|
|
368
407
|
}
|
|
369
|
-
return createSetNode(id,
|
|
408
|
+
return createSetNode(id, items);
|
|
370
409
|
}
|
|
371
410
|
|
|
372
411
|
function parseStream(
|
|
373
412
|
ctx: SOSParserContext,
|
|
413
|
+
depth: number,
|
|
374
414
|
id: number,
|
|
375
415
|
current: Stream<unknown>,
|
|
376
416
|
): SerovalNode {
|
|
@@ -386,7 +426,7 @@ function parseStream(
|
|
|
386
426
|
current.on({
|
|
387
427
|
next: value => {
|
|
388
428
|
if (ctx.state.alive) {
|
|
389
|
-
const parsed = parseWithError(ctx, value);
|
|
429
|
+
const parsed = parseWithError(ctx, depth, value);
|
|
390
430
|
if (parsed) {
|
|
391
431
|
onParse(ctx, createStreamNextNode(id, parsed));
|
|
392
432
|
}
|
|
@@ -394,7 +434,7 @@ function parseStream(
|
|
|
394
434
|
},
|
|
395
435
|
throw: value => {
|
|
396
436
|
if (ctx.state.alive) {
|
|
397
|
-
const parsed = parseWithError(ctx, value);
|
|
437
|
+
const parsed = parseWithError(ctx, depth, value);
|
|
398
438
|
if (parsed) {
|
|
399
439
|
onParse(ctx, createStreamThrowNode(id, parsed));
|
|
400
440
|
}
|
|
@@ -403,7 +443,7 @@ function parseStream(
|
|
|
403
443
|
},
|
|
404
444
|
return: value => {
|
|
405
445
|
if (ctx.state.alive) {
|
|
406
|
-
const parsed = parseWithError(ctx, value);
|
|
446
|
+
const parsed = parseWithError(ctx, depth, value);
|
|
407
447
|
if (parsed) {
|
|
408
448
|
onParse(ctx, createStreamReturnNode(id, parsed));
|
|
409
449
|
}
|
|
@@ -417,10 +457,11 @@ function parseStream(
|
|
|
417
457
|
function handlePromiseSuccess(
|
|
418
458
|
this: StreamParserContext,
|
|
419
459
|
id: number,
|
|
460
|
+
depth: number,
|
|
420
461
|
data: unknown,
|
|
421
462
|
): void {
|
|
422
463
|
if (this.state.alive) {
|
|
423
|
-
const parsed = parseWithError(this, data);
|
|
464
|
+
const parsed = parseWithError(this, depth, data);
|
|
424
465
|
if (parsed) {
|
|
425
466
|
onParse(
|
|
426
467
|
this,
|
|
@@ -432,7 +473,6 @@ function handlePromiseSuccess(
|
|
|
432
473
|
NIL,
|
|
433
474
|
NIL,
|
|
434
475
|
NIL,
|
|
435
|
-
NIL,
|
|
436
476
|
[
|
|
437
477
|
parseSpecialReference(this.base, SpecialReference.PromiseSuccess),
|
|
438
478
|
parsed,
|
|
@@ -440,6 +480,7 @@ function handlePromiseSuccess(
|
|
|
440
480
|
NIL,
|
|
441
481
|
NIL,
|
|
442
482
|
NIL,
|
|
483
|
+
NIL,
|
|
443
484
|
),
|
|
444
485
|
);
|
|
445
486
|
}
|
|
@@ -450,10 +491,11 @@ function handlePromiseSuccess(
|
|
|
450
491
|
function handlePromiseFailure(
|
|
451
492
|
this: StreamParserContext,
|
|
452
493
|
id: number,
|
|
494
|
+
depth: number,
|
|
453
495
|
data: unknown,
|
|
454
496
|
): void {
|
|
455
497
|
if (this.state.alive) {
|
|
456
|
-
const parsed = parseWithError(this, data);
|
|
498
|
+
const parsed = parseWithError(this, depth, data);
|
|
457
499
|
if (parsed) {
|
|
458
500
|
onParse(
|
|
459
501
|
this,
|
|
@@ -465,7 +507,6 @@ function handlePromiseFailure(
|
|
|
465
507
|
NIL,
|
|
466
508
|
NIL,
|
|
467
509
|
NIL,
|
|
468
|
-
NIL,
|
|
469
510
|
[
|
|
470
511
|
parseSpecialReference(this.base, SpecialReference.PromiseFailure),
|
|
471
512
|
parsed,
|
|
@@ -473,6 +514,7 @@ function handlePromiseFailure(
|
|
|
473
514
|
NIL,
|
|
474
515
|
NIL,
|
|
475
516
|
NIL,
|
|
517
|
+
NIL,
|
|
476
518
|
),
|
|
477
519
|
);
|
|
478
520
|
}
|
|
@@ -482,6 +524,7 @@ function handlePromiseFailure(
|
|
|
482
524
|
|
|
483
525
|
function parsePromise(
|
|
484
526
|
ctx: SOSParserContext,
|
|
527
|
+
depth: number,
|
|
485
528
|
id: number,
|
|
486
529
|
current: Promise<unknown>,
|
|
487
530
|
): SerovalPromiseConstructorNode {
|
|
@@ -490,8 +533,8 @@ function parsePromise(
|
|
|
490
533
|
if (ctx.type === ParserMode.Stream) {
|
|
491
534
|
pushPendingState(ctx);
|
|
492
535
|
current.then(
|
|
493
|
-
handlePromiseSuccess.bind(ctx, resolver),
|
|
494
|
-
handlePromiseFailure.bind(ctx, resolver),
|
|
536
|
+
handlePromiseSuccess.bind(ctx, resolver, depth),
|
|
537
|
+
handlePromiseFailure.bind(ctx, resolver, depth),
|
|
495
538
|
);
|
|
496
539
|
}
|
|
497
540
|
return createPromiseConstructorNode(ctx.base, id, resolver);
|
|
@@ -499,6 +542,7 @@ function parsePromise(
|
|
|
499
542
|
|
|
500
543
|
function parsePluginSync(
|
|
501
544
|
ctx: SyncParserContext,
|
|
545
|
+
depth: number,
|
|
502
546
|
id: number,
|
|
503
547
|
current: unknown,
|
|
504
548
|
currentPlugins: Plugin<any, any>[],
|
|
@@ -506,23 +550,21 @@ function parsePluginSync(
|
|
|
506
550
|
for (let i = 0, len = currentPlugins.length; i < len; i++) {
|
|
507
551
|
const plugin = currentPlugins[i];
|
|
508
552
|
if (plugin.parse.sync && plugin.test(current)) {
|
|
509
|
-
if (ctx.child == null) {
|
|
510
|
-
ctx.child = new SyncParsePluginContext(ctx);
|
|
511
|
-
}
|
|
512
553
|
return createPluginNode(
|
|
513
554
|
id,
|
|
514
555
|
plugin.tag,
|
|
515
|
-
plugin.parse.sync(current, ctx
|
|
556
|
+
plugin.parse.sync(current, new SyncParsePluginContext(ctx, depth), {
|
|
516
557
|
id,
|
|
517
558
|
}),
|
|
518
559
|
);
|
|
519
560
|
}
|
|
520
561
|
}
|
|
521
|
-
return
|
|
562
|
+
return NIL;
|
|
522
563
|
}
|
|
523
564
|
|
|
524
565
|
function parsePluginStream(
|
|
525
566
|
ctx: StreamParserContext,
|
|
567
|
+
depth: number,
|
|
526
568
|
id: number,
|
|
527
569
|
current: unknown,
|
|
528
570
|
currentPlugins: Plugin<any, any>[],
|
|
@@ -530,37 +572,36 @@ function parsePluginStream(
|
|
|
530
572
|
for (let i = 0, len = currentPlugins.length; i < len; i++) {
|
|
531
573
|
const plugin = currentPlugins[i];
|
|
532
574
|
if (plugin.parse.stream && plugin.test(current)) {
|
|
533
|
-
if (ctx.child == null) {
|
|
534
|
-
ctx.child = new StreamParsePluginContext(ctx);
|
|
535
|
-
}
|
|
536
575
|
return createPluginNode(
|
|
537
576
|
id,
|
|
538
577
|
plugin.tag,
|
|
539
|
-
plugin.parse.stream(current, ctx
|
|
578
|
+
plugin.parse.stream(current, new StreamParsePluginContext(ctx, depth), {
|
|
540
579
|
id,
|
|
541
580
|
}),
|
|
542
581
|
);
|
|
543
582
|
}
|
|
544
583
|
}
|
|
545
|
-
return
|
|
584
|
+
return NIL;
|
|
546
585
|
}
|
|
547
586
|
|
|
548
587
|
function parsePlugin(
|
|
549
588
|
ctx: SOSParserContext,
|
|
589
|
+
depth: number,
|
|
550
590
|
id: number,
|
|
551
591
|
current: unknown,
|
|
552
592
|
): SerovalPluginNode | undefined {
|
|
553
593
|
const currentPlugins = ctx.base.plugins;
|
|
554
594
|
if (currentPlugins) {
|
|
555
595
|
return ctx.type === ParserMode.Sync
|
|
556
|
-
? parsePluginSync(ctx, id, current, currentPlugins)
|
|
557
|
-
: parsePluginStream(ctx, id, current, currentPlugins);
|
|
596
|
+
? parsePluginSync(ctx, depth, id, current, currentPlugins)
|
|
597
|
+
: parsePluginStream(ctx, depth, id, current, currentPlugins);
|
|
558
598
|
}
|
|
559
|
-
return
|
|
599
|
+
return NIL;
|
|
560
600
|
}
|
|
561
601
|
|
|
562
602
|
function parseObjectPhase2(
|
|
563
603
|
ctx: SOSParserContext,
|
|
604
|
+
depth: number,
|
|
564
605
|
id: number,
|
|
565
606
|
current: object,
|
|
566
607
|
currentClass: unknown,
|
|
@@ -569,21 +610,21 @@ function parseObjectPhase2(
|
|
|
569
610
|
case Object:
|
|
570
611
|
return parsePlainObject(
|
|
571
612
|
ctx,
|
|
613
|
+
depth,
|
|
572
614
|
id,
|
|
573
615
|
current as Record<string, unknown>,
|
|
574
616
|
false,
|
|
575
617
|
);
|
|
576
|
-
case
|
|
618
|
+
case NIL:
|
|
577
619
|
return parsePlainObject(
|
|
578
620
|
ctx,
|
|
621
|
+
depth,
|
|
579
622
|
id,
|
|
580
623
|
current as Record<string, unknown>,
|
|
581
624
|
true,
|
|
582
625
|
);
|
|
583
626
|
case Date:
|
|
584
627
|
return createDateNode(id, current as unknown as Date);
|
|
585
|
-
case RegExp:
|
|
586
|
-
return createRegExpNode(id, current as unknown as RegExp);
|
|
587
628
|
case Error:
|
|
588
629
|
case EvalError:
|
|
589
630
|
case RangeError:
|
|
@@ -591,12 +632,12 @@ function parseObjectPhase2(
|
|
|
591
632
|
case SyntaxError:
|
|
592
633
|
case TypeError:
|
|
593
634
|
case URIError:
|
|
594
|
-
return parseError(ctx, id, current as unknown as Error);
|
|
635
|
+
return parseError(ctx, depth, id, current as unknown as Error);
|
|
595
636
|
case Number:
|
|
596
637
|
case Boolean:
|
|
597
638
|
case String:
|
|
598
639
|
case BigInt:
|
|
599
|
-
return parseBoxed(ctx, id, current);
|
|
640
|
+
return parseBoxed(ctx, depth, id, current);
|
|
600
641
|
case ArrayBuffer:
|
|
601
642
|
return createArrayBufferNode(
|
|
602
643
|
ctx.base,
|
|
@@ -612,21 +653,34 @@ function parseObjectPhase2(
|
|
|
612
653
|
case Uint8ClampedArray:
|
|
613
654
|
case Float32Array:
|
|
614
655
|
case Float64Array:
|
|
615
|
-
return parseTypedArray(
|
|
656
|
+
return parseTypedArray(
|
|
657
|
+
ctx,
|
|
658
|
+
depth,
|
|
659
|
+
id,
|
|
660
|
+
current as unknown as TypedArrayValue,
|
|
661
|
+
);
|
|
616
662
|
case DataView:
|
|
617
|
-
return parseDataView(ctx, id, current as unknown as DataView);
|
|
663
|
+
return parseDataView(ctx, depth, id, current as unknown as DataView);
|
|
618
664
|
case Map:
|
|
619
|
-
return parseMap(
|
|
665
|
+
return parseMap(
|
|
666
|
+
ctx,
|
|
667
|
+
depth,
|
|
668
|
+
id,
|
|
669
|
+
current as unknown as Map<unknown, unknown>,
|
|
670
|
+
);
|
|
620
671
|
case Set:
|
|
621
|
-
return parseSet(ctx, id, current as unknown as Set<unknown>);
|
|
672
|
+
return parseSet(ctx, depth, id, current as unknown as Set<unknown>);
|
|
622
673
|
default:
|
|
623
674
|
break;
|
|
624
675
|
}
|
|
625
676
|
// Promises
|
|
626
677
|
if (currentClass === Promise || current instanceof Promise) {
|
|
627
|
-
return parsePromise(ctx, id, current as unknown as Promise<unknown>);
|
|
678
|
+
return parsePromise(ctx, depth, id, current as unknown as Promise<unknown>);
|
|
628
679
|
}
|
|
629
680
|
const currentFeatures = ctx.base.features;
|
|
681
|
+
if (currentFeatures & Feature.RegExp && currentClass === RegExp) {
|
|
682
|
+
return createRegExpNode(id, current as unknown as RegExp);
|
|
683
|
+
}
|
|
630
684
|
// BigInt Typed Arrays
|
|
631
685
|
if (currentFeatures & Feature.BigIntTypedArray) {
|
|
632
686
|
switch (currentClass) {
|
|
@@ -634,6 +688,7 @@ function parseObjectPhase2(
|
|
|
634
688
|
case BigUint64Array:
|
|
635
689
|
return parseBigIntTypedArray(
|
|
636
690
|
ctx,
|
|
691
|
+
depth,
|
|
637
692
|
id,
|
|
638
693
|
current as unknown as BigIntTypedArrayValue,
|
|
639
694
|
);
|
|
@@ -646,59 +701,77 @@ function parseObjectPhase2(
|
|
|
646
701
|
typeof AggregateError !== 'undefined' &&
|
|
647
702
|
(currentClass === AggregateError || current instanceof AggregateError)
|
|
648
703
|
) {
|
|
649
|
-
return parseAggregateError(
|
|
704
|
+
return parseAggregateError(
|
|
705
|
+
ctx,
|
|
706
|
+
depth,
|
|
707
|
+
id,
|
|
708
|
+
current as unknown as AggregateError,
|
|
709
|
+
);
|
|
650
710
|
}
|
|
651
711
|
// Slow path. We only need to handle Errors and Iterators
|
|
652
712
|
// since they have very broad implementations.
|
|
653
713
|
if (current instanceof Error) {
|
|
654
|
-
return parseError(ctx, id, current);
|
|
714
|
+
return parseError(ctx, depth, id, current);
|
|
655
715
|
}
|
|
656
716
|
// Generator functions don't have a global constructor
|
|
657
717
|
// despite existing
|
|
658
718
|
if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) {
|
|
659
|
-
return parsePlainObject(ctx, id, current, !!currentClass);
|
|
719
|
+
return parsePlainObject(ctx, depth, id, current, !!currentClass);
|
|
660
720
|
}
|
|
661
721
|
throw new SerovalUnsupportedTypeError(current);
|
|
662
722
|
}
|
|
663
723
|
|
|
664
724
|
function parseObject(
|
|
665
725
|
ctx: SOSParserContext,
|
|
726
|
+
depth: number,
|
|
666
727
|
id: number,
|
|
667
728
|
current: object,
|
|
668
729
|
): SerovalNode {
|
|
669
730
|
if (Array.isArray(current)) {
|
|
670
|
-
return parseArray(ctx, id, current);
|
|
731
|
+
return parseArray(ctx, depth, id, current);
|
|
671
732
|
}
|
|
672
733
|
if (isStream(current)) {
|
|
673
|
-
return parseStream(ctx, id, current);
|
|
734
|
+
return parseStream(ctx, depth, id, current);
|
|
674
735
|
}
|
|
675
736
|
const currentClass = current.constructor;
|
|
676
737
|
if (currentClass === OpaqueReference) {
|
|
677
738
|
return parseSOS(
|
|
678
739
|
ctx,
|
|
740
|
+
depth,
|
|
679
741
|
(current as OpaqueReference<unknown, unknown>).replacement,
|
|
680
742
|
);
|
|
681
743
|
}
|
|
682
|
-
const parsed = parsePlugin(ctx, id, current);
|
|
744
|
+
const parsed = parsePlugin(ctx, depth, id, current);
|
|
683
745
|
if (parsed) {
|
|
684
746
|
return parsed;
|
|
685
747
|
}
|
|
686
|
-
return parseObjectPhase2(ctx, id, current, currentClass);
|
|
748
|
+
return parseObjectPhase2(ctx, depth, id, current, currentClass);
|
|
687
749
|
}
|
|
688
750
|
|
|
689
|
-
function parseFunction(
|
|
751
|
+
function parseFunction(
|
|
752
|
+
ctx: SOSParserContext,
|
|
753
|
+
depth: number,
|
|
754
|
+
current: unknown,
|
|
755
|
+
): SerovalNode {
|
|
690
756
|
const ref = getReferenceNode(ctx.base, current);
|
|
691
757
|
if (ref.type !== ParserNodeType.Fresh) {
|
|
692
758
|
return ref.value;
|
|
693
759
|
}
|
|
694
|
-
const plugin = parsePlugin(ctx, ref.value, current);
|
|
760
|
+
const plugin = parsePlugin(ctx, depth, ref.value, current);
|
|
695
761
|
if (plugin) {
|
|
696
762
|
return plugin;
|
|
697
763
|
}
|
|
698
764
|
throw new SerovalUnsupportedTypeError(current);
|
|
699
765
|
}
|
|
700
766
|
|
|
701
|
-
export function parseSOS<T>(
|
|
767
|
+
export function parseSOS<T>(
|
|
768
|
+
ctx: SOSParserContext,
|
|
769
|
+
depth: number,
|
|
770
|
+
current: T,
|
|
771
|
+
): SerovalNode {
|
|
772
|
+
if (depth >= ctx.base.depthLimit) {
|
|
773
|
+
throw new SerovalDepthLimitError(ctx.base.depthLimit);
|
|
774
|
+
}
|
|
702
775
|
switch (typeof current) {
|
|
703
776
|
case 'boolean':
|
|
704
777
|
return current ? TRUE_NODE : FALSE_NODE;
|
|
@@ -714,7 +787,7 @@ export function parseSOS<T>(ctx: SOSParserContext, current: T): SerovalNode {
|
|
|
714
787
|
if (current) {
|
|
715
788
|
const ref = getReferenceNode(ctx.base, current);
|
|
716
789
|
return ref.type === ParserNodeType.Fresh
|
|
717
|
-
? parseObject(ctx, ref.value, current as object)
|
|
790
|
+
? parseObject(ctx, depth + 1, ref.value, current as object)
|
|
718
791
|
: ref.value;
|
|
719
792
|
}
|
|
720
793
|
return NULL_NODE;
|
|
@@ -722,7 +795,7 @@ export function parseSOS<T>(ctx: SOSParserContext, current: T): SerovalNode {
|
|
|
722
795
|
case 'symbol':
|
|
723
796
|
return parseWellKnownSymbol(ctx.base, current);
|
|
724
797
|
case 'function': {
|
|
725
|
-
return parseFunction(ctx, current);
|
|
798
|
+
return parseFunction(ctx, depth, current);
|
|
726
799
|
}
|
|
727
800
|
default:
|
|
728
801
|
throw new SerovalUnsupportedTypeError(current);
|
|
@@ -731,7 +804,7 @@ export function parseSOS<T>(ctx: SOSParserContext, current: T): SerovalNode {
|
|
|
731
804
|
|
|
732
805
|
export function parseTop<T>(ctx: SyncParserContext, current: T): SerovalNode {
|
|
733
806
|
try {
|
|
734
|
-
return parseSOS(ctx, current);
|
|
807
|
+
return parseSOS(ctx, 0, current);
|
|
735
808
|
} catch (error) {
|
|
736
809
|
throw error instanceof SerovalParserError
|
|
737
810
|
? error
|
|
@@ -787,12 +860,13 @@ function popPendingState(ctx: StreamParserContext): void {
|
|
|
787
860
|
}
|
|
788
861
|
}
|
|
789
862
|
|
|
790
|
-
|
|
863
|
+
function parseWithError<T>(
|
|
791
864
|
ctx: StreamParserContext,
|
|
865
|
+
depth: number,
|
|
792
866
|
current: T,
|
|
793
867
|
): SerovalNode | undefined {
|
|
794
868
|
try {
|
|
795
|
-
return parseSOS(ctx, current);
|
|
869
|
+
return parseSOS(ctx, depth, current);
|
|
796
870
|
} catch (err) {
|
|
797
871
|
onError(ctx, err);
|
|
798
872
|
return NIL;
|
|
@@ -803,7 +877,7 @@ export function startStreamParse<T>(
|
|
|
803
877
|
ctx: StreamParserContext,
|
|
804
878
|
current: T,
|
|
805
879
|
): void {
|
|
806
|
-
const parsed = parseWithError(ctx, current);
|
|
880
|
+
const parsed = parseWithError(ctx, 0, current);
|
|
807
881
|
if (parsed) {
|
|
808
882
|
onParseInternal(ctx, parsed, true);
|
|
809
883
|
ctx.state.initial = false;
|
package/src/core/cross/index.ts
CHANGED
|
@@ -181,6 +181,8 @@ export function fromCrossJSON<T>(
|
|
|
181
181
|
const ctx = createCrossDeserializerContext({
|
|
182
182
|
plugins,
|
|
183
183
|
refs: options.refs,
|
|
184
|
+
features: options.features,
|
|
185
|
+
disabledFeatures: options.disabledFeatures,
|
|
184
186
|
});
|
|
185
187
|
return deserializeTop(ctx, source) as T;
|
|
186
188
|
}
|