seroval 0.9.0 → 0.10.1

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 (90) hide show
  1. package/README.md +4 -287
  2. package/dist/cjs/development/index.cjs +3500 -1135
  3. package/dist/cjs/development/index.cjs.map +4 -4
  4. package/dist/cjs/production/index.cjs +12 -3
  5. package/dist/esm/development/index.mjs +3502 -1135
  6. package/dist/esm/development/index.mjs.map +4 -4
  7. package/dist/esm/production/index.mjs +12 -3
  8. package/dist/types/core/Serializer.d.ts +14 -0
  9. package/dist/types/{tree → core}/UnsupportedTypeError.d.ts +4 -3
  10. package/dist/types/{assert.d.ts → core/assert.d.ts} +1 -1
  11. package/dist/types/core/assignments.d.ts +33 -0
  12. package/dist/types/core/base-primitives.d.ts +12 -0
  13. package/dist/types/{compat.d.ts → core/compat.d.ts} +22 -22
  14. package/dist/types/core/constants.d.ts +89 -0
  15. package/dist/types/core/context.d.ts +9 -0
  16. package/dist/types/core/cross/async.d.ts +3 -0
  17. package/dist/types/core/cross/context.d.ts +30 -0
  18. package/dist/types/core/cross/index.d.ts +7 -0
  19. package/dist/types/core/cross/primitives.d.ts +9 -0
  20. package/dist/types/core/cross/serialize.d.ts +5 -0
  21. package/dist/types/core/cross/stream.d.ts +3 -0
  22. package/dist/types/core/cross/sync.d.ts +3 -0
  23. package/dist/types/core/cross/web-api.d.ts +4 -0
  24. package/dist/types/{get-identifier.d.ts → core/get-identifier.d.ts} +1 -1
  25. package/dist/types/core/keys.d.ts +12 -0
  26. package/dist/types/{tree/constants.d.ts → core/literals.d.ts} +9 -11
  27. package/dist/types/core/promise-to-result.d.ts +1 -0
  28. package/dist/types/{tree → core}/reference.d.ts +5 -6
  29. package/dist/types/{tree → core}/shared.d.ts +13 -13
  30. package/dist/types/{string.d.ts → core/string.d.ts} +3 -3
  31. package/dist/types/core/tree/async.d.ts +3 -0
  32. package/dist/types/core/tree/context.d.ts +45 -0
  33. package/dist/types/core/tree/deserialize.d.ts +3 -0
  34. package/dist/types/core/tree/index.d.ts +15 -0
  35. package/dist/types/core/tree/primitives.d.ts +9 -0
  36. package/dist/types/core/tree/serialize.d.ts +4 -0
  37. package/dist/types/core/tree/sync.d.ts +3 -0
  38. package/dist/types/core/tree/web-api.d.ts +4 -0
  39. package/dist/types/{tree → core}/types.d.ts +228 -238
  40. package/dist/types/core/web-api.d.ts +4 -0
  41. package/dist/types/index.d.ts +9 -19
  42. package/dist/types/types.d.ts +20 -20
  43. package/package.json +5 -5
  44. package/src/core/Serializer.ts +46 -0
  45. package/src/{tree → core}/UnsupportedTypeError.ts +1 -1
  46. package/src/core/assignments.ts +159 -0
  47. package/src/{tree/primitives.ts → core/base-primitives.ts} +33 -136
  48. package/src/core/constants.ts +169 -0
  49. package/src/core/context.ts +15 -0
  50. package/src/core/cross/async.ts +614 -0
  51. package/src/core/cross/context.ts +79 -0
  52. package/src/core/cross/index.ts +154 -0
  53. package/src/core/cross/primitives.ts +137 -0
  54. package/src/core/cross/serialize.ts +846 -0
  55. package/src/core/cross/stream.ts +740 -0
  56. package/src/core/cross/sync.ts +561 -0
  57. package/src/core/cross/web-api.ts +55 -0
  58. package/src/core/header.js +65 -0
  59. package/src/core/keys.ts +33 -0
  60. package/src/core/literals.ts +28 -0
  61. package/src/core/promise-to-result.ts +9 -0
  62. package/src/{tree → core}/reference.ts +6 -7
  63. package/src/{tree → core}/shared.ts +4 -4
  64. package/src/{tree → core/tree}/async.ts +46 -34
  65. package/src/core/tree/context.ts +136 -0
  66. package/src/{tree → core/tree}/deserialize.ts +68 -55
  67. package/src/core/tree/index.ts +146 -0
  68. package/src/core/tree/primitives.ts +132 -0
  69. package/src/{tree → core/tree}/serialize.ts +87 -193
  70. package/src/{tree → core/tree}/sync.ts +50 -39
  71. package/src/{tree → core/tree}/web-api.ts +8 -52
  72. package/src/{tree → core}/types.ts +76 -60
  73. package/src/core/web-api.ts +51 -0
  74. package/src/index.ts +7 -141
  75. package/src/types.ts +1 -1
  76. package/dist/types/context.d.ts +0 -67
  77. package/dist/types/tree/async.d.ts +0 -3
  78. package/dist/types/tree/deserialize.d.ts +0 -3
  79. package/dist/types/tree/primitives.d.ts +0 -19
  80. package/dist/types/tree/serialize.d.ts +0 -4
  81. package/dist/types/tree/symbols.d.ts +0 -33
  82. package/dist/types/tree/sync.d.ts +0 -3
  83. package/dist/types/tree/web-api.d.ts +0 -6
  84. package/src/context.ts +0 -164
  85. package/src/tree/constants.ts +0 -73
  86. package/src/tree/symbols.ts +0 -65
  87. /package/src/{assert.ts → core/assert.ts} +0 -0
  88. /package/src/{compat.ts → core/compat.ts} +0 -0
  89. /package/src/{get-identifier.ts → core/get-identifier.ts} +0 -0
  90. /package/src/{string.ts → core/string.ts} +0 -0
