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
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { ALL_ENABLED, Feature } from '../compat';
|
|
1
2
|
import {
|
|
2
3
|
CONSTANT_VAL,
|
|
3
4
|
ERROR_CONSTRUCTOR,
|
|
5
|
+
NIL,
|
|
4
6
|
SerovalNodeType,
|
|
5
7
|
SerovalObjectFlags,
|
|
6
8
|
SYMBOL_REF,
|
|
@@ -11,7 +13,9 @@ import {
|
|
|
11
13
|
type PromiseConstructorResolver,
|
|
12
14
|
} from '../constructors';
|
|
13
15
|
import {
|
|
16
|
+
SerovalDepthLimitError,
|
|
14
17
|
SerovalDeserializationError,
|
|
18
|
+
SerovalMalformedNodeError,
|
|
15
19
|
SerovalMissingInstanceError,
|
|
16
20
|
SerovalMissingPluginError,
|
|
17
21
|
SerovalUnsupportedNodeError,
|
|
@@ -20,8 +24,14 @@ import type { PluginAccessOptions } from '../plugin';
|
|
|
20
24
|
import { SerovalMode } from '../plugin';
|
|
21
25
|
import { getReference } from '../reference';
|
|
22
26
|
import type { Stream } from '../stream';
|
|
23
|
-
import { createStream, streamToAsyncIterable } from '../stream';
|
|
27
|
+
import { createStream, isStream, streamToAsyncIterable } from '../stream';
|
|
24
28
|
import { deserializeString } from '../string';
|
|
29
|
+
import {
|
|
30
|
+
SYM_ASYNC_ITERATOR,
|
|
31
|
+
SYM_IS_CONCAT_SPREADABLE,
|
|
32
|
+
SYM_ITERATOR,
|
|
33
|
+
SYM_TO_STRING_TAG,
|
|
34
|
+
} from '../symbols';
|
|
25
35
|
import type {
|
|
26
36
|
SerovalAggregateErrorNode,
|
|
27
37
|
SerovalArrayBufferNode,
|
|
@@ -39,7 +49,6 @@ import type {
|
|
|
39
49
|
SerovalNode,
|
|
40
50
|
SerovalNullConstructorNode,
|
|
41
51
|
SerovalObjectNode,
|
|
42
|
-
SerovalObjectRecordKey,
|
|
43
52
|
SerovalObjectRecordNode,
|
|
44
53
|
SerovalPluginNode,
|
|
45
54
|
SerovalPromiseConstructorNode,
|
|
@@ -63,6 +72,10 @@ import type {
|
|
|
63
72
|
} from '../utils/typed-array';
|
|
64
73
|
import { getTypedArrayConstructor } from '../utils/typed-array';
|
|
65
74
|
|
|
75
|
+
const MAX_BASE64_LENGTH = 1_000_000; // ~0.75MB decoded
|
|
76
|
+
const MAX_BIGINT_LENGTH = 10_000;
|
|
77
|
+
const MAX_REGEXP_SOURCE_LENGTH = 20_000;
|
|
78
|
+
|
|
66
79
|
function applyObjectFlag(obj: unknown, flag: SerovalObjectFlags): unknown {
|
|
67
80
|
switch (flag) {
|
|
68
81
|
case SerovalObjectFlags.Frozen:
|
|
@@ -81,6 +94,9 @@ type AssignableNode = SerovalAggregateErrorNode | SerovalErrorNode;
|
|
|
81
94
|
|
|
82
95
|
export interface BaseDeserializerContextOptions extends PluginAccessOptions {
|
|
83
96
|
refs?: Map<number, unknown>;
|
|
97
|
+
features?: number;
|
|
98
|
+
disabledFeatures?: number;
|
|
99
|
+
depthLimit?: number;
|
|
84
100
|
}
|
|
85
101
|
|
|
86
102
|
export interface BaseDeserializerContext extends PluginAccessOptions {
|
|
@@ -89,8 +105,12 @@ export interface BaseDeserializerContext extends PluginAccessOptions {
|
|
|
89
105
|
* Mapping ids to values
|
|
90
106
|
*/
|
|
91
107
|
refs: Map<number, unknown>;
|
|
108
|
+
features: number;
|
|
109
|
+
depthLimit: number;
|
|
92
110
|
}
|
|
93
111
|
|
|
112
|
+
const DEFAULT_DEPTH_LIMIT = 1000;
|
|
113
|
+
|
|
94
114
|
export function createBaseDeserializerContext(
|
|
95
115
|
mode: SerovalMode,
|
|
96
116
|
options: BaseDeserializerContextOptions,
|
|
@@ -99,6 +119,8 @@ export function createBaseDeserializerContext(
|
|
|
99
119
|
mode,
|
|
100
120
|
plugins: options.plugins,
|
|
101
121
|
refs: options.refs || new Map(),
|
|
122
|
+
features: options.features ?? ALL_ENABLED ^ (options.disabledFeatures || 0),
|
|
123
|
+
depthLimit: options.depthLimit || DEFAULT_DEPTH_LIMIT,
|
|
102
124
|
};
|
|
103
125
|
}
|
|
104
126
|
|
|
@@ -124,7 +146,7 @@ export function createVanillaDeserializerContext(
|
|
|
124
146
|
return {
|
|
125
147
|
mode: SerovalMode.Vanilla,
|
|
126
148
|
base: createBaseDeserializerContext(SerovalMode.Vanilla, options),
|
|
127
|
-
child:
|
|
149
|
+
child: NIL,
|
|
128
150
|
state: {
|
|
129
151
|
marked: new Set(options.markedRefs),
|
|
130
152
|
},
|
|
@@ -145,7 +167,7 @@ export function createCrossDeserializerContext(
|
|
|
145
167
|
return {
|
|
146
168
|
mode: SerovalMode.Cross,
|
|
147
169
|
base: createBaseDeserializerContext(SerovalMode.Cross, options),
|
|
148
|
-
child:
|
|
170
|
+
child: NIL,
|
|
149
171
|
};
|
|
150
172
|
}
|
|
151
173
|
|
|
@@ -154,10 +176,25 @@ type DeserializerContext =
|
|
|
154
176
|
| CrossDeserializerContext;
|
|
155
177
|
|
|
156
178
|
export class DeserializePluginContext {
|
|
157
|
-
constructor(
|
|
179
|
+
constructor(
|
|
180
|
+
private _p: DeserializerContext,
|
|
181
|
+
private depth: number,
|
|
182
|
+
) {}
|
|
158
183
|
|
|
159
184
|
deserialize<T>(node: SerovalNode): T {
|
|
160
|
-
return deserialize(this._p, node) as T;
|
|
185
|
+
return deserialize(this._p, this.depth, node) as T;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function guardIndexedValue(ctx: BaseDeserializerContext, id: number): void {
|
|
190
|
+
if (id < 0 || !Number.isFinite(id) || !Number.isInteger(id)) {
|
|
191
|
+
throw new SerovalMalformedNodeError({
|
|
192
|
+
t: SerovalNodeType.IndexedValue,
|
|
193
|
+
i: id,
|
|
194
|
+
} as SerovalNode);
|
|
195
|
+
}
|
|
196
|
+
if (ctx.refs.has(id)) {
|
|
197
|
+
throw new Error('Conflicted ref id: ' + id);
|
|
161
198
|
}
|
|
162
199
|
}
|
|
163
200
|
|
|
@@ -166,6 +203,7 @@ function assignIndexedValueVanilla<T>(
|
|
|
166
203
|
id: number,
|
|
167
204
|
value: T,
|
|
168
205
|
): T {
|
|
206
|
+
guardIndexedValue(ctx.base, id);
|
|
169
207
|
if (ctx.state.marked.has(id)) {
|
|
170
208
|
ctx.base.refs.set(id, value);
|
|
171
209
|
}
|
|
@@ -177,9 +215,8 @@ function assignIndexedValueCross<T>(
|
|
|
177
215
|
id: number,
|
|
178
216
|
value: T,
|
|
179
217
|
): T {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
218
|
+
guardIndexedValue(ctx.base, id);
|
|
219
|
+
ctx.base.refs.set(id, value);
|
|
183
220
|
return value;
|
|
184
221
|
}
|
|
185
222
|
|
|
@@ -193,6 +230,16 @@ function assignIndexedValue<T>(
|
|
|
193
230
|
: assignIndexedValueCross(ctx, id, value);
|
|
194
231
|
}
|
|
195
232
|
|
|
233
|
+
function deserializeKnownValue<
|
|
234
|
+
T extends Record<string, unknown>,
|
|
235
|
+
K extends keyof T,
|
|
236
|
+
>(node: SerovalNode, record: T, key: K): T[K] {
|
|
237
|
+
if (Object.hasOwn(record, key)) {
|
|
238
|
+
return record[key];
|
|
239
|
+
}
|
|
240
|
+
throw new SerovalMalformedNodeError(node);
|
|
241
|
+
}
|
|
242
|
+
|
|
196
243
|
function deserializeReference(
|
|
197
244
|
ctx: DeserializerContext,
|
|
198
245
|
node: SerovalReferenceNode,
|
|
@@ -206,41 +253,108 @@ function deserializeReference(
|
|
|
206
253
|
|
|
207
254
|
function deserializeArray(
|
|
208
255
|
ctx: DeserializerContext,
|
|
256
|
+
depth: number,
|
|
209
257
|
node: SerovalArrayNode,
|
|
210
258
|
): unknown[] {
|
|
211
|
-
const
|
|
259
|
+
const items = node.a;
|
|
260
|
+
const len = items.length;
|
|
212
261
|
const result: unknown[] = assignIndexedValue(
|
|
213
262
|
ctx,
|
|
214
263
|
node.i,
|
|
215
264
|
new Array<unknown>(len),
|
|
216
265
|
);
|
|
217
|
-
let item: SerovalNode |
|
|
218
|
-
|
|
219
|
-
item = node.a[i];
|
|
266
|
+
for (let i = 0, item: SerovalNode | 0; i < len; i++) {
|
|
267
|
+
item = items[i];
|
|
220
268
|
if (item) {
|
|
221
|
-
result[i] = deserialize(ctx, item);
|
|
269
|
+
result[i] = deserialize(ctx, depth, item);
|
|
222
270
|
}
|
|
223
271
|
}
|
|
224
272
|
applyObjectFlag(result, node.o);
|
|
225
273
|
return result;
|
|
226
274
|
}
|
|
227
275
|
|
|
276
|
+
function isValidKey(key: string): boolean {
|
|
277
|
+
switch (key) {
|
|
278
|
+
case 'constructor':
|
|
279
|
+
case '__proto__':
|
|
280
|
+
case 'prototype':
|
|
281
|
+
case '__defineGetter__':
|
|
282
|
+
case '__defineSetter__':
|
|
283
|
+
case '__lookupGetter__':
|
|
284
|
+
case '__lookupSetter__':
|
|
285
|
+
// case 'then':
|
|
286
|
+
return false;
|
|
287
|
+
default:
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function isValidSymbol(symbol: symbol): boolean {
|
|
293
|
+
switch (symbol) {
|
|
294
|
+
case SYM_ASYNC_ITERATOR:
|
|
295
|
+
case SYM_IS_CONCAT_SPREADABLE:
|
|
296
|
+
case SYM_TO_STRING_TAG:
|
|
297
|
+
case SYM_ITERATOR:
|
|
298
|
+
return true;
|
|
299
|
+
default:
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function assignStringProperty(
|
|
305
|
+
object: Record<string | symbol, unknown>,
|
|
306
|
+
key: string,
|
|
307
|
+
value: unknown,
|
|
308
|
+
): void {
|
|
309
|
+
if (isValidKey(key)) {
|
|
310
|
+
object[key] = value;
|
|
311
|
+
} else {
|
|
312
|
+
Object.defineProperty(object, key, {
|
|
313
|
+
value,
|
|
314
|
+
configurable: true,
|
|
315
|
+
enumerable: true,
|
|
316
|
+
writable: true,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function assignProperty(
|
|
322
|
+
ctx: DeserializerContext,
|
|
323
|
+
depth: number,
|
|
324
|
+
object: Record<string | symbol, unknown>,
|
|
325
|
+
key: string | SerovalNode,
|
|
326
|
+
value: SerovalNode,
|
|
327
|
+
): void {
|
|
328
|
+
if (typeof key === 'string') {
|
|
329
|
+
assignStringProperty(object, key, deserialize(ctx, depth, value));
|
|
330
|
+
} else {
|
|
331
|
+
const actual = deserialize(ctx, depth, key);
|
|
332
|
+
switch (typeof actual) {
|
|
333
|
+
case 'string':
|
|
334
|
+
assignStringProperty(object, actual, deserialize(ctx, depth, value));
|
|
335
|
+
break;
|
|
336
|
+
case 'symbol':
|
|
337
|
+
if (isValidSymbol(actual)) {
|
|
338
|
+
object[actual] = deserialize(ctx, depth, value);
|
|
339
|
+
}
|
|
340
|
+
break;
|
|
341
|
+
default:
|
|
342
|
+
throw new SerovalMalformedNodeError(key);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
228
347
|
function deserializeProperties(
|
|
229
348
|
ctx: DeserializerContext,
|
|
349
|
+
depth: number,
|
|
230
350
|
node: SerovalObjectRecordNode,
|
|
231
351
|
result: Record<string | symbol, unknown>,
|
|
232
352
|
): Record<string | symbol, unknown> {
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
key = keys[i];
|
|
239
|
-
if (typeof key === 'string') {
|
|
240
|
-
result[deserializeString(key)] = deserialize(ctx, vals[i]);
|
|
241
|
-
} else {
|
|
242
|
-
result[deserialize(ctx, key) as symbol] = deserialize(ctx, vals[i]);
|
|
243
|
-
}
|
|
353
|
+
const keys = node.k;
|
|
354
|
+
const len = keys.length;
|
|
355
|
+
if (len > 0) {
|
|
356
|
+
for (let i = 0, vals = node.v, len = keys.length; i < len; i++) {
|
|
357
|
+
assignProperty(ctx, depth, result, keys[i], vals[i]);
|
|
244
358
|
}
|
|
245
359
|
}
|
|
246
360
|
return result;
|
|
@@ -248,6 +362,7 @@ function deserializeProperties(
|
|
|
248
362
|
|
|
249
363
|
function deserializeObject(
|
|
250
364
|
ctx: DeserializerContext,
|
|
365
|
+
depth: number,
|
|
251
366
|
node: SerovalObjectNode | SerovalNullConstructorNode,
|
|
252
367
|
): Record<string, unknown> {
|
|
253
368
|
const result = assignIndexedValue(
|
|
@@ -258,7 +373,7 @@ function deserializeObject(
|
|
|
258
373
|
unknown
|
|
259
374
|
>,
|
|
260
375
|
);
|
|
261
|
-
deserializeProperties(ctx, node.p, result);
|
|
376
|
+
deserializeProperties(ctx, depth, node.p, result);
|
|
262
377
|
applyObjectFlag(result, node.o);
|
|
263
378
|
return result;
|
|
264
379
|
}
|
|
@@ -274,34 +389,43 @@ function deserializeRegExp(
|
|
|
274
389
|
ctx: DeserializerContext,
|
|
275
390
|
node: SerovalRegExpNode,
|
|
276
391
|
): RegExp {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
392
|
+
if (ctx.base.features & Feature.RegExp) {
|
|
393
|
+
const source = deserializeString(node.c);
|
|
394
|
+
if (source.length > MAX_REGEXP_SOURCE_LENGTH) {
|
|
395
|
+
throw new SerovalMalformedNodeError(node);
|
|
396
|
+
}
|
|
397
|
+
return assignIndexedValue(ctx, node.i, new RegExp(source, node.m));
|
|
398
|
+
}
|
|
399
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
282
400
|
}
|
|
283
401
|
|
|
284
402
|
function deserializeSet(
|
|
285
403
|
ctx: DeserializerContext,
|
|
404
|
+
depth: number,
|
|
286
405
|
node: SerovalSetNode,
|
|
287
406
|
): Set<unknown> {
|
|
288
407
|
const result = assignIndexedValue(ctx, node.i, new Set<unknown>());
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
result.add(deserialize(ctx, items[i]));
|
|
408
|
+
for (let i = 0, items = node.a, len = items.length; i < len; i++) {
|
|
409
|
+
result.add(deserialize(ctx, depth, items[i]));
|
|
292
410
|
}
|
|
293
411
|
return result;
|
|
294
412
|
}
|
|
295
413
|
|
|
296
414
|
function deserializeMap(
|
|
297
415
|
ctx: DeserializerContext,
|
|
416
|
+
depth: number,
|
|
298
417
|
node: SerovalMapNode,
|
|
299
418
|
): Map<unknown, unknown> {
|
|
300
419
|
const result = assignIndexedValue(ctx, node.i, new Map<unknown, unknown>());
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
420
|
+
for (
|
|
421
|
+
let i = 0, keys = node.e.k, vals = node.e.v, len = keys.length;
|
|
422
|
+
i < len;
|
|
423
|
+
i++
|
|
424
|
+
) {
|
|
425
|
+
result.set(
|
|
426
|
+
deserialize(ctx, depth, keys[i]),
|
|
427
|
+
deserialize(ctx, depth, vals[i]),
|
|
428
|
+
);
|
|
305
429
|
}
|
|
306
430
|
return result;
|
|
307
431
|
}
|
|
@@ -310,55 +434,70 @@ function deserializeArrayBuffer(
|
|
|
310
434
|
ctx: DeserializerContext,
|
|
311
435
|
node: SerovalArrayBufferNode,
|
|
312
436
|
): ArrayBuffer {
|
|
437
|
+
if (node.s.length > MAX_BASE64_LENGTH) {
|
|
438
|
+
throw new SerovalMalformedNodeError(node);
|
|
439
|
+
}
|
|
313
440
|
const result = assignIndexedValue(
|
|
314
441
|
ctx,
|
|
315
442
|
node.i,
|
|
316
|
-
ARRAY_BUFFER_CONSTRUCTOR(
|
|
443
|
+
ARRAY_BUFFER_CONSTRUCTOR(deserializeString(node.s)),
|
|
317
444
|
);
|
|
318
445
|
return result;
|
|
319
446
|
}
|
|
320
447
|
|
|
321
448
|
function deserializeTypedArray(
|
|
322
449
|
ctx: DeserializerContext,
|
|
450
|
+
depth: number,
|
|
323
451
|
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
|
|
324
452
|
): TypedArrayValue | BigIntTypedArrayValue {
|
|
325
453
|
const construct = getTypedArrayConstructor(node.c) as Int8ArrayConstructor;
|
|
326
|
-
const source = deserialize(ctx, node.f) as ArrayBuffer;
|
|
454
|
+
const source = deserialize(ctx, depth, node.f) as ArrayBuffer;
|
|
455
|
+
const offset = node.b ?? 0;
|
|
456
|
+
if (offset < 0 || offset > source.byteLength) {
|
|
457
|
+
throw new SerovalMalformedNodeError(node);
|
|
458
|
+
}
|
|
327
459
|
const result = assignIndexedValue(
|
|
328
460
|
ctx,
|
|
329
461
|
node.i,
|
|
330
|
-
new construct(source,
|
|
462
|
+
new construct(source, offset, node.l),
|
|
331
463
|
);
|
|
332
464
|
return result;
|
|
333
465
|
}
|
|
334
466
|
|
|
335
467
|
function deserializeDataView(
|
|
336
468
|
ctx: DeserializerContext,
|
|
469
|
+
depth: number,
|
|
337
470
|
node: SerovalDataViewNode,
|
|
338
471
|
): DataView {
|
|
339
|
-
const source = deserialize(ctx, node.f) as ArrayBuffer;
|
|
472
|
+
const source = deserialize(ctx, depth, node.f) as ArrayBuffer;
|
|
473
|
+
const offset = node.b ?? 0;
|
|
474
|
+
if (offset < 0 || offset > source.byteLength) {
|
|
475
|
+
throw new SerovalMalformedNodeError(node);
|
|
476
|
+
}
|
|
340
477
|
const result = assignIndexedValue(
|
|
341
478
|
ctx,
|
|
342
479
|
node.i,
|
|
343
|
-
new DataView(source,
|
|
480
|
+
new DataView(source, offset, node.l),
|
|
344
481
|
);
|
|
345
482
|
return result;
|
|
346
483
|
}
|
|
347
484
|
|
|
348
485
|
function deserializeDictionary<T extends AssignableValue>(
|
|
349
486
|
ctx: DeserializerContext,
|
|
487
|
+
depth: number,
|
|
350
488
|
node: AssignableNode,
|
|
351
489
|
result: T,
|
|
352
490
|
): T {
|
|
353
491
|
if (node.p) {
|
|
354
|
-
const fields = deserializeProperties(ctx, node.p, {});
|
|
355
|
-
Object.
|
|
492
|
+
const fields = deserializeProperties(ctx, depth, node.p, {});
|
|
493
|
+
Object.defineProperties(result, Object.getOwnPropertyDescriptors(fields));
|
|
356
494
|
}
|
|
357
495
|
return result;
|
|
358
496
|
}
|
|
359
497
|
|
|
360
498
|
function deserializeAggregateError(
|
|
361
499
|
ctx: DeserializerContext,
|
|
500
|
+
depth: number,
|
|
362
501
|
node: SerovalAggregateErrorNode,
|
|
363
502
|
): AggregateError {
|
|
364
503
|
// Serialize the required arguments
|
|
@@ -370,29 +509,31 @@ function deserializeAggregateError(
|
|
|
370
509
|
// `AggregateError` might've been extended
|
|
371
510
|
// either through class or custom properties
|
|
372
511
|
// Make sure to assign extra properties
|
|
373
|
-
return deserializeDictionary(ctx, node, result);
|
|
512
|
+
return deserializeDictionary(ctx, depth, node, result);
|
|
374
513
|
}
|
|
375
514
|
|
|
376
515
|
function deserializeError(
|
|
377
516
|
ctx: DeserializerContext,
|
|
517
|
+
depth: number,
|
|
378
518
|
node: SerovalErrorNode,
|
|
379
519
|
): Error {
|
|
380
|
-
const construct = ERROR_CONSTRUCTOR
|
|
520
|
+
const construct = deserializeKnownValue(node, ERROR_CONSTRUCTOR, node.s);
|
|
381
521
|
const result = assignIndexedValue(
|
|
382
522
|
ctx,
|
|
383
523
|
node.i,
|
|
384
524
|
new construct(deserializeString(node.m)),
|
|
385
525
|
);
|
|
386
|
-
return deserializeDictionary(ctx, node, result);
|
|
526
|
+
return deserializeDictionary(ctx, depth, node, result);
|
|
387
527
|
}
|
|
388
528
|
|
|
389
529
|
function deserializePromise(
|
|
390
530
|
ctx: DeserializerContext,
|
|
531
|
+
depth: number,
|
|
391
532
|
node: SerovalPromiseNode,
|
|
392
533
|
): Promise<unknown> {
|
|
393
534
|
const deferred = PROMISE_CONSTRUCTOR();
|
|
394
535
|
const result = assignIndexedValue(ctx, node.i, deferred.p);
|
|
395
|
-
const deserialized = deserialize(ctx, node.f);
|
|
536
|
+
const deserialized = deserialize(ctx, depth, node.f);
|
|
396
537
|
if (node.s) {
|
|
397
538
|
deferred.s(deserialized);
|
|
398
539
|
} else {
|
|
@@ -403,14 +544,20 @@ function deserializePromise(
|
|
|
403
544
|
|
|
404
545
|
function deserializeBoxed(
|
|
405
546
|
ctx: DeserializerContext,
|
|
547
|
+
depth: number,
|
|
406
548
|
node: SerovalBoxedNode,
|
|
407
549
|
): unknown {
|
|
408
|
-
|
|
409
|
-
|
|
550
|
+
return assignIndexedValue(
|
|
551
|
+
ctx,
|
|
552
|
+
node.i,
|
|
553
|
+
// biome-ignore lint/style/useConsistentBuiltinInstantiation: intended
|
|
554
|
+
Object(deserialize(ctx, depth, node.f)),
|
|
555
|
+
);
|
|
410
556
|
}
|
|
411
557
|
|
|
412
558
|
function deserializePlugin(
|
|
413
559
|
ctx: DeserializerContext,
|
|
560
|
+
depth: number,
|
|
414
561
|
node: SerovalPluginNode,
|
|
415
562
|
): unknown {
|
|
416
563
|
const currentPlugins = ctx.base.plugins;
|
|
@@ -419,13 +566,10 @@ function deserializePlugin(
|
|
|
419
566
|
for (let i = 0, len = currentPlugins.length; i < len; i++) {
|
|
420
567
|
const plugin = currentPlugins[i];
|
|
421
568
|
if (plugin.tag === tag) {
|
|
422
|
-
if (ctx.child == null) {
|
|
423
|
-
ctx.child = new DeserializePluginContext(ctx);
|
|
424
|
-
}
|
|
425
569
|
return assignIndexedValue(
|
|
426
570
|
ctx,
|
|
427
571
|
node.i,
|
|
428
|
-
plugin.deserialize(node.s, ctx
|
|
572
|
+
plugin.deserialize(node.s, new DeserializePluginContext(ctx, depth), {
|
|
429
573
|
id: node.i,
|
|
430
574
|
}),
|
|
431
575
|
);
|
|
@@ -448,59 +592,65 @@ function deserializePromiseConstructor(
|
|
|
448
592
|
|
|
449
593
|
function deserializePromiseResolve(
|
|
450
594
|
ctx: DeserializerContext,
|
|
595
|
+
depth: number,
|
|
451
596
|
node: SerovalPromiseResolveNode,
|
|
452
597
|
): unknown {
|
|
453
598
|
const deferred = ctx.base.refs.get(node.i) as
|
|
454
599
|
| PromiseConstructorResolver
|
|
455
600
|
| undefined;
|
|
456
601
|
if (deferred) {
|
|
457
|
-
deferred.s(deserialize(ctx, node.a[1]));
|
|
458
|
-
return
|
|
602
|
+
deferred.s(deserialize(ctx, depth, node.a[1]));
|
|
603
|
+
return NIL;
|
|
459
604
|
}
|
|
460
605
|
throw new SerovalMissingInstanceError('Promise');
|
|
461
606
|
}
|
|
462
607
|
|
|
463
608
|
function deserializePromiseReject(
|
|
464
609
|
ctx: DeserializerContext,
|
|
610
|
+
depth: number,
|
|
465
611
|
node: SerovalPromiseRejectNode,
|
|
466
612
|
): unknown {
|
|
467
613
|
const deferred = ctx.base.refs.get(node.i) as
|
|
468
614
|
| PromiseConstructorResolver
|
|
469
615
|
| undefined;
|
|
470
616
|
if (deferred) {
|
|
471
|
-
deferred.f(deserialize(ctx, node.a[1]));
|
|
472
|
-
return
|
|
617
|
+
deferred.f(deserialize(ctx, depth, node.a[1]));
|
|
618
|
+
return NIL;
|
|
473
619
|
}
|
|
474
620
|
throw new SerovalMissingInstanceError('Promise');
|
|
475
621
|
}
|
|
476
622
|
|
|
477
623
|
function deserializeIteratorFactoryInstance(
|
|
478
624
|
ctx: DeserializerContext,
|
|
625
|
+
depth: number,
|
|
479
626
|
node: SerovalIteratorFactoryInstanceNode,
|
|
480
627
|
): unknown {
|
|
481
|
-
deserialize(ctx, node.a[0]);
|
|
482
|
-
const source = deserialize(ctx, node.a[1]);
|
|
628
|
+
deserialize(ctx, depth, node.a[0]);
|
|
629
|
+
const source = deserialize(ctx, depth, node.a[1]);
|
|
483
630
|
return sequenceToIterator(source as Sequence);
|
|
484
631
|
}
|
|
485
632
|
|
|
486
633
|
function deserializeAsyncIteratorFactoryInstance(
|
|
487
634
|
ctx: DeserializerContext,
|
|
635
|
+
depth: number,
|
|
488
636
|
node: SerovalAsyncIteratorFactoryInstanceNode,
|
|
489
637
|
): unknown {
|
|
490
|
-
deserialize(ctx, node.a[0]);
|
|
491
|
-
const source = deserialize(ctx, node.a[1]);
|
|
638
|
+
deserialize(ctx, depth, node.a[0]);
|
|
639
|
+
const source = deserialize(ctx, depth, node.a[1]);
|
|
492
640
|
return streamToAsyncIterable(source as Stream<any>);
|
|
493
641
|
}
|
|
494
642
|
|
|
495
643
|
function deserializeStreamConstructor(
|
|
496
644
|
ctx: DeserializerContext,
|
|
645
|
+
depth: number,
|
|
497
646
|
node: SerovalStreamConstructorNode,
|
|
498
647
|
): unknown {
|
|
499
648
|
const result = assignIndexedValue(ctx, node.i, createStream());
|
|
500
|
-
const
|
|
649
|
+
const items = node.a;
|
|
650
|
+
const len = items.length;
|
|
501
651
|
if (len) {
|
|
502
652
|
for (let i = 0; i < len; i++) {
|
|
503
|
-
deserialize(ctx,
|
|
653
|
+
deserialize(ctx, depth, items[i]);
|
|
504
654
|
}
|
|
505
655
|
}
|
|
506
656
|
return result;
|
|
@@ -508,126 +658,140 @@ function deserializeStreamConstructor(
|
|
|
508
658
|
|
|
509
659
|
function deserializeStreamNext(
|
|
510
660
|
ctx: DeserializerContext,
|
|
661
|
+
depth: number,
|
|
511
662
|
node: SerovalStreamNextNode,
|
|
512
663
|
): unknown {
|
|
513
664
|
const deferred = ctx.base.refs.get(node.i) as Stream<unknown> | undefined;
|
|
514
|
-
if (deferred) {
|
|
515
|
-
deferred.next(deserialize(ctx, node.f));
|
|
516
|
-
return
|
|
665
|
+
if (deferred && isStream(deferred)) {
|
|
666
|
+
deferred.next(deserialize(ctx, depth, node.f));
|
|
667
|
+
return NIL;
|
|
517
668
|
}
|
|
518
669
|
throw new SerovalMissingInstanceError('Stream');
|
|
519
670
|
}
|
|
520
671
|
|
|
521
672
|
function deserializeStreamThrow(
|
|
522
673
|
ctx: DeserializerContext,
|
|
674
|
+
depth: number,
|
|
523
675
|
node: SerovalStreamThrowNode,
|
|
524
676
|
): unknown {
|
|
525
677
|
const deferred = ctx.base.refs.get(node.i) as Stream<unknown> | undefined;
|
|
526
|
-
if (deferred) {
|
|
527
|
-
deferred.throw(deserialize(ctx, node.f));
|
|
528
|
-
return
|
|
678
|
+
if (deferred && isStream(deferred)) {
|
|
679
|
+
deferred.throw(deserialize(ctx, depth, node.f));
|
|
680
|
+
return NIL;
|
|
529
681
|
}
|
|
530
682
|
throw new SerovalMissingInstanceError('Stream');
|
|
531
683
|
}
|
|
532
684
|
|
|
533
685
|
function deserializeStreamReturn(
|
|
534
686
|
ctx: DeserializerContext,
|
|
687
|
+
depth: number,
|
|
535
688
|
node: SerovalStreamReturnNode,
|
|
536
689
|
): unknown {
|
|
537
690
|
const deferred = ctx.base.refs.get(node.i) as Stream<unknown> | undefined;
|
|
538
|
-
if (deferred) {
|
|
539
|
-
deferred.return(deserialize(ctx, node.f));
|
|
540
|
-
return
|
|
691
|
+
if (deferred && isStream(deferred)) {
|
|
692
|
+
deferred.return(deserialize(ctx, depth, node.f));
|
|
693
|
+
return NIL;
|
|
541
694
|
}
|
|
542
695
|
throw new SerovalMissingInstanceError('Stream');
|
|
543
696
|
}
|
|
544
697
|
|
|
545
698
|
function deserializeIteratorFactory(
|
|
546
699
|
ctx: DeserializerContext,
|
|
700
|
+
depth: number,
|
|
547
701
|
node: SerovalIteratorFactoryNode,
|
|
548
702
|
): unknown {
|
|
549
|
-
deserialize(ctx, node.f);
|
|
550
|
-
return
|
|
703
|
+
deserialize(ctx, depth, node.f);
|
|
704
|
+
return NIL;
|
|
551
705
|
}
|
|
552
706
|
|
|
553
707
|
function deserializeAsyncIteratorFactory(
|
|
554
708
|
ctx: DeserializerContext,
|
|
709
|
+
depth: number,
|
|
555
710
|
node: SerovalAsyncIteratorFactoryNode,
|
|
556
711
|
): unknown {
|
|
557
|
-
deserialize(ctx, node.a[1]);
|
|
558
|
-
return
|
|
712
|
+
deserialize(ctx, depth, node.a[1]);
|
|
713
|
+
return NIL;
|
|
559
714
|
}
|
|
560
|
-
|
|
715
|
+
|
|
716
|
+
function deserialize(
|
|
561
717
|
ctx: DeserializerContext,
|
|
718
|
+
depth: number,
|
|
562
719
|
node: SerovalNode,
|
|
563
720
|
): unknown {
|
|
721
|
+
if (depth > ctx.base.depthLimit) {
|
|
722
|
+
throw new SerovalDepthLimitError(ctx.base.depthLimit);
|
|
723
|
+
}
|
|
724
|
+
depth += 1;
|
|
564
725
|
switch (node.t) {
|
|
565
726
|
case SerovalNodeType.Constant:
|
|
566
|
-
return CONSTANT_VAL
|
|
727
|
+
return deserializeKnownValue(node, CONSTANT_VAL, node.s);
|
|
567
728
|
case SerovalNodeType.Number:
|
|
568
|
-
return node.s;
|
|
729
|
+
return Number(node.s);
|
|
569
730
|
case SerovalNodeType.String:
|
|
570
|
-
return deserializeString(node.s);
|
|
731
|
+
return deserializeString(String(node.s));
|
|
571
732
|
case SerovalNodeType.BigInt:
|
|
733
|
+
if (String(node.s).length > MAX_BIGINT_LENGTH) {
|
|
734
|
+
throw new SerovalMalformedNodeError(node);
|
|
735
|
+
}
|
|
572
736
|
return BigInt(node.s);
|
|
573
737
|
case SerovalNodeType.IndexedValue:
|
|
574
738
|
return ctx.base.refs.get(node.i);
|
|
575
739
|
case SerovalNodeType.Reference:
|
|
576
740
|
return deserializeReference(ctx, node);
|
|
577
741
|
case SerovalNodeType.Array:
|
|
578
|
-
return deserializeArray(ctx, node);
|
|
742
|
+
return deserializeArray(ctx, depth, node);
|
|
579
743
|
case SerovalNodeType.Object:
|
|
580
744
|
case SerovalNodeType.NullConstructor:
|
|
581
|
-
return deserializeObject(ctx, node);
|
|
745
|
+
return deserializeObject(ctx, depth, node);
|
|
582
746
|
case SerovalNodeType.Date:
|
|
583
747
|
return deserializeDate(ctx, node);
|
|
584
748
|
case SerovalNodeType.RegExp:
|
|
585
749
|
return deserializeRegExp(ctx, node);
|
|
586
750
|
case SerovalNodeType.Set:
|
|
587
|
-
return deserializeSet(ctx, node);
|
|
751
|
+
return deserializeSet(ctx, depth, node);
|
|
588
752
|
case SerovalNodeType.Map:
|
|
589
|
-
return deserializeMap(ctx, node);
|
|
753
|
+
return deserializeMap(ctx, depth, node);
|
|
590
754
|
case SerovalNodeType.ArrayBuffer:
|
|
591
755
|
return deserializeArrayBuffer(ctx, node);
|
|
592
756
|
case SerovalNodeType.BigIntTypedArray:
|
|
593
757
|
case SerovalNodeType.TypedArray:
|
|
594
|
-
return deserializeTypedArray(ctx, node);
|
|
758
|
+
return deserializeTypedArray(ctx, depth, node);
|
|
595
759
|
case SerovalNodeType.DataView:
|
|
596
|
-
return deserializeDataView(ctx, node);
|
|
760
|
+
return deserializeDataView(ctx, depth, node);
|
|
597
761
|
case SerovalNodeType.AggregateError:
|
|
598
|
-
return deserializeAggregateError(ctx, node);
|
|
762
|
+
return deserializeAggregateError(ctx, depth, node);
|
|
599
763
|
case SerovalNodeType.Error:
|
|
600
|
-
return deserializeError(ctx, node);
|
|
764
|
+
return deserializeError(ctx, depth, node);
|
|
601
765
|
case SerovalNodeType.Promise:
|
|
602
|
-
return deserializePromise(ctx, node);
|
|
766
|
+
return deserializePromise(ctx, depth, node);
|
|
603
767
|
case SerovalNodeType.WKSymbol:
|
|
604
|
-
return SYMBOL_REF
|
|
768
|
+
return deserializeKnownValue(node, SYMBOL_REF, node.s);
|
|
605
769
|
case SerovalNodeType.Boxed:
|
|
606
|
-
return deserializeBoxed(ctx, node);
|
|
770
|
+
return deserializeBoxed(ctx, depth, node);
|
|
607
771
|
case SerovalNodeType.Plugin:
|
|
608
|
-
return deserializePlugin(ctx, node);
|
|
772
|
+
return deserializePlugin(ctx, depth, node);
|
|
609
773
|
case SerovalNodeType.PromiseConstructor:
|
|
610
774
|
return deserializePromiseConstructor(ctx, node);
|
|
611
775
|
case SerovalNodeType.PromiseSuccess:
|
|
612
|
-
return deserializePromiseResolve(ctx, node);
|
|
776
|
+
return deserializePromiseResolve(ctx, depth, node);
|
|
613
777
|
case SerovalNodeType.PromiseFailure:
|
|
614
|
-
return deserializePromiseReject(ctx, node);
|
|
778
|
+
return deserializePromiseReject(ctx, depth, node);
|
|
615
779
|
case SerovalNodeType.IteratorFactoryInstance:
|
|
616
|
-
return deserializeIteratorFactoryInstance(ctx, node);
|
|
780
|
+
return deserializeIteratorFactoryInstance(ctx, depth, node);
|
|
617
781
|
case SerovalNodeType.AsyncIteratorFactoryInstance:
|
|
618
|
-
return deserializeAsyncIteratorFactoryInstance(ctx, node);
|
|
782
|
+
return deserializeAsyncIteratorFactoryInstance(ctx, depth, node);
|
|
619
783
|
case SerovalNodeType.StreamConstructor:
|
|
620
|
-
return deserializeStreamConstructor(ctx, node);
|
|
784
|
+
return deserializeStreamConstructor(ctx, depth, node);
|
|
621
785
|
case SerovalNodeType.StreamNext:
|
|
622
|
-
return deserializeStreamNext(ctx, node);
|
|
786
|
+
return deserializeStreamNext(ctx, depth, node);
|
|
623
787
|
case SerovalNodeType.StreamThrow:
|
|
624
|
-
return deserializeStreamThrow(ctx, node);
|
|
788
|
+
return deserializeStreamThrow(ctx, depth, node);
|
|
625
789
|
case SerovalNodeType.StreamReturn:
|
|
626
|
-
return deserializeStreamReturn(ctx, node);
|
|
790
|
+
return deserializeStreamReturn(ctx, depth, node);
|
|
627
791
|
case SerovalNodeType.IteratorFactory:
|
|
628
|
-
return deserializeIteratorFactory(ctx, node);
|
|
792
|
+
return deserializeIteratorFactory(ctx, depth, node);
|
|
629
793
|
case SerovalNodeType.AsyncIteratorFactory:
|
|
630
|
-
return deserializeAsyncIteratorFactory(ctx, node);
|
|
794
|
+
return deserializeAsyncIteratorFactory(ctx, depth, node);
|
|
631
795
|
// case SerovalNodeType.SpecialReference:
|
|
632
796
|
default:
|
|
633
797
|
throw new SerovalUnsupportedNodeError(node);
|
|
@@ -639,7 +803,7 @@ export function deserializeTop(
|
|
|
639
803
|
node: SerovalNode,
|
|
640
804
|
): unknown {
|
|
641
805
|
try {
|
|
642
|
-
return deserialize(ctx, node);
|
|
806
|
+
return deserialize(ctx, 0, node);
|
|
643
807
|
} catch (error) {
|
|
644
808
|
throw new SerovalDeserializationError(error);
|
|
645
809
|
}
|