seroval 0.7.0 → 0.8.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.
Files changed (41) hide show
  1. package/dist/cjs/development/index.cjs +1109 -1039
  2. package/dist/cjs/development/index.cjs.map +4 -4
  3. package/dist/cjs/production/index.cjs +3 -3
  4. package/dist/esm/development/index.mjs +1109 -1039
  5. package/dist/esm/development/index.mjs.map +4 -4
  6. package/dist/esm/production/index.mjs +3 -3
  7. package/dist/types/assert.d.ts +1 -1
  8. package/dist/types/context.d.ts +2 -2
  9. package/dist/types/index.d.ts +3 -4
  10. package/dist/types/string.d.ts +1 -1
  11. package/dist/types/tree/UnsupportedTypeError.d.ts +3 -0
  12. package/dist/types/tree/async.d.ts +3 -3
  13. package/dist/types/tree/constants.d.ts +11 -0
  14. package/dist/types/tree/deserialize.d.ts +2 -2
  15. package/dist/types/tree/primitives.d.ts +9 -15
  16. package/dist/types/tree/serialize.d.ts +2 -2
  17. package/dist/types/tree/shared.d.ts +10 -8
  18. package/dist/types/tree/sync.d.ts +3 -3
  19. package/dist/types/tree/types.d.ts +64 -71
  20. package/dist/types/tree/web-api.d.ts +2 -2
  21. package/dist/types/types.d.ts +4 -4
  22. package/package.json +10 -8
  23. package/src/assert.ts +2 -2
  24. package/src/compat.ts +0 -1
  25. package/src/context.ts +10 -7
  26. package/src/get-identifier.ts +1 -1
  27. package/src/index.ts +35 -26
  28. package/src/string.ts +2 -2
  29. package/src/tree/UnsupportedTypeError.ts +8 -0
  30. package/src/tree/async.ts +245 -233
  31. package/src/tree/constants.ts +72 -0
  32. package/src/tree/deserialize.ts +96 -93
  33. package/src/tree/primitives.ts +81 -134
  34. package/src/tree/reference.ts +4 -3
  35. package/src/tree/serialize.ts +251 -197
  36. package/src/tree/shared.ts +31 -22
  37. package/src/tree/symbols.ts +13 -13
  38. package/src/tree/sync.ts +226 -198
  39. package/src/tree/types.ts +74 -93
  40. package/src/tree/web-api.ts +10 -7
  41. package/src/types.ts +7 -3
