seroval 1.3.2 → 1.4.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 (112) hide show
  1. package/dist/cjs/development/index.cjs +2640 -2683
  2. package/dist/cjs/development/index.cjs.map +4 -4
  3. package/dist/cjs/production/index.cjs +3 -17
  4. package/dist/esm/development/index.mjs +2640 -2683
  5. package/dist/esm/development/index.mjs.map +4 -4
  6. package/dist/esm/production/index.mjs +3 -17
  7. package/dist/types/core/base-primitives.d.ts +1 -2
  8. package/dist/types/core/base-primitives.d.ts.map +1 -1
  9. package/dist/types/core/compat.d.ts +1 -1
  10. package/dist/types/core/compat.d.ts.map +1 -1
  11. package/dist/types/core/constants.d.ts +1 -0
  12. package/dist/types/core/constants.d.ts.map +1 -1
  13. package/dist/types/core/constructors.d.ts +54 -0
  14. package/dist/types/core/constructors.d.ts.map +1 -0
  15. package/dist/types/core/context/async-parser.d.ts +19 -0
  16. package/dist/types/core/context/async-parser.d.ts.map +1 -0
  17. package/dist/types/core/context/deserializer.d.ts +35 -38
  18. package/dist/types/core/context/deserializer.d.ts.map +1 -1
  19. package/dist/types/core/context/parser.d.ts +32 -19
  20. package/dist/types/core/context/parser.d.ts.map +1 -1
  21. package/dist/types/core/context/serializer.d.ts +38 -99
  22. package/dist/types/core/context/serializer.d.ts.map +1 -1
  23. package/dist/types/core/context/sync-parser.d.ts +59 -0
  24. package/dist/types/core/context/sync-parser.d.ts.map +1 -0
  25. package/dist/types/core/cross/index.d.ts +12 -13
  26. package/dist/types/core/cross/index.d.ts.map +1 -1
  27. package/dist/types/core/errors.d.ts.map +1 -1
  28. package/dist/types/core/function-string.d.ts +2 -2
  29. package/dist/types/core/function-string.d.ts.map +1 -1
  30. package/dist/types/core/plugin.d.ts +13 -11
  31. package/dist/types/core/plugin.d.ts.map +1 -1
  32. package/dist/types/core/reference.d.ts.map +1 -1
  33. package/dist/types/core/special-reference.d.ts +3 -2
  34. package/dist/types/core/special-reference.d.ts.map +1 -1
  35. package/dist/types/core/stream.d.ts +1 -2
  36. package/dist/types/core/stream.d.ts.map +1 -1
  37. package/dist/types/core/symbols.d.ts +14 -0
  38. package/dist/types/core/symbols.d.ts.map +1 -0
  39. package/dist/types/core/tree/index.d.ts +3 -2
  40. package/dist/types/core/tree/index.d.ts.map +1 -1
  41. package/dist/types/core/types.d.ts +3 -1
  42. package/dist/types/core/types.d.ts.map +1 -1
  43. package/dist/types/core/utils/iterator-to-sequence.d.ts.map +1 -1
  44. package/dist/types/index.d.ts +10 -5
  45. package/dist/types/index.d.ts.map +1 -1
  46. package/package.json +17 -19
  47. package/src/core/base-primitives.ts +0 -27
  48. package/src/core/compat.ts +2 -1
  49. package/src/core/constants.ts +28 -26
  50. package/src/core/constructors.ts +269 -0
  51. package/src/core/context/async-parser.ts +586 -0
  52. package/src/core/context/deserializer.ts +506 -316
  53. package/src/core/context/parser.ts +243 -180
  54. package/src/core/context/serializer.ts +1058 -827
  55. package/src/core/context/sync-parser.ts +833 -0
  56. package/src/core/cross/index.ts +63 -47
  57. package/src/core/errors.ts +73 -12
  58. package/src/core/function-string.ts +11 -10
  59. package/src/core/plugin.ts +20 -11
  60. package/src/core/reference.ts +8 -5
  61. package/src/core/special-reference.ts +18 -90
  62. package/src/core/stream.ts +18 -152
  63. package/src/core/symbols.ts +18 -0
  64. package/src/core/tree/index.ts +45 -31
  65. package/src/core/types.ts +7 -2
  66. package/src/core/utils/iterator-to-sequence.ts +6 -28
  67. package/src/index.ts +29 -11
  68. package/dist/types/core/context/parser/async.d.ts +0 -24
  69. package/dist/types/core/context/parser/async.d.ts.map +0 -1
  70. package/dist/types/core/context/parser/stream.d.ts +0 -43
  71. package/dist/types/core/context/parser/stream.d.ts.map +0 -1
  72. package/dist/types/core/context/parser/sync.d.ts +0 -30
  73. package/dist/types/core/context/parser/sync.d.ts.map +0 -1
  74. package/dist/types/core/cross/async.d.ts +0 -8
  75. package/dist/types/core/cross/async.d.ts.map +0 -1
  76. package/dist/types/core/cross/deserializer.d.ts +0 -9
  77. package/dist/types/core/cross/deserializer.d.ts.map +0 -1
  78. package/dist/types/core/cross/parser.d.ts +0 -6
  79. package/dist/types/core/cross/parser.d.ts.map +0 -1
  80. package/dist/types/core/cross/serializer.d.ts +0 -16
  81. package/dist/types/core/cross/serializer.d.ts.map +0 -1
  82. package/dist/types/core/cross/stream.d.ts +0 -8
  83. package/dist/types/core/cross/stream.d.ts.map +0 -1
  84. package/dist/types/core/cross/sync.d.ts +0 -8
  85. package/dist/types/core/cross/sync.d.ts.map +0 -1
  86. package/dist/types/core/tree/async.d.ts +0 -8
  87. package/dist/types/core/tree/async.d.ts.map +0 -1
  88. package/dist/types/core/tree/deserializer.d.ts +0 -13
  89. package/dist/types/core/tree/deserializer.d.ts.map +0 -1
  90. package/dist/types/core/tree/serializer.d.ts +0 -29
  91. package/dist/types/core/tree/serializer.d.ts.map +0 -1
  92. package/dist/types/core/tree/sync.d.ts +0 -8
  93. package/dist/types/core/tree/sync.d.ts.map +0 -1
  94. package/dist/types/core/utils/assert.d.ts +0 -2
  95. package/dist/types/core/utils/assert.d.ts.map +0 -1
  96. package/dist/types/core/utils/deferred.d.ts +0 -7
  97. package/dist/types/core/utils/deferred.d.ts.map +0 -1
  98. package/src/core/context/parser/async.ts +0 -495
  99. package/src/core/context/parser/stream.ts +0 -323
  100. package/src/core/context/parser/sync.ts +0 -404
  101. package/src/core/cross/async.ts +0 -9
  102. package/src/core/cross/deserializer.ts +0 -16
  103. package/src/core/cross/parser.ts +0 -7
  104. package/src/core/cross/serializer.ts +0 -72
  105. package/src/core/cross/stream.ts +0 -9
  106. package/src/core/cross/sync.ts +0 -9
  107. package/src/core/tree/async.ts +0 -9
  108. package/src/core/tree/deserializer.ts +0 -26
  109. package/src/core/tree/serializer.ts +0 -98
  110. package/src/core/tree/sync.ts +0 -9
  111. package/src/core/utils/assert.ts +0 -5
  112. package/src/core/utils/deferred.ts +0 -22
