seroval 0.5.1 → 0.7.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.
@@ -1,16 +1,24 @@
1
+ /* eslint-disable prefer-spread */
1
2
  /* eslint-disable @typescript-eslint/no-use-before-define */
2
3
  import {
3
4
  SerializationContext,
4
5
  } from '../context';
5
- import { invQuote } from '../quote';
6
- import { AsyncServerValue } from '../types';
6
+ import { deserializeString } from '../string';
7
+ import { getReference } from './reference';
7
8
  import { getErrorConstructor, getTypedArrayConstructor } from './shared';
8
9
  import { SYMBOL_REF } from './symbols';
9
10
  import {
10
11
  SerovalAggregateErrorNode,
12
+ SerovalArrayBufferNode,
11
13
  SerovalArrayNode,
12
14
  SerovalBigIntTypedArrayNode,
15
+ SerovalBlobNode,
16
+ SerovalDataViewNode,
17
+ SerovalDateNode,
13
18
  SerovalErrorNode,
19
+ SerovalFileNode,
20
+ SerovalFormDataNode,
21
+ SerovalHeadersNode,
14
22
  SerovalIterableNode,
15
23
  SerovalMapNode,
16
24
  SerovalNode,
@@ -19,26 +27,36 @@ import {
19
27
  SerovalObjectNode,
20
28
  SerovalObjectRecordNode,
21
29
  SerovalPromiseNode,
30
+ SerovalReferenceNode,
31
+ SerovalRegExpNode,
22
32
  SerovalSetNode,
23
33
  SerovalTypedArrayNode,
34
+ SerovalURLNode,
35
+ SerovalURLSearchParamsNode,
24
36
  } from './types';
25
37
 
26
- function assignRef<T extends AsyncServerValue>(
38
+ function assignIndexedValue<T>(
27
39
  ctx: SerializationContext,
28
40
  index: number,
29
41
  value: T,
30
42
  ) {
31
- ctx.valueMap.set(index, value);
43
+ if (ctx.markedRefs.has(index)) {
44
+ ctx.valueMap.set(index, value);
45
+ }
32
46
  return value;
33
47
  }
34
48
 
35
- function deserializeNodeList(
49
+ function deserializeArray(
36
50
  ctx: SerializationContext,
37
- node: SerovalArrayNode | SerovalIterableNode | SerovalAggregateErrorNode,
38
- result: AsyncServerValue[],
51
+ node: SerovalArrayNode,
39
52
  ) {
53
+ const result: unknown[] = assignIndexedValue(
54
+ ctx,
55
+ node.i,
56
+ new Array<unknown>(node.l),
57
+ );
40
58
  let item: SerovalNode;
41
- for (let i = 0, len = node.a.length; i < len; i++) {
59
+ for (let i = 0, len = node.l; i < len; i++) {
42
60
  item = node.a[i];
43
61
  if (item) {
44
62
  result[i] = deserializeTree(ctx, item);
@@ -47,31 +65,16 @@ function deserializeNodeList(
47
65
  return result;
48
66
  }
49
67
 
50
- function deserializeArray(
51
- ctx: SerializationContext,
52
- node: SerovalArrayNode,
53
- ) {
54
- const result: AsyncServerValue[] = assignRef(
55
- ctx,
56
- node.i,
57
- new Array<AsyncServerValue>(node.l),
58
- );
59
- ctx.stack.push(node.i);
60
- deserializeNodeList(ctx, node, result);
61
- ctx.stack.pop();
62
- return result;
63
- }
64
-
65
68
  function deserializeProperties(
66
69
  ctx: SerializationContext,
67
70
  node: SerovalObjectRecordNode,
68
- result: Record<string, AsyncServerValue>,
71
+ result: Record<string, unknown>,
69
72
  ) {
70
73
  if (node.s === 0) {
71
74
  return {};
72
75
  }
73
76
  for (let i = 0; i < node.s; i++) {
74
- result[node.k[i]] = deserializeTree(ctx, node.v[i]);
77
+ result[deserializeString(node.k[i])] = deserializeTree(ctx, node.v[i]);
75
78
  }
76
79
  return result;
77
80
  }
@@ -80,10 +83,12 @@ function deserializeNullConstructor(
80
83
  ctx: SerializationContext,
81
84
  node: SerovalNullConstructorNode,
82
85
  ) {
83
- const result = assignRef(ctx, node.i, Object.create(null) as Record<string, AsyncServerValue>);
84
- ctx.stack.push(node.i);
86
+ const result = assignIndexedValue(
87
+ ctx,
88
+ node.i,
89
+ Object.create(null) as Record<string, unknown>,
90
+ );
85
91
  deserializeProperties(ctx, node.d, result);
86
- ctx.stack.pop();
87
92
  return result;
88
93
  }
89
94
 
@@ -91,10 +96,8 @@ function deserializeObject(
91
96
  ctx: SerializationContext,
92
97
  node: SerovalObjectNode,
93
98
  ) {
94
- const result = assignRef(ctx, node.i, {} as Record<string, AsyncServerValue>);
95
- ctx.stack.push(node.i);
99
+ const result = assignIndexedValue(ctx, node.i, {} as Record<string, unknown>);
96
100
  deserializeProperties(ctx, node.d, result);
97
- ctx.stack.pop();
98
101
  return result;
99
102
  }
100
103
 
@@ -102,12 +105,10 @@ function deserializeSet(
102
105
  ctx: SerializationContext,
103
106
  node: SerovalSetNode,
104
107
  ) {
105
- const result = assignRef(ctx, node.i, new Set<AsyncServerValue>());
106
- ctx.stack.push(node.i);
107
- for (let i = 0, len = node.a.length; i < len; i++) {
108
+ const result = assignIndexedValue(ctx, node.i, new Set<unknown>());
109
+ for (let i = 0, len = node.l; i < len; i++) {
108
110
  result.add(deserializeTree(ctx, node.a[i]));
109
111
  }
110
- ctx.stack.pop();
111
112
  return result;
112
113
  }
113
114
 
@@ -115,23 +116,21 @@ function deserializeMap(
115
116
  ctx: SerializationContext,
116
117
  node: SerovalMapNode,
117
118
  ) {
118
- const result = assignRef(
119
+ const result = assignIndexedValue(
119
120
  ctx,
120
121
  node.i,
121
- new Map<AsyncServerValue, AsyncServerValue>(),
122
+ new Map<unknown, unknown>(),
122
123
  );
123
- ctx.stack.push(node.i);
124
- for (let i = 0; i < node.d.s; i++) {
124
+ for (let i = 0, len = node.d.s; i < len; i++) {
125
125
  result.set(
126
126
  deserializeTree(ctx, node.d.k[i]),
127
127
  deserializeTree(ctx, node.d.v[i]),
128
128
  );
129
129
  }
130
- ctx.stack.pop();
131
130
  return result;
132
131
  }
133
132
 
134
- type AssignableValue = AggregateError | Error | Iterable<AsyncServerValue>
133
+ type AssignableValue = AggregateError | Error | Iterable<unknown>
135
134
  type AssignableNode = SerovalAggregateErrorNode | SerovalErrorNode | SerovalIterableNode;
136
135
 
137
136
  function deserializeDictionary<T extends AssignableValue>(
@@ -140,9 +139,7 @@ function deserializeDictionary<T extends AssignableValue>(
140
139
  result: T,
141
140
  ) {
142
141
  if (node.d) {
143
- ctx.stack.push(node.i);
144
142
  const fields = deserializeProperties(ctx, node.d, {});
145
- ctx.stack.pop();
146
143
  Object.assign(result, fields);
147
144
  }
148
145
  return result;
@@ -153,10 +150,11 @@ function deserializeAggregateError(
153
150
  node: SerovalAggregateErrorNode,
154
151
  ) {
155
152
  // Serialize the required arguments
156
- const result = assignRef(ctx, node.i, new AggregateError([], node.m));
157
- ctx.stack.push(node.i);
158
- result.errors = deserializeNodeList(ctx, node, new Array<AsyncServerValue>(node.l));
159
- ctx.stack.pop();
153
+ const result = assignIndexedValue(
154
+ ctx,
155
+ node.i,
156
+ new AggregateError([], deserializeString(node.m)),
157
+ );
160
158
  // `AggregateError` might've been extended
161
159
  // either through class or custom properties
162
160
  // Make sure to assign extra properties
@@ -168,13 +166,13 @@ function deserializeError(
168
166
  node: SerovalErrorNode,
169
167
  ) {
170
168
  const ErrorConstructor = getErrorConstructor(node.c);
171
- const result = assignRef(ctx, node.i, new ErrorConstructor(node.m));
169
+ const result = assignIndexedValue(ctx, node.i, new ErrorConstructor(deserializeString(node.m)));
172
170
  return deserializeDictionary(ctx, node, result);
173
171
  }
174
172
 
175
173
  interface Deferred {
176
- resolve(value: AsyncServerValue): void;
177
- promise: Promise<AsyncServerValue>;
174
+ resolve(value: unknown): void;
175
+ promise: Promise<unknown>;
178
176
  }
179
177
 
180
178
  function createDeferred(): Deferred {
@@ -194,26 +192,31 @@ function deserializePromise(
194
192
  node: SerovalPromiseNode,
195
193
  ) {
196
194
  const deferred = createDeferred();
197
- const result = assignRef(ctx, node.i, deferred.promise);
195
+ const result = assignIndexedValue(ctx, node.i, deferred.promise);
198
196
  deferred.resolve(deserializeTree(ctx, node.f));
199
197
  return result;
200
198
  }
201
199
 
200
+ function deserializeArrayBuffer(
201
+ ctx: SerializationContext,
202
+ node: SerovalArrayBufferNode,
203
+ ) {
204
+ const bytes = new Uint8Array(node.s);
205
+ const result = assignIndexedValue(ctx, node.i, bytes.buffer);
206
+ return result;
207
+ }
208
+
202
209
  function deserializeTypedArray(
203
210
  ctx: SerializationContext,
204
211
  node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
205
212
  ) {
206
213
  const TypedArray = getTypedArrayConstructor(node.c);
207
- const dummy = new TypedArray();
208
- const result = assignRef(ctx, node.i, new TypedArray(
209
- dummy.buffer,
214
+ const source = deserializeTree(ctx, node.f) as ArrayBuffer;
215
+ const result = assignIndexedValue(ctx, node.i, new TypedArray(
216
+ source,
217
+ node.b,
210
218
  node.l,
211
219
  ));
212
- for (let i = 0, len = node.s.length; i < len; i++) {
213
- result[i] = node.t === SerovalNodeType.BigIntTypedArray
214
- ? BigInt(node.s[i])
215
- : Number(node.s[i]);
216
- }
217
220
  return result;
218
221
  }
219
222
 
@@ -221,24 +224,131 @@ function deserializeIterable(
221
224
  ctx: SerializationContext,
222
225
  node: SerovalIterableNode,
223
226
  ) {
224
- const values: AsyncServerValue[] = [];
225
- deserializeNodeList(ctx, node, values);
226
- const result = assignRef(ctx, node.i, {
227
+ const values: unknown[] = [];
228
+ let item: SerovalNode;
229
+ for (let i = 0, len = node.l; i < len; i++) {
230
+ item = node.a[i];
231
+ if (item) {
232
+ values[i] = deserializeTree(ctx, item);
233
+ }
234
+ }
235
+ const result: Iterable<unknown> = assignIndexedValue(ctx, node.i, {
227
236
  [Symbol.iterator]: () => values.values(),
228
237
  });
229
238
  return deserializeDictionary(ctx, node, result);
230
239
  }
231
240
 
241
+ function deserializeDate(
242
+ ctx: SerializationContext,
243
+ node: SerovalDateNode,
244
+ ) {
245
+ return assignIndexedValue(ctx, node.i, new Date(node.s));
246
+ }
247
+
248
+ function deserializeRegExp(
249
+ ctx: SerializationContext,
250
+ node: SerovalRegExpNode,
251
+ ) {
252
+ return assignIndexedValue(ctx, node.i, new RegExp(node.c, node.m));
253
+ }
254
+
255
+ function deserializeURL(
256
+ ctx: SerializationContext,
257
+ node: SerovalURLNode,
258
+ ) {
259
+ return assignIndexedValue(ctx, node.i, new URL(deserializeString(node.s)));
260
+ }
261
+
262
+ function deserializeURLSearchParams(
263
+ ctx: SerializationContext,
264
+ node: SerovalURLSearchParamsNode,
265
+ ) {
266
+ return assignIndexedValue(ctx, node.i, new URLSearchParams(deserializeString(node.s)));
267
+ }
268
+
269
+ function deserializeReference(
270
+ ctx: SerializationContext,
271
+ node: SerovalReferenceNode,
272
+ ) {
273
+ return assignIndexedValue(ctx, node.i, getReference(deserializeString(node.s)));
274
+ }
275
+
276
+ function deserializeDataView(
277
+ ctx: SerializationContext,
278
+ node: SerovalDataViewNode,
279
+ ) {
280
+ const source = deserializeTree(ctx, node.f) as ArrayBuffer;
281
+ const result = assignIndexedValue(ctx, node.i, new DataView(
282
+ source,
283
+ node.b,
284
+ node.l,
285
+ ));
286
+ return result;
287
+ }
288
+
289
+ function deserializeBlob(
290
+ ctx: SerializationContext,
291
+ node: SerovalBlobNode,
292
+ ) {
293
+ const source = deserializeTree(ctx, node.f) as ArrayBuffer;
294
+ const result = assignIndexedValue(ctx, node.i, new Blob(
295
+ [source],
296
+ { type: deserializeString(node.c) },
297
+ ));
298
+ return result;
299
+ }
300
+
301
+ function deserializeFile(
302
+ ctx: SerializationContext,
303
+ node: SerovalFileNode,
304
+ ) {
305
+ const source = deserializeTree(ctx, node.f) as ArrayBuffer;
306
+ const result = assignIndexedValue(ctx, node.i, new File(
307
+ [source],
308
+ deserializeString(node.m),
309
+ { type: deserializeString(node.c), lastModified: node.b },
310
+ ));
311
+ return result;
312
+ }
313
+
314
+ function deserializeHeaders(
315
+ ctx: SerializationContext,
316
+ node: SerovalHeadersNode,
317
+ ) {
318
+ const result = assignIndexedValue(ctx, node.i, new Headers());
319
+ for (let i = 0, len = node.d.s; i < len; i++) {
320
+ result.set(
321
+ deserializeString(node.d.k[i]),
322
+ deserializeTree(ctx, node.d.v[i]) as string,
323
+ );
324
+ }
325
+ return result;
326
+ }
327
+
328
+ function deserializeFormData(
329
+ ctx: SerializationContext,
330
+ node: SerovalFormDataNode,
331
+ ) {
332
+ const result = assignIndexedValue(ctx, node.i, new FormData());
333
+ for (let i = 0, len = node.d.s; i < len; i++) {
334
+ result.set(
335
+ deserializeString(node.d.k[i]),
336
+ deserializeTree(ctx, node.d.v[i]) as FormDataEntryValue,
337
+ );
338
+ }
339
+ return result;
340
+ }
341
+
232
342
  export default function deserializeTree(
233
343
  ctx: SerializationContext,
234
344
  node: SerovalNode,
235
- ): AsyncServerValue {
345
+ ): unknown {
236
346
  switch (node.t) {
237
347
  case SerovalNodeType.Number:
238
348
  case SerovalNodeType.Boolean:
239
349
  return node.s;
240
350
  case SerovalNodeType.String:
241
- return invQuote(node.s);
351
+ return deserializeString(node.s);
242
352
  case SerovalNodeType.Undefined:
243
353
  return undefined;
244
354
  case SerovalNodeType.Null:
@@ -253,7 +363,7 @@ export default function deserializeTree(
253
363
  return NaN;
254
364
  case SerovalNodeType.BigInt:
255
365
  return BigInt(node.s);
256
- case SerovalNodeType.Reference:
366
+ case SerovalNodeType.IndexedValue:
257
367
  return ctx.valueMap.get(node.i);
258
368
  case SerovalNodeType.Array:
259
369
  return deserializeArray(ctx, node);
@@ -262,16 +372,20 @@ export default function deserializeTree(
262
372
  case SerovalNodeType.NullConstructor:
263
373
  return deserializeNullConstructor(ctx, node);
264
374
  case SerovalNodeType.Date:
265
- return assignRef(ctx, node.i, new Date(node.s));
375
+ return deserializeDate(ctx, node);
266
376
  case SerovalNodeType.RegExp:
267
- return assignRef(ctx, node.i, new RegExp(node.c, node.m));
377
+ return deserializeRegExp(ctx, node);
268
378
  case SerovalNodeType.Set:
269
379
  return deserializeSet(ctx, node);
270
380
  case SerovalNodeType.Map:
271
381
  return deserializeMap(ctx, node);
382
+ case SerovalNodeType.ArrayBuffer:
383
+ return deserializeArrayBuffer(ctx, node);
272
384
  case SerovalNodeType.BigIntTypedArray:
273
385
  case SerovalNodeType.TypedArray:
274
386
  return deserializeTypedArray(ctx, node);
387
+ case SerovalNodeType.DataView:
388
+ return deserializeDataView(ctx, node);
275
389
  case SerovalNodeType.AggregateError:
276
390
  return deserializeAggregateError(ctx, node);
277
391
  case SerovalNodeType.Error:
@@ -282,6 +396,20 @@ export default function deserializeTree(
282
396
  return deserializePromise(ctx, node);
283
397
  case SerovalNodeType.WKSymbol:
284
398
  return SYMBOL_REF[node.s];
399
+ case SerovalNodeType.URL:
400
+ return deserializeURL(ctx, node);
401
+ case SerovalNodeType.URLSearchParams:
402
+ return deserializeURLSearchParams(ctx, node);
403
+ case SerovalNodeType.Reference:
404
+ return deserializeReference(ctx, node);
405
+ case SerovalNodeType.Blob:
406
+ return deserializeBlob(ctx, node);
407
+ case SerovalNodeType.File:
408
+ return deserializeFile(ctx, node);
409
+ case SerovalNodeType.Headers:
410
+ return deserializeHeaders(ctx, node);
411
+ case SerovalNodeType.FormData:
412
+ return deserializeFormData(ctx, node);
285
413
  default:
286
414
  throw new Error('Unsupported type');
287
415
  }