@@ -0,0 +1,28 @@
1
+ import { SerovalConstant, SerovalNodeType } from './constants';
2
+ import type { SerovalConstantNode } 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
+ p: undefined,
13
+ e: undefined,
14
+ a: undefined,
15
+ f: undefined,
16
+ b: undefined,
17
+ o: undefined,
18
+ };
19
+ }
20
+
21
+ export const TRUE_NODE = createConstantNode(SerovalConstant.True);
22
+ export const FALSE_NODE = createConstantNode(SerovalConstant.False);
23
+ export const UNDEFINED_NODE = createConstantNode(SerovalConstant.Undefined);
24
+ export const NULL_NODE = createConstantNode(SerovalConstant.Null);
25
+ export const NEG_ZERO_NODE = createConstantNode(SerovalConstant.NegativeZero);
26
+ export const INFINITY_NODE = createConstantNode(SerovalConstant.Infinity);
27
+ export const NEG_INFINITY_NODE = createConstantNode(SerovalConstant.NegativeInfinity);
28
+ export const NAN_NODE = createConstantNode(SerovalConstant.NaN);
@@ -0,0 +1,9 @@
1
+ export default async function promiseToResult(
2
+ current: Promise<unknown>,
3
+ ): Promise<[0 | 1, unknown]> {
4
+ try {
5
+ return [1, await current];
6
+ } catch (e) {
7
+ return [0, e];
8
+ }
9
+ }
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable no-restricted-globals */
2
- import assert from '../assert';
2
+ import assert from './assert';
3
+ import { REFERENCES_KEY } from './keys';
3
4
 
4
5
  const REFERENCE = new Map<unknown, string>();
5
6
  const INV_REFERENCE = new Map<string, unknown>();
@@ -28,31 +29,29 @@ export function getReference<T>(id: string): T {
28
29
  return INV_REFERENCE.get(id) as T;
29
30
  }
30
31
 