@@ -8,7 +8,7 @@ import type { WellKnownSymbols } from '../constants';
8
8
  import { INV_SYMBOL_REF, NIL, SerovalNodeType } from '../constants';
9
9
  import { SerovalUnsupportedTypeError } from '../errors';
10
10
  import { createSerovalNode } from '../node';
11
- import type { Plugin, PluginAccessOptions, SerovalMode } from '../plugin';
11
+ import type { PluginAccessOptions, SerovalMode } from '../plugin';
12
12
  import { hasReferenceID } from '../reference';
13
13
  import {
14
14
  ASYNC_ITERATOR,
@@ -16,7 +16,10 @@ import {
16
16
  SPECIAL_REFS,
17
17
  SpecialReference,
18
18
  } from '../special-reference';
19
+ import { serializeString } from '../string';
20
+ import { SYM_ASYNC_ITERATOR, SYM_ITERATOR } from '../symbols';
19
21
  import type {
22
+ SerovalArrayBufferNode,
20
23
  SerovalAsyncIteratorFactoryNode,
21
24
  SerovalIndexedValueNode,
22
25
  SerovalIteratorFactoryNode,
@@ -30,7 +33,6 @@ import type {
30
33
  SerovalSpecialReferenceNode,
31
34
  SerovalWKSymbolNode,
32
35
  } from '../types';
33
- import assert from '../utils/assert';
34
36
  import { getObjectFlag } from '../utils/get-object-flag';
35
37
 
36
38
  export interface BaseParserContextOptions extends PluginAccessOptions {
@@ -61,210 +63,271 @@ export interface ReferencedNode {
61
63
 
62
64
  type ObjectNode = FreshNode | IndexedNode | ReferencedNode;
63
65
 
64
- export abstract class BaseParserContext implements PluginAccessOptions {
65
- abstract readonly mode: SerovalMode;
66
+ export interface BaseParserContext extends PluginAccessOptions {
67
+ readonly mode: SerovalMode;
66
68
 
67
- features: number;
68
-
69
- marked = new Set<number>();
69
+ marked: Set<number>;
70
70
 
71
71
  refs: Map<unknown, number>;
72
72
 
73
- plugins?: Plugin<any, any>[] | undefined;
73
+ features: number;
74
+ }
74
75
 
75
- constructor(options: BaseParserContextOptions) {
76
- this.plugins = options.plugins;
77
- this.features = ALL_ENABLED ^ (options.disabledFeatures || 0);
78
- this.refs = options.refs || new Map<unknown, number>();
79
- }
76
+ export function createBaseParserContext(
77
+ mode: SerovalMode,
78
+ options: BaseParserContextOptions,
79
+ ): BaseParserContext {
80
+ return {
81
+ plugins: options.plugins,
82
+ mode,
83
+ marked: new Set(),
84
+ features: ALL_ENABLED ^ (options.disabledFeatures || 0),
85
+ refs: options.refs || new Map(),
86
+ };
87
+ }
80
88
 
81
- protected markRef(id: number): void {
82
- this.marked.add(id);
83
- }
89
+ /**
90
+ * Ensures that the value (based on an identifier) has been visited by the parser.
91
+ * @param ctx
92
+ * @param id
93
+ */
94
+ export function markParserRef(ctx: BaseParserContext, id: number): void {
95
+ ctx.marked.add(id);
96
+ }
84
97
 
85
- protected isMarked(id: number): boolean {
86
- return this.marked.has(id);
87
- }
98
+ export function isParserRefMarked(ctx: BaseParserContext, id: number): boolean {
99
+ return ctx.marked.has(id);
100
+ }
88
101
 
89
- protected createIndex<T>(current: T): number {
90
- const id = this.refs.size;
91
- this.refs.set(current, id);
92
- return id;
93
- }
102
+ /**
103
+ * Creates an identifier for a value
104
+ * @param ctx
105
+ * @param current
106
+ */
107
+ export function createIndexForValue<T>(
108
+ ctx: BaseParserContext,
109
+ current: T,
110
+ ): number {
111
+ const id = ctx.refs.size;
112
+ ctx.refs.set(current, id);
113
+ return id;
114
+ }
94
115
 
95
- protected getIndexedValue<T>(current: T): FreshNode | IndexedNode {
96
- const registeredId = this.refs.get(current);
97
- if (registeredId != null) {
98
- this.markRef(registeredId);
99
- return {
100
- type: ParserNodeType.Indexed,
101
- value: createIndexedValueNode(registeredId),
102
- };
103
- }
116
+ export function getNodeForIndexedValue<T>(
117
+ ctx: BaseParserContext,
118
+ current: T,
119
+ ): FreshNode | IndexedNode {
120
+ const registeredId = ctx.refs.get(current);
121
+ if (registeredId != null) {
122
+ markParserRef(ctx, registeredId);
104
123
  return {
105
- type: ParserNodeType.Fresh,
106
- value: this.createIndex(current),
124
+ type: ParserNodeType.Indexed,
125
+ value: createIndexedValueNode(registeredId),
107
126
  };
108
127
  }
128
+ return {
129
+ type: ParserNodeType.Fresh,
130
+ value: createIndexForValue(ctx, current),
131
+ };
132
+ }
109
133
 
110
- protected getReference<T>(current: T): ObjectNode {
111
- const indexed = this.getIndexedValue(current);
112
- if (indexed.type === ParserNodeType.Indexed) {
113
- return indexed;
114
- }
115
- if (hasReferenceID(current)) {
116
- return {
117
- type: ParserNodeType.Referenced,
118
- value: createReferenceNode(indexed.value, current),
119
- };
120
- }
134
+ export function getReferenceNode<T>(
135
+ ctx: BaseParserContext,
136
+ current: T,
137
+ ): ObjectNode {
138
+ const indexed = getNodeForIndexedValue(ctx, current);
139
+ if (indexed.type === ParserNodeType.Indexed) {
121
140
  return indexed;
122
141
  }
142
+ // Special references are special ;)
143
+ if (hasReferenceID(current)) {
144
+ return {
145
+ type: ParserNodeType.Referenced,
146
+ value: createReferenceNode(indexed.value, current),
147
+ };
148
+ }
149
+ return indexed;
150
+ }
123
151
 
124
- protected parseWellKnownSymbol(
125
- current: symbol,
126
- ): SerovalIndexedValueNode | SerovalWKSymbolNode | SerovalReferenceNode {
127
- const ref = this.getReference(current);
128
- if (ref.type !== ParserNodeType.Fresh) {
129
- return ref.value;
130
- }
131
- assert(current in INV_SYMBOL_REF, new SerovalUnsupportedTypeError(current));
152
+ /**
153
+ * Parsing methods
154
+ */
155
+ export function parseWellKnownSymbol(
156
+ ctx: BaseParserContext,
157
+ current: symbol,
158
+ ): SerovalIndexedValueNode | SerovalWKSymbolNode | SerovalReferenceNode {
159
+ const ref = getReferenceNode(ctx, current);
160
+ if (ref.type !== ParserNodeType.Fresh) {
161
+ return ref.value;
162
+ }
163
+ if (current in INV_SYMBOL_REF) {
132
164
  return createWKSymbolNode(ref.value, current as WellKnownSymbols);
133
165
  }
166
+ throw new SerovalUnsupportedTypeError(current);
167
+ }
134
168
 
135
- protected parseSpecialReference(
136
- ref: SpecialReference,
137
- ): SerovalIndexedValueNode | SerovalSpecialReferenceNode {
138
- const result = this.getIndexedValue(SPECIAL_REFS[ref]);
139
- if (result.type === ParserNodeType.Indexed) {
140
- return result.value;
141
- }
142
- return createSerovalNode(
143
- SerovalNodeType.SpecialReference,
144
- result.value,
145
- ref,
146
- NIL,
147
- NIL,
148
- NIL,
149
- NIL,
150
- NIL,
151
- NIL,
152
- NIL,
153
- NIL,
154
- NIL,
155
- );
169
+ export function parseSpecialReference(
170
+ ctx: BaseParserContext,
171
+ ref: SpecialReference,
172
+ ): SerovalIndexedValueNode | SerovalSpecialReferenceNode {
173
+ const result = getNodeForIndexedValue(ctx, SPECIAL_REFS[ref]);
174
+ if (result.type === ParserNodeType.Indexed) {
175
+ return result.value;
156
176
  }
177
+ return createSerovalNode(
178
+ SerovalNodeType.SpecialReference,
179
+ result.value,
180
+ ref,
181
+ NIL,
182
+ NIL,
183
+ NIL,
184
+ NIL,
185
+ NIL,
186
+ NIL,
187
+ NIL,
188
+ NIL,
189
+ NIL,
190
+ );
191
+ }
157
192
 
158
- protected parseIteratorFactory():
159
- | SerovalIndexedValueNode
160
- | SerovalIteratorFactoryNode {
161
- const result = this.getIndexedValue(ITERATOR);
162
- if (result.type === ParserNodeType.Indexed) {
163
- return result.value;
164
- }
165
- return createSerovalNode(
166
- SerovalNodeType.IteratorFactory,
167
- result.value,
168
- NIL,
169
- NIL,
170
- NIL,
171
- NIL,
172
- NIL,
173
- NIL,
174
- NIL,
175
- this.parseWellKnownSymbol(Symbol.iterator),
176
- NIL,
177
- NIL,
178
- );
193
+ export function parseIteratorFactory(
194
+ ctx: BaseParserContext,
195
+ ): SerovalIndexedValueNode | SerovalIteratorFactoryNode {
196
+ const result = getNodeForIndexedValue(ctx, ITERATOR);
197
+ if (result.type === ParserNodeType.Indexed) {
198
+ return result.value;
179
199
  }
200
+ return createSerovalNode(
201
+ SerovalNodeType.IteratorFactory,
202
+ result.value,
203
+ NIL,
204
+ NIL,
205
+ NIL,
206
+ NIL,
207
+ NIL,
208
+ NIL,
209
+ NIL,
210
+ parseWellKnownSymbol(ctx, SYM_ITERATOR),
211
+ NIL,
212
+ NIL,
213
+ );
214
+ }
180
215
 
181
- protected parseAsyncIteratorFactory():
182
- | SerovalIndexedValueNode
183
- | SerovalAsyncIteratorFactoryNode {
184
- const result = this.getIndexedValue(ASYNC_ITERATOR);
185
- if (result.type === ParserNodeType.Indexed) {
186
- return result.value;
187
- }
188
- return createSerovalNode(
189
- SerovalNodeType.AsyncIteratorFactory,
190
- result.value,
191
- NIL,
192
- NIL,
193
- NIL,
194
- NIL,
195
- NIL,
196
- NIL,
197
- [
198
- this.parseSpecialReference(SpecialReference.PromiseConstructor),
199
- this.parseWellKnownSymbol(Symbol.asyncIterator),
200
- ],
201
- NIL,
202
- NIL,
203
- NIL,
204
- );
216
+ export function parseAsyncIteratorFactory(
217
+ ctx: BaseParserContext,
218
+ ): SerovalIndexedValueNode | SerovalAsyncIteratorFactoryNode {
219
+ const result = getNodeForIndexedValue(ctx, ASYNC_ITERATOR);
220
+ if (result.type === ParserNodeType.Indexed) {
221
+ return result.value;
205
222
  }
223
+ return createSerovalNode(
224
+ SerovalNodeType.AsyncIteratorFactory,
225
+ result.value,
226
+ NIL,
227
+ NIL,
228
+ NIL,
229
+ NIL,
230
+ NIL,
231
+ NIL,
232
+ [
233
+ parseSpecialReference(ctx, SpecialReference.PromiseConstructor),
234
+ parseWellKnownSymbol(ctx, SYM_ASYNC_ITERATOR),
235
+ ],
236
+ NIL,
237
+ NIL,
238
+ NIL,
239
+ );
240
+ }
206
241
 
207
- protected createObjectNode(
208
- id: number,
209
- current: Record<string, unknown>,
210
- empty: boolean,
211
- record: SerovalObjectRecordNode,
212
- ): SerovalObjectNode | SerovalNullConstructorNode {
213
- return createSerovalNode(
214
- empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
215
- id,
216
- NIL,
217
- NIL,
218
- NIL,
219
- NIL,
220
- record,
221
- NIL,
222
- NIL,
223
- NIL,
224
- NIL,
225
- getObjectFlag(current),
226
- );
227
- }
242
+ export function createObjectNode(
243
+ id: number,
244
+ current: Record<string, unknown>,
245
+ empty: boolean,
246
+ record: SerovalObjectRecordNode,
247
+ ): SerovalObjectNode | SerovalNullConstructorNode {
248
+ return createSerovalNode(
249
+ empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
250
+ id,
251
+ NIL,
252
+ NIL,
253
+ NIL,
254
+ NIL,
255
+ record,
256
+ NIL,
257
+ NIL,
258
+ NIL,
259
+ NIL,
260
+ getObjectFlag(current),
261
+ );
262
+ }
228
263
 
229
- protected createMapNode(
230
- id: number,
231
- k: SerovalNode[],
232
- v: SerovalNode[],
233
- s: number,
234
- ): SerovalMapNode {
235
- return createSerovalNode(
236
- SerovalNodeType.Map,
237
- id,
238
- NIL,
239
- NIL,
240
- NIL,
241
- NIL,
242
- NIL,
243
- { k, v, s },
244
- NIL,
245
- this.parseSpecialReference(SpecialReference.MapSentinel),
246
- NIL,
247
- NIL,
248
- );
249
- }
264
+ export function createMapNode(
265
+ ctx: BaseParserContext,
266
+ id: number,
267
+ k: SerovalNode[],
268
+ v: SerovalNode[],
269
+ s: number,
270
+ ): SerovalMapNode {
271
+ return createSerovalNode(
272
+ SerovalNodeType.Map,
273
+ id,
274
+ NIL,
275
+ NIL,
276
+ NIL,
277
+ NIL,
278
+ NIL,
279
+ { k, v, s },
280
+ NIL,
281
+ parseSpecialReference(ctx, SpecialReference.MapSentinel),
282
+ NIL,
283
+ NIL,
284
+ );
285
+ }
286
+
287
+ export function createPromiseConstructorNode(
288
+ ctx: BaseParserContext,
289
+ id: number,
290
+ resolver: number,
291
+ ): SerovalPromiseConstructorNode {
292
+ return createSerovalNode(
293
+ SerovalNodeType.PromiseConstructor,
294
+ id,
295
+ resolver,
296
+ NIL,
297
+ NIL,
298
+ NIL,
299
+ NIL,
300
+ NIL,
301
+ NIL,
302
+ parseSpecialReference(ctx, SpecialReference.PromiseConstructor),
303
+ NIL,
304
+ NIL,
305
+ );
306
+ }
250
307
 
251
- protected createPromiseConstructorNode(
252
- id: number,
253
- resolver: number,
254
- ): SerovalPromiseConstructorNode {
255
- return createSerovalNode(
256
- SerovalNodeType.PromiseConstructor,
257
- id,
258
- resolver,
259
- NIL,
260
- NIL,
261
- NIL,
262
- NIL,
263
- NIL,
264
- NIL,
265
- this.parseSpecialReference(SpecialReference.PromiseConstructor),
266
- NIL,
267
- NIL,
268
- );
308
+ export function createArrayBufferNode(
309
+ ctx: BaseParserContext,
310
+ id: number,
311
+ current: ArrayBuffer,
312
+ ): SerovalArrayBufferNode {
313
+ const bytes = new Uint8Array(current);
314
+ const len = bytes.length;
315
+ let result = '';
316
+ for (let i = 0; i < len; i++) {
317
+ result += String.fromCharCode(bytes[i]);
269
318
  }
319
+ return createSerovalNode(
320
+ SerovalNodeType.ArrayBuffer,
321
+ id,
322
+ serializeString(btoa(result)),
323
+ len,
324
+ NIL,
325
+ NIL,
326
+ NIL,
327
+ NIL,
328
+ NIL,
329
+ parseSpecialReference(ctx, SpecialReference.ArrayBufferConstructor),
330
+ NIL,
331
+ NIL,
332
+ );
270
333
  }