@@ -0,0 +1,72 @@
1
+ import type { SerovalConstantNode } from './types';
2
+ import { SerovalConstant, SerovalNodeType } from './types';
3
+
4
+ function createConstantNode(value: SerovalConstant): SerovalConstantNode {
5
+ return {
6
+ t: SerovalNodeType.Constant,
7
+ i: undefined,
8
+ s: value,
9
+ l: undefined,
10
+ c: undefined,
11
+ m: undefined,
12
+ d: undefined,
13
+ a: undefined,
14
+ f: undefined,
15
+ b: undefined,
16
+ };
17
+ }
18
+
19
+ export const TRUE_NODE = createConstantNode(SerovalConstant.True);
20
+ export const FALSE_NODE = createConstantNode(SerovalConstant.False);
21
+ export const UNDEFINED_NODE = createConstantNode(SerovalConstant.Undefined);
22
+ export const NULL_NODE = createConstantNode(SerovalConstant.Null);
23
+ export const NEG_ZERO_NODE = createConstantNode(SerovalConstant.NegativeZero);
24
+ export const INFINITY_NODE = createConstantNode(SerovalConstant.Infinity);
25
+ export const NEG_INFINITY_NODE = createConstantNode(SerovalConstant.NegativeInfinity);
26
+ export const NAN_NODE = createConstantNode(SerovalConstant.NaN);
27
+
28
+ export function serializeConstant(node: SerovalConstantNode): string {
29
+ switch (node.s) {
30
+ case SerovalConstant.True:
31
+ return '!0';
32
+ case SerovalConstant.False:
33
+ return '!1';
34
+ case SerovalConstant.Undefined:
35
+ return 'void 0';
36
+ case SerovalConstant.Null:
37
+ return 'null';
38
+ case SerovalConstant.NegativeZero:
39
+ return '-0';
40
+ case SerovalConstant.Infinity:
41
+ return '1/0';
42
+ case SerovalConstant.NegativeInfinity:
43
+ return '-1/0';
44
+ case SerovalConstant.NaN:
45
+ return 'NaN';
46
+ default:
47
+ throw new Error('invariant');
48
+ }
49
+ }
50
+
51
+ export function deserializeConstant(node: SerovalConstantNode): unknown {
52
+ switch (node.s) {
53
+ case SerovalConstant.True:
54
+ return true;
55
+ case SerovalConstant.False:
56
+ return false;
57
+ case SerovalConstant.Undefined:
58
+ return undefined;
59
+ case SerovalConstant.Null:
60
+ return null;
61
+ case SerovalConstant.NegativeZero:
62
+ return -0;
63
+ case SerovalConstant.Infinity:
64
+ return Infinity;
65
+ case SerovalConstant.NegativeInfinity:
66
+ return -Infinity;
67
+ case SerovalConstant.NaN:
68
+ return NaN;
69
+ default:
70
+ throw new Error('invariant');
71
+ }
72
+ }
@@ -1,30 +1,32 @@
1
1
  /* eslint-disable prefer-spread */
2
2
  /* eslint-disable @typescript-eslint/no-use-before-define */