31
- export const GLOBAL_KEY = '__SEROVAL__';
32
-
33
32
  if (typeof globalThis !== undefined) {
34
- Object.defineProperty(globalThis, GLOBAL_KEY, {
33
+ Object.defineProperty(globalThis, REFERENCES_KEY, {
35
34
  value: INV_REFERENCE,
36
35
  configurable: true,
37
36
  writable: false,
38
37
  enumerable: false,
39
38
  });
40
39
  } else if (typeof window !== undefined) {
41
- Object.defineProperty(window, GLOBAL_KEY, {
40
+ Object.defineProperty(window, REFERENCES_KEY, {
42
41
  value: INV_REFERENCE,
43
42
  configurable: true,
44
43
  writable: false,
45
44
  enumerable: false,
46
45
  });
47
46
  } else if (typeof self !== undefined) {
48
- Object.defineProperty(self, GLOBAL_KEY, {
47
+ Object.defineProperty(self, REFERENCES_KEY, {
49
48
  value: INV_REFERENCE,
50
49
  configurable: true,
51
50
  writable: false,
52
51
  enumerable: false,
53
52
  });
54
53
  } else if (typeof global !== undefined) {
55
- Object.defineProperty(global, GLOBAL_KEY, {
54
+ Object.defineProperty(global, REFERENCES_KEY, {
56
55
  value: INV_REFERENCE,
57
56
  configurable: true,
58
57
  writable: false,
@@ -1,9 +1,9 @@
1
- import { Feature } from '../compat';
2
- import type { ParserContext } from '../context';
1
+ import { Feature } from './compat';
3
2
  import type {
4
3
  ErrorValue,
5
4
  } from '../types';
6
- import { SerovalObjectFlags } from './types';
5
+ import { SerovalObjectFlags } from './constants';
6
+ import type { BaseParserContext } from './context';
7
7
 
8
8
  export function getErrorConstructorName(error: ErrorValue): string {
9
9
  if (error instanceof EvalError) {
@@ -51,7 +51,7 @@ export function getErrorConstructor(errorName: string): ErrorConstructors {
51
51
  }
52
52
 
53
53
  export function getErrorOptions(
54
- ctx: ParserContext,
54
+ ctx: BaseParserContext,
55
55
  error: Error,
56
56
  ): Record<string, unknown> | undefined {
57
57
  let options: Record<string, unknown> | undefined;
@@ -2,44 +2,36 @@
2
2
  /* eslint-disable @typescript-eslint/no-use-before-define */
3
3
  import assert from '../assert';
4
4
  import { Feature } from '../compat';
5
- import type { ParserContext } from '../context';
5
+ import type { ParserContext } from './context';
6
6
  import {
7
7
  createIndexedValue,
8
- } from '../context';
8
+ } from './context';
9
9
  import { serializeString } from '../string';
10
10
  import type {
11
11
  BigIntTypedArrayValue,
12
12
  TypedArrayValue,
13
- } from '../types';
14
- import UnsupportedTypeError from './UnsupportedTypeError';
13
+ } from '../../types';
14
+ import UnsupportedTypeError from '../UnsupportedTypeError';
15
15
  import {
16
16
  TRUE_NODE,
17
17
  FALSE_NODE,
18
18
  UNDEFINED_NODE,
19
19
  NULL_NODE,
20
- } from './constants';
20
+ } from '../literals';
21
21
  import {
22
- createBigIntNode,
23
22
  createBigIntTypedArrayNode,
24
- createDateNode,
25
- createNumberNode,
26
- createIndexedValueNode,
27
- createRegExpNode,
28
- createStringNode,
29
23
  createTypedArrayNode,
30
- createReferenceNode,
31
- createArrayBufferNode,
32
24
  createDataViewNode,
33
25
  createSymbolNode,
34
26
  createFunctionNode,
35
27
  } from './primitives';
36
- import { hasReferenceID } from './reference';
28
+ import { hasReferenceID } from '../reference';
37
29
  import {
38
30
  getErrorConstructorName,
39
31
  getErrorOptions,
40
32
  getObjectFlag,
41
33
  isIterable,
42
- } from './shared';
34
+ } from '../shared';
43
35
  import type {
44
36
  SerovalAggregateErrorNode,
45
37
  SerovalArrayNode,
@@ -56,17 +48,27 @@ import type {
56
48
  SerovalPlainRecordNode,
57
49
  SerovalPromiseNode,
58
50
  SerovalSetNode,
59
- } from './types';
51
+ } from '../types';
60
52
  import {
61
- SerovalNodeType,
62
53
  SerovalObjectRecordSpecialKey,
63
- } from './types';
54
+ } from '../types';
64
55
  import {
65
56
  createBlobNode,
66
57
  createFileNode,
67
- createURLNode,
68
- createURLSearchParamsNode,
69
58
  } from './web-api';
59
+ import { SerovalNodeType } from '../constants';
60
+ import {
61
+ createArrayBufferNode,
62
+ createBigIntNode,
63
+ createDateNode,
64
+ createIndexedValueNode,
65
+ createNumberNode,
66
+ createReferenceNode,
67
+ createRegExpNode,
68
+ createStringNode,
69
+ } from '../base-primitives';
70
+ import { createURLNode, createURLSearchParamsNode } from '../web-api';
71
+ import promiseToResult from '../promise-to-result';
70
72
 
71
73
  type ObjectLikeNode =
72
74
  | SerovalObjectNode
@@ -111,7 +113,8 @@ async function generateArrayNode(
111
113
  l: current.length,
112
114
  c: undefined,
113
115
  m: undefined,
114
- d: undefined,
116
+ p: undefined,
117
+ e: undefined,
115
118
  a: await generateNodeList(ctx, current),
116
119
  f: undefined,
117
120
  b: undefined,
@@ -155,7 +158,8 @@ async function generateMapNode(
155
158
  l: undefined,
156
159
  c: undefined,
157
160
  m: undefined,
158
- d: { k: keyNodes, v: valueNodes, s: len },
161
+ p: undefined,
162
+ e: { k: keyNodes, v: valueNodes, s: len },
159
163
  a: undefined,
160
164
  f: undefined,
161
165
  b: undefined,
@@ -193,7 +197,8 @@ async function generateSetNode(
193
197
  l: len,
194
198
  c: undefined,
195
199
  m: undefined,
196
- d: undefined,
200
+ p: undefined,
201
+ e: undefined,
197
202
  a: nodes,
198
203
  f: undefined,
199
204
  b: undefined,
@@ -295,17 +300,18 @@ async function generatePromiseNode(
295
300
  current: Promise<unknown>,
296
301
  ): Promise<SerovalPromiseNode> {
297
302
  assert(ctx.features & Feature.Promise, new UnsupportedTypeError(current));
303
+ const [status, result] = await promiseToResult(current);
298
304
  return {
299
305
  t: SerovalNodeType.Promise,
300
306
  i: id,
301
- s: undefined,
307
+ s: status,
302
308
  l: undefined,
303
309
  c: undefined,
304
310
  m: undefined,
305
- // Parse options first before the items
306
- d: undefined,
311
+ p: undefined,
312
+ e: undefined,
307
313
  a: undefined,
308
- f: await parseAsync(ctx, await current),
314
+ f: await parseAsync(ctx, result),
309
315
  b: undefined,
310
316
  o: undefined,
311
317
  };
@@ -324,7 +330,8 @@ async function generateObjectNode(
324
330
  l: undefined,
325
331
  c: undefined,
326
332
  m: undefined,
327
- d: await generateProperties(ctx, current),
333
+ p: await generateProperties(ctx, current),
334
+ e: undefined,
328
335
  a: undefined,
329
336
  f: undefined,
330
337
  b: undefined,
@@ -348,7 +355,8 @@ async function generateAggregateErrorNode(
348
355
  l: undefined,
349
356
  c: undefined,
350
357
  m: serializeString(current.message),
351
- d: optionsNode,
358
+ p: optionsNode,
359
+ e: undefined,
352
360
  a: undefined,
353
361
  f: undefined,
354
362
  b: undefined,
@@ -372,7 +380,8 @@ async function generateErrorNode(
372
380
  l: undefined,
373
381
  c: getErrorConstructorName(current),
374
382
  m: serializeString(current.message),
375
- d: optionsNode,
383
+ p: optionsNode,
384
+ e: undefined,
376
385
  a: undefined,
377
386
  f: undefined,
378
387
  b: undefined,
@@ -397,7 +406,8 @@ async function generateHeadersNode(
397
406
  l: undefined,
398
407
  c: undefined,
399
408
  m: undefined,
400
- d: await generatePlainProperties(ctx, items),
409
+ p: undefined,
410
+ e: await generatePlainProperties(ctx, items),
401
411
  a: undefined,
402
412
  f: undefined,
403
413
  b: undefined,
@@ -422,7 +432,8 @@ async function generateFormDataNode(
422
432
  l: undefined,
423
433
  c: undefined,
424
434
  m: undefined,
425
- d: await generatePlainProperties(ctx, items),
435
+ p: undefined,
436
+ e: await generatePlainProperties(ctx, items),
426
437
  a: undefined,
427
438
  f: undefined,
428
439
  b: undefined,
@@ -442,7 +453,8 @@ async function generateBoxedNode(
442
453
  l: undefined,
443
454
  c: undefined,
444
455
  m: undefined,
445
- d: undefined,
456
+ p: undefined,
457
+ e: undefined,
446
458
  a: undefined,
447
459
  f: await parseAsync(ctx, current.valueOf()),
448
460
  b: undefined,
@@ -460,7 +472,7 @@ async function parseObject(
460
472
  // Non-primitive values needs a reference ID
461
473
  // mostly because the values themselves are stateful
462
474
  const id = createIndexedValue(ctx, current);
463
- if (ctx.markedRefs.has(id)) {
475
+ if (ctx.reference.marked.has(id)) {
464
476
  return createIndexedValueNode(id);
465
477
  }
466
478
  if (hasReferenceID(current)) {
@@ -0,0 +1,136 @@
1
+ import { ALL_ENABLED } from '../compat';
2
+ import type { BaseParserContext, BaseSerializerContext } from '../context';
3
+ import getIdentifier from '../get-identifier';
4
+
5
+ export interface ParserReference {
6
+ ids: Map<unknown, number>;
7
+ marked: Set<number>;
8
+ }
9
+
10
+ export interface ParserContext extends BaseParserContext {
11
+ reference: ParserReference;
12
+ }
13
+
14
+ export interface ParserOptions {
15
+ disabledFeatures: number;
16
+ }
17
+
18
+ export function createParserContext(options: Partial<ParserOptions> = {}): ParserContext {
19
+ return {
20
+ reference: {
21
+ ids: new Map(),
22
+ marked: new Set(),
23
+ },
24
+ features: ALL_ENABLED ^ (options.disabledFeatures || 0),
25
+ };
26
+ }
27
+
28
+ export interface SerializerReference {
29
+ size: number;
30
+ // Map tree refs to actual refs
31
+ valid: (number | undefined)[];
32
+ // Refs that are...referenced
33
+ marked: Set<number>;
34
+ }
35
+
36
+ export interface SerializerContext extends BaseSerializerContext {
37
+ reference: SerializerReference;
38
+ // Variables
39
+ vars: (string | undefined)[];
40
+ }
41
+
42
+ export interface SerializerOptions {
43
+ markedRefs: number[] | Set<number>;
44
+ features: number;
45
+ }
46
+
47
+ export function createSerializerContext(options: SerializerOptions): SerializerContext {
48
+ return {
49
+ stack: [],
50
+ vars: [],
51
+ assignments: [],
52
+ reference: {
53
+ valid: [],
54
+ size: 0,
55
+ marked: new Set(options.markedRefs),
56
+ },
57
+ features: options.features,
58
+ flags: [],
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Increments the number of references the referenced value has
64
+ */
65
+ export function markRef(
66
+ ctx: ParserContext | SerializerContext,
67
+ current: number,
68
+ ): void {
69
+ ctx.reference.marked.add(current);
70
+ }
71
+ /**
72
+ * Creates the reference param (identifier) from the given reference ID
73
+ * Calling this function means the value has been referenced somewhere
74
+ */
75
+ export function getRefParam(ctx: SerializerContext, index: number): string {
76
+ /**
77
+ * Creates a new reference ID from a given reference ID
78
+ * This new reference ID means that the reference itself
79
+ * has been referenced at least once, and is used to generate
80
+ * the variables
81
+ */
82
+ let actualIndex = ctx.reference.valid[index];
83
+ if (actualIndex == null) {
84
+ actualIndex = ctx.reference.size++;
85
+ ctx.reference.valid[index] = actualIndex;
86
+ }
87
+ let identifier = ctx.vars[actualIndex];
88
+ if (identifier == null) {
89
+ identifier = getIdentifier(actualIndex);
90
+ ctx.vars[actualIndex] = identifier;
91
+ }
92
+ return identifier;
93
+ }
94
+
95
+ export function getRootID<T>(
96
+ ctx: ParserContext,
97
+ current: T,
98
+ ): number {
99
+ const ref = ctx.reference.ids.get(current);
100
+ if (ref == null) {
101
+ return ctx.reference.ids.size;
102
+ }
103
+ return ref;
104
+ }
105
+
106
+ export function createIndexedValue<T>(
107
+ ctx: ParserContext,
108
+ current: T,
109
+ ): number {
110
+ const ref = ctx.reference.ids.get(current);
111
+ if (ref == null) {
112
+ const id = ctx.reference.ids.size;
113
+ ctx.reference.ids.set(current, id);
114
+ return id;
115
+ }
116
+ markRef(ctx, ref);
117
+ return ref;
118
+ }
119
+
120
+ export interface DeserializerContext {
121
+ values: Map<number, unknown>;
122
+ refs: Set<number>;
123
+ }
124
+
125
+ export interface DeserializerOptions {
126
+ markedRefs: number[] | Set<number>;
127
+ }
128
+
129
+ export function createDeserializerContext(
130
+ options: DeserializerOptions,
131
+ ): DeserializerContext {
132
+ return {
133
+ values: new Map(),
134
+ refs: new Set(options.markedRefs),
135
+ };
136
+ }