3
- import {
3
+ import type {
4
4
  SerializationContext,
5
5
  } from '../context';
6
6
  import { deserializeString } from '../string';
7
+ import type { BigIntTypedArrayValue, TypedArrayValue } from '../types';
8
+ import { deserializeConstant } from './constants';
7
9
  import { getReference } from './reference';
8
10
  import { getErrorConstructor, getTypedArrayConstructor } from './shared';
9
11
  import { SYMBOL_REF } from './symbols';
10
- import {
12
+ import type {
11
13
  SerovalAggregateErrorNode,
12
14
  SerovalArrayBufferNode,
13
15
  SerovalArrayNode,
14
16
  SerovalBigIntTypedArrayNode,
15
17
  SerovalBlobNode,
18
+ SerovalBoxedNode,
16
19
  SerovalDataViewNode,
17
20
  SerovalDateNode,
18
21
  SerovalErrorNode,
19
22
  SerovalFileNode,
20
23
  SerovalFormDataNode,
21
24
  SerovalHeadersNode,
22
- SerovalIterableNode,
23
25
  SerovalMapNode,
24
26
  SerovalNode,
25
- SerovalNodeType,
26
27
  SerovalNullConstructorNode,
27
28
  SerovalObjectNode,
29
+ SerovalObjectRecordKey,
28
30
  SerovalObjectRecordNode,
29
31
  SerovalPromiseNode,
30
32
  SerovalReferenceNode,
@@ -34,12 +36,16 @@ import {
34
36
  SerovalURLNode,
35
37
  SerovalURLSearchParamsNode,
36
38
  } from './types';
39
+ import {
40
+ SerovalNodeType,
41
+ SerovalObjectRecordSpecialKey,
42
+ } from './types';
37
43
 
38
44
  function assignIndexedValue<T>(
39
45
  ctx: SerializationContext,
40
46
  index: number,
41
47
  value: T,
42
- ) {
48
+ ): T {
43
49
  if (ctx.markedRefs.has(index)) {
44
50
  ctx.valueMap.set(index, value);
45
51
  }
@@ -49,14 +55,15 @@ function assignIndexedValue<T>(
49
55
  function deserializeArray(
50
56
  ctx: SerializationContext,
51
57
  node: SerovalArrayNode,
52
- ) {
58
+ ): unknown[] {
59
+ const len = node.l;
53
60
  const result: unknown[] = assignIndexedValue(
54
61
  ctx,
55
62
  node.i,
56
- new Array<unknown>(node.l),
63
+ new Array<unknown>(len),
57
64
  );
58
- let item: SerovalNode;
59
- for (let i = 0, len = node.l; i < len; i++) {
65
+ let item: SerovalNode | undefined;
66
+ for (let i = 0; i < len; i++) {
60
67
  item = node.a[i];
61
68
  if (item) {
62
69
  result[i] = deserializeTree(ctx, item);
@@ -68,46 +75,55 @@ function deserializeArray(
68
75
  function deserializeProperties(
69
76
  ctx: SerializationContext,
70
77
  node: SerovalObjectRecordNode,
71
- result: Record<string, unknown>,
72
- ) {
73
- if (node.s === 0) {
74
- return {};
75
- }
76
- for (let i = 0; i < node.s; i++) {
77
- result[deserializeString(node.k[i])] = deserializeTree(ctx, node.v[i]);
78
+ result: Record<string | symbol, unknown>,
79
+ ): Record<string | symbol, unknown> {
80
+ const len = node.s;
81
+ if (len) {
82
+ let key: SerovalObjectRecordKey;
83
+ let value: unknown;
84
+ const keys = node.k;
85
+ const vals = node.v;
86
+ for (let i = 0; i < len; i++) {
87
+ key = keys[i];
88
+ value = deserializeTree(ctx, vals[i]);
89
+ switch (key) {
90
+ case SerovalObjectRecordSpecialKey.SymbolIterator: {
91
+ const current = value as unknown[];
92
+ result[Symbol.iterator] = (): IterableIterator<unknown> => current.values();
93
+ }
94
+ break;
95
+ default:
96
+ result[deserializeString(key)] = value;
97
+ break;
98
+ }
99
+ }
78
100
  }
79
101
  return result;
80
102
  }
81
103
 
82
- function deserializeNullConstructor(
104
+ function deserializeObject(
83
105
  ctx: SerializationContext,
84
- node: SerovalNullConstructorNode,
85
- ) {
106
+ node: SerovalObjectNode | SerovalNullConstructorNode,
107
+ ): Record<string, unknown> {
86
108
  const result = assignIndexedValue(
87
109
  ctx,
88
110
  node.i,
89
- Object.create(null) as Record<string, unknown>,
111
+ (node.t === SerovalNodeType.Object
112
+ ? {}
113
+ : Object.create(null)) as Record<string, unknown>,
90
114
  );
91
115
  deserializeProperties(ctx, node.d, result);
92
116
  return result;
93
117
  }
94
118
 
95
- function deserializeObject(
96
- ctx: SerializationContext,
97
- node: SerovalObjectNode,
98
- ) {
99
- const result = assignIndexedValue(ctx, node.i, {} as Record<string, unknown>);
100
- deserializeProperties(ctx, node.d, result);
101
- return result;
102
- }
103
-
104
119
  function deserializeSet(
105
120
  ctx: SerializationContext,
106
121
  node: SerovalSetNode,
107
- ) {
122
+ ): Set<unknown> {
108
123
  const result = assignIndexedValue(ctx, node.i, new Set<unknown>());
124
+ const items = node.a;
109
125
  for (let i = 0, len = node.l; i < len; i++) {
110
- result.add(deserializeTree(ctx, node.a[i]));
126
+ result.add(deserializeTree(ctx, items[i]));
111
127
  }
112
128
  return result;
113
129
  }
@@ -115,29 +131,31 @@ function deserializeSet(
115
131
  function deserializeMap(
116
132
  ctx: SerializationContext,
117
133
  node: SerovalMapNode,
118
- ) {
134
+ ): Map<unknown, unknown> {
119
135
  const result = assignIndexedValue(
120
136
  ctx,
121
137
  node.i,
122
138
  new Map<unknown, unknown>(),
123
139
  );
140
+ const keys = node.d.k;
141
+ const vals = node.d.v;
124
142
  for (let i = 0, len = node.d.s; i < len; i++) {
125
143
  result.set(
126
- deserializeTree(ctx, node.d.k[i]),
127
- deserializeTree(ctx, node.d.v[i]),
144
+ deserializeTree(ctx, keys[i]),
145
+ deserializeTree(ctx, vals[i]),
128
146
  );
129
147
  }
130
148
  return result;
131
149
  }
132
150
 
133
151
  type AssignableValue = AggregateError | Error | Iterable<unknown>
134
- type AssignableNode = SerovalAggregateErrorNode | SerovalErrorNode | SerovalIterableNode;
152
+ type AssignableNode = SerovalAggregateErrorNode | SerovalErrorNode;
135
153
 
136
154
  function deserializeDictionary<T extends AssignableValue>(
137
155
  ctx: SerializationContext,
138
156
  node: AssignableNode,
139
157
  result: T,
140
- ) {
158
+ ): T {
141
159
  if (node.d) {
142
160
  const fields = deserializeProperties(ctx, node.d, {});
143
161
  Object.assign(result, fields);
@@ -148,7 +166,7 @@ function deserializeDictionary<T extends AssignableValue>(
148
166
  function deserializeAggregateError(
149
167
  ctx: SerializationContext,
150
168
  node: SerovalAggregateErrorNode,
151
- ) {
169
+ ): AggregateError {
152
170
  // Serialize the required arguments
153
171
  const result = assignIndexedValue(
154
172
  ctx,
@@ -164,7 +182,7 @@ function deserializeAggregateError(
164
182
  function deserializeError(
165
183
  ctx: SerializationContext,
166
184
  node: SerovalErrorNode,
167
- ) {
185
+ ): Error {
168
186
  const ErrorConstructor = getErrorConstructor(node.c);
169
187
  const result = assignIndexedValue(ctx, node.i, new ErrorConstructor(deserializeString(node.m)));
170
188
  return deserializeDictionary(ctx, node, result);
@@ -178,7 +196,7 @@ interface Deferred {
178
196
  function createDeferred(): Deferred {
179
197
  let resolver: Deferred['resolve'];
180
198
  return {
181
- resolve(v) {
199
+ resolve(v): void {
182
200
  resolver(v);
183
201
  },
184
202
  promise: new Promise((res) => {
@@ -187,10 +205,10 @@ function createDeferred(): Deferred {
187
205
  };
188
206
  }
189
207
 
190
- function deserializePromise(
208
+ async function deserializePromise(
191
209
  ctx: SerializationContext,
192
210
  node: SerovalPromiseNode,
193
- ) {
211
+ ): Promise<unknown> {
194
212
  const deferred = createDeferred();
195
213
  const result = assignIndexedValue(ctx, node.i, deferred.promise);
196
214
  deferred.resolve(deserializeTree(ctx, node.f));
@@ -200,7 +218,7 @@ function deserializePromise(
200
218
  function deserializeArrayBuffer(
201
219
  ctx: SerializationContext,
202
220
  node: SerovalArrayBufferNode,
203
- ) {
221
+ ): ArrayBuffer {
204
222
  const bytes = new Uint8Array(node.s);
205
223
  const result = assignIndexedValue(ctx, node.i, bytes.buffer);
206
224
  return result;
@@ -209,7 +227,7 @@ function deserializeArrayBuffer(
209
227
  function deserializeTypedArray(
210
228
  ctx: SerializationContext,
211
229
  node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
212
- ) {
230
+ ): TypedArrayValue | BigIntTypedArrayValue {
213
231
  const TypedArray = getTypedArrayConstructor(node.c);
214
232
  const source = deserializeTree(ctx, node.f) as ArrayBuffer;
215
233
  const result = assignIndexedValue(ctx, node.i, new TypedArray(
@@ -220,63 +238,45 @@ function deserializeTypedArray(
220
238
  return result;
221
239
  }
222
240
 
223
- function deserializeIterable(
224
- ctx: SerializationContext,
225
- node: SerovalIterableNode,
226
- ) {
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, {
236
- [Symbol.iterator]: () => values.values(),
237
- });
238
- return deserializeDictionary(ctx, node, result);
239
- }
240
-
241
241
  function deserializeDate(
242
242
  ctx: SerializationContext,
243
243
  node: SerovalDateNode,
244
- ) {
244
+ ): Date {
245
245
  return assignIndexedValue(ctx, node.i, new Date(node.s));
246
246
  }
247
247
 
248
248
  function deserializeRegExp(
249
249
  ctx: SerializationContext,
250
250
  node: SerovalRegExpNode,
251
- ) {
251
+ ): RegExp {
252
252
  return assignIndexedValue(ctx, node.i, new RegExp(node.c, node.m));
253
253
  }
254
254
 
255
255
  function deserializeURL(
256
256
  ctx: SerializationContext,
257
257
  node: SerovalURLNode,
258
- ) {
258
+ ): URL {
259
259
  return assignIndexedValue(ctx, node.i, new URL(deserializeString(node.s)));
260
260
  }
261
261
 
262
262
  function deserializeURLSearchParams(
263
263
  ctx: SerializationContext,
264
264
  node: SerovalURLSearchParamsNode,
265
- ) {
265
+ ): URLSearchParams {
266
266
  return assignIndexedValue(ctx, node.i, new URLSearchParams(deserializeString(node.s)));
267
267
  }
268
268
 
269
269
  function deserializeReference(
270
270
  ctx: SerializationContext,
271
271
  node: SerovalReferenceNode,
272
- ) {
272
+ ): unknown {
273
273
  return assignIndexedValue(ctx, node.i, getReference(deserializeString(node.s)));
274
274
  }
275
275
 
276
276
  function deserializeDataView(
277
277
  ctx: SerializationContext,
278
278
  node: SerovalDataViewNode,
279
- ) {
279
+ ): DataView {
280
280
  const source = deserializeTree(ctx, node.f) as ArrayBuffer;
281
281
  const result = assignIndexedValue(ctx, node.i, new DataView(
282
282
  source,
@@ -289,7 +289,7 @@ function deserializeDataView(
289
289
  function deserializeBlob(
290
290
  ctx: SerializationContext,
291
291
  node: SerovalBlobNode,
292
- ) {
292
+ ): Blob {
293
293
  const source = deserializeTree(ctx, node.f) as ArrayBuffer;
294
294
  const result = assignIndexedValue(ctx, node.i, new Blob(
295
295
  [source],
@@ -301,7 +301,7 @@ function deserializeBlob(
301
301
  function deserializeFile(
302
302
  ctx: SerializationContext,
303
303
  node: SerovalFileNode,
304
- ) {
304
+ ): File {
305
305
  const source = deserializeTree(ctx, node.f) as ArrayBuffer;
306
306
  const result = assignIndexedValue(ctx, node.i, new File(
307
307
  [source],
@@ -314,12 +314,14 @@ function deserializeFile(
314
314
  function deserializeHeaders(
315
315
  ctx: SerializationContext,
316
316
  node: SerovalHeadersNode,
317
- ) {
317
+ ): Headers {
318
318
  const result = assignIndexedValue(ctx, node.i, new Headers());
319
+ const keys = node.d.k;
320
+ const vals = node.d.v;
319
321
  for (let i = 0, len = node.d.s; i < len; i++) {
320
322
  result.set(
321
- deserializeString(node.d.k[i]),
322
- deserializeTree(ctx, node.d.v[i]) as string,
323
+ deserializeString(keys[i]),
324
+ deserializeTree(ctx, vals[i]) as string,
323
325
  );
324
326
  }
325
327
  return result;
@@ -328,39 +330,41 @@ function deserializeHeaders(
328
330
  function deserializeFormData(
329
331
  ctx: SerializationContext,
330
332
  node: SerovalFormDataNode,
331
- ) {
333
+ ): FormData {
332
334
  const result = assignIndexedValue(ctx, node.i, new FormData());
335
+ const keys = node.d.k;
336
+ const vals = node.d.v;
333
337
  for (let i = 0, len = node.d.s; i < len; i++) {
334
338
  result.set(
335
- deserializeString(node.d.k[i]),
336
- deserializeTree(ctx, node.d.v[i]) as FormDataEntryValue,
339
+ deserializeString(keys[i]),
340
+ deserializeTree(ctx, vals[i]) as FormDataEntryValue,
337
341
  );
338
342
  }
339
343
  return result;
340
344
  }
341
345
 
346
+ function deserializeBoxed(
347
+ ctx: SerializationContext,
348
+ node: SerovalBoxedNode,
349
+ ): unknown {
350
+ return assignIndexedValue(
351
+ ctx,
352
+ node.i,
353
+ Object(deserializeTree(ctx, node.f)),
354
+ );
355
+ }
356
+
342
357
  export default function deserializeTree(
343
358
  ctx: SerializationContext,
344
359
  node: SerovalNode,
345
360
  ): unknown {
346
361
  switch (node.t) {
362
+ case SerovalNodeType.Constant:
363
+ return deserializeConstant(node);
347
364
  case SerovalNodeType.Number:
348
- case SerovalNodeType.Boolean:
349
365
  return node.s;
350
366
  case SerovalNodeType.String:
351
367
  return deserializeString(node.s);
352
- case SerovalNodeType.Undefined:
353
- return undefined;
354
- case SerovalNodeType.Null:
355
- return null;
356
- case SerovalNodeType.NegativeZero:
357
- return -0;
358
- case SerovalNodeType.Infinity:
359
- return Infinity;
360
- case SerovalNodeType.NegativeInfinity:
361
- return -Infinity;
362
- case SerovalNodeType.NaN:
363
- return NaN;
364
368
  case SerovalNodeType.BigInt:
365
369
  return BigInt(node.s);
366
370
  case SerovalNodeType.IndexedValue:
@@ -368,9 +372,8 @@ export default function deserializeTree(
368
372
  case SerovalNodeType.Array:
369
373
  return deserializeArray(ctx, node);
370
374
  case SerovalNodeType.Object:
371
- return deserializeObject(ctx, node);
372
375
  case SerovalNodeType.NullConstructor:
373
- return deserializeNullConstructor(ctx, node);
376
+ return deserializeObject(ctx, node);
374
377
  case SerovalNodeType.Date:
375
378
  return deserializeDate(ctx, node);
376
379
  case SerovalNodeType.RegExp:
@@ -390,8 +393,6 @@ export default function deserializeTree(
390
393
  return deserializeAggregateError(ctx, node);
391
394
  case SerovalNodeType.Error:
392
395
  return deserializeError(ctx, node);
393
- case SerovalNodeType.Iterable:
394
- return deserializeIterable(ctx, node);
395
396
  case SerovalNodeType.Promise:
396
397
  return deserializePromise(ctx, node);
397
398
  case SerovalNodeType.WKSymbol:
@@ -410,7 +411,9 @@ export default function deserializeTree(
410
411
  return deserializeHeaders(ctx, node);
411
412
  case SerovalNodeType.FormData:
412
413
  return deserializeFormData(ctx, node);
414
+ case SerovalNodeType.Boxed:
415
+ return deserializeBoxed(ctx, node);
413
416
  default:
414
- throw new Error('Unsupported type');
417
+ throw new Error('invariant');
415
418
  }
416
419
  }