seroval 1.3.2 → 1.4.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.
- package/dist/cjs/development/index.cjs +2817 -2700
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -17
- package/dist/esm/development/index.mjs +2817 -2700
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -17
- package/dist/types/core/base-primitives.d.ts +3 -4
- package/dist/types/core/base-primitives.d.ts.map +1 -1
- package/dist/types/core/compat.d.ts +3 -2
- package/dist/types/core/compat.d.ts.map +1 -1
- package/dist/types/core/constants.d.ts +2 -1
- package/dist/types/core/constants.d.ts.map +1 -1
- package/dist/types/core/constructors.d.ts +54 -0
- package/dist/types/core/constructors.d.ts.map +1 -0
- package/dist/types/core/context/async-parser.d.ts +20 -0
- package/dist/types/core/context/async-parser.d.ts.map +1 -0
- package/dist/types/core/context/deserializer.d.ts +40 -38
- package/dist/types/core/context/deserializer.d.ts.map +1 -1
- package/dist/types/core/context/parser.d.ts +34 -19
- package/dist/types/core/context/parser.d.ts.map +1 -1
- package/dist/types/core/context/serializer.d.ts +38 -99
- package/dist/types/core/context/serializer.d.ts.map +1 -1
- package/dist/types/core/context/sync-parser.d.ts +59 -0
- package/dist/types/core/context/sync-parser.d.ts.map +1 -0
- package/dist/types/core/cross/index.d.ts +12 -13
- 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/function-string.d.ts +2 -2
- package/dist/types/core/function-string.d.ts.map +1 -1
- package/dist/types/core/literals.d.ts.map +1 -1
- package/dist/types/core/node.d.ts +1 -1
- package/dist/types/core/node.d.ts.map +1 -1
- package/dist/types/core/plugin.d.ts +13 -11
- package/dist/types/core/plugin.d.ts.map +1 -1
- package/dist/types/core/reference.d.ts.map +1 -1
- package/dist/types/core/special-reference.d.ts +3 -2
- package/dist/types/core/special-reference.d.ts.map +1 -1
- package/dist/types/core/stream.d.ts +1 -2
- package/dist/types/core/stream.d.ts.map +1 -1
- package/dist/types/core/string.d.ts.map +1 -1
- package/dist/types/core/symbols.d.ts +14 -0
- package/dist/types/core/symbols.d.ts.map +1 -0
- package/dist/types/core/tree/index.d.ts +7 -3
- package/dist/types/core/tree/index.d.ts.map +1 -1
- package/dist/types/core/types.d.ts +4 -11
- package/dist/types/core/types.d.ts.map +1 -1
- package/dist/types/core/utils/iterator-to-sequence.d.ts.map +1 -1
- package/dist/types/index.d.ts +10 -5
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +18 -21
- package/dist/types/core/context/parser/async.d.ts +0 -24
- package/dist/types/core/context/parser/async.d.ts.map +0 -1
- package/dist/types/core/context/parser/stream.d.ts +0 -43
- package/dist/types/core/context/parser/stream.d.ts.map +0 -1
- package/dist/types/core/context/parser/sync.d.ts +0 -30
- package/dist/types/core/context/parser/sync.d.ts.map +0 -1
- package/dist/types/core/cross/async.d.ts +0 -8
- package/dist/types/core/cross/async.d.ts.map +0 -1
- package/dist/types/core/cross/deserializer.d.ts +0 -9
- package/dist/types/core/cross/deserializer.d.ts.map +0 -1
- package/dist/types/core/cross/parser.d.ts +0 -6
- package/dist/types/core/cross/parser.d.ts.map +0 -1
- package/dist/types/core/cross/serializer.d.ts +0 -16
- package/dist/types/core/cross/serializer.d.ts.map +0 -1
- package/dist/types/core/cross/stream.d.ts +0 -8
- package/dist/types/core/cross/stream.d.ts.map +0 -1
- package/dist/types/core/cross/sync.d.ts +0 -8
- package/dist/types/core/cross/sync.d.ts.map +0 -1
- package/dist/types/core/tree/async.d.ts +0 -8
- package/dist/types/core/tree/async.d.ts.map +0 -1
- package/dist/types/core/tree/deserializer.d.ts +0 -13
- package/dist/types/core/tree/deserializer.d.ts.map +0 -1
- package/dist/types/core/tree/serializer.d.ts +0 -29
- package/dist/types/core/tree/serializer.d.ts.map +0 -1
- package/dist/types/core/tree/sync.d.ts +0 -8
- package/dist/types/core/tree/sync.d.ts.map +0 -1
- package/dist/types/core/utils/assert.d.ts +0 -2
- package/dist/types/core/utils/assert.d.ts.map +0 -1
- package/dist/types/core/utils/deferred.d.ts +0 -7
- package/dist/types/core/utils/deferred.d.ts.map +0 -1
- package/src/core/Serializer.ts +0 -119
- package/src/core/base-primitives.ts +0 -542
- package/src/core/compat.ts +0 -20
- package/src/core/constants.ts +0 -185
- package/src/core/context/deserializer.ts +0 -456
- package/src/core/context/parser/async.ts +0 -495
- package/src/core/context/parser/stream.ts +0 -323
- package/src/core/context/parser/sync.ts +0 -404
- package/src/core/context/parser.ts +0 -270
- package/src/core/context/serializer.ts +0 -1180
- package/src/core/cross/async.ts +0 -9
- package/src/core/cross/deserializer.ts +0 -16
- package/src/core/cross/index.ts +0 -170
- package/src/core/cross/parser.ts +0 -7
- package/src/core/cross/serializer.ts +0 -72
- package/src/core/cross/stream.ts +0 -9
- package/src/core/cross/sync.ts +0 -9
- package/src/core/errors.ts +0 -102
- package/src/core/function-string.ts +0 -31
- package/src/core/keys.ts +0 -17
- package/src/core/literals.ts +0 -43
- package/src/core/node.ts +0 -40
- package/src/core/opaque-reference.ts +0 -9
- package/src/core/plugin.ts +0 -91
- package/src/core/reference.ts +0 -63
- package/src/core/special-reference.ts +0 -114
- package/src/core/stream.ts +0 -205
- package/src/core/string.ts +0 -84
- package/src/core/tree/async.ts +0 -9
- package/src/core/tree/deserializer.ts +0 -26
- package/src/core/tree/index.ts +0 -111
- package/src/core/tree/serializer.ts +0 -98
- package/src/core/tree/sync.ts +0 -9
- package/src/core/types.ts +0 -370
- package/src/core/utils/assert.ts +0 -5
- package/src/core/utils/deferred.ts +0 -22
- package/src/core/utils/error.ts +0 -73
- package/src/core/utils/get-identifier.ts +0 -18
- package/src/core/utils/get-object-flag.ts +0 -14
- package/src/core/utils/is-valid-identifier.ts +0 -12
- package/src/core/utils/iterator-to-sequence.ts +0 -66
- package/src/core/utils/promise-to-result.ts +0 -9
- package/src/core/utils/typed-array.ts +0 -56
- package/src/index.ts +0 -18
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createAsyncIteratorFactoryInstanceNode,
|
|
3
|
-
createIteratorFactoryInstanceNode,
|
|
4
|
-
createPluginNode,
|
|
5
|
-
createStreamConstructorNode,
|
|
6
|
-
createStreamNextNode,
|
|
7
|
-
createStreamReturnNode,
|
|
8
|
-
createStreamThrowNode,
|
|
9
|
-
createStringNode,
|
|
10
|
-
} from '../../base-primitives';
|
|
11
|
-
import { NIL, SerovalNodeType } from '../../constants';
|
|
12
|
-
import { FALSE_NODE, TRUE_NODE } from '../../literals';
|
|
13
|
-
import { createSerovalNode } from '../../node';
|
|
14
|
-
import { SpecialReference } from '../../special-reference';
|
|
15
|
-
import type { Stream } from '../../stream';
|
|
16
|
-
import { createStreamFromAsyncIterable } from '../../stream';
|
|
17
|
-
import { serializeString } from '../../string';
|
|
18
|
-
import type {
|
|
19
|
-
SerovalNode,
|
|
20
|
-
SerovalObjectRecordKey,
|
|
21
|
-
SerovalObjectRecordNode,
|
|
22
|
-
SerovalPluginNode,
|
|
23
|
-
SerovalPromiseConstructorNode,
|
|
24
|
-
} from '../../types';
|
|
25
|
-
import { iteratorToSequence } from '../../utils/iterator-to-sequence';
|
|
26
|
-
import type { BaseSyncParserContextOptions } from './sync';
|
|
27
|
-
import BaseSyncParserContext from './sync';
|
|
28
|
-
|
|
29
|
-
export interface BaseStreamParserContextOptions
|
|
30
|
-
extends BaseSyncParserContextOptions {
|
|
31
|
-
onParse: (node: SerovalNode, initial: boolean) => void;
|
|
32
|
-
onError?: (error: unknown) => void;
|
|
33
|
-
onDone?: () => void;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default abstract class BaseStreamParserContext extends BaseSyncParserContext {
|
|
37
|
-
// Life
|
|
38
|
-
private alive = true;
|
|
39
|
-
|
|
40
|
-
// Amount of pending promises/streams
|
|
41
|
-
private pending = 0;
|
|
42
|
-
|
|
43
|
-
private onParseCallback: (node: SerovalNode, initial: boolean) => void;
|
|
44
|
-
|
|
45
|
-
private onErrorCallback?: (error: unknown) => void;
|
|
46
|
-
|
|
47
|
-
private onDoneCallback?: () => void;
|
|
48
|
-
|
|
49
|
-
constructor(options: BaseStreamParserContextOptions) {
|
|
50
|
-
super(options);
|
|
51
|
-
this.onParseCallback = options.onParse;
|
|
52
|
-
this.onErrorCallback = options.onError;
|
|
53
|
-
this.onDoneCallback = options.onDone;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private initial = true;
|
|
57
|
-
|
|
58
|
-
private buffer: SerovalNode[] = [];
|
|
59
|
-
|
|
60
|
-
private onParseInternal(node: SerovalNode, initial: boolean): void {
|
|
61
|
-
try {
|
|
62
|
-
this.onParseCallback(node, initial);
|
|
63
|
-
} catch (error) {
|
|
64
|
-
this.onError(error);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private flush(): void {
|
|
69
|
-
for (let i = 0, len = this.buffer.length; i < len; i++) {
|
|
70
|
-
this.onParseInternal(this.buffer[i], false);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
onParse(node: SerovalNode): void {
|
|
75
|
-
if (this.initial) {
|
|
76
|
-
this.buffer.push(node);
|
|
77
|
-
} else {
|
|
78
|
-
this.onParseInternal(node, false);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
onError(error: unknown): void {
|
|
83
|
-
if (this.onErrorCallback) {
|
|
84
|
-
this.onErrorCallback(error);
|
|
85
|
-
} else {
|
|
86
|
-
throw error;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
private onDone(): void {
|
|
91
|
-
if (this.onDoneCallback) {
|
|
92
|
-
this.onDoneCallback();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
pushPendingState(): void {
|
|
97
|
-
this.pending++;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
popPendingState(): void {
|
|
101
|
-
if (--this.pending <= 0) {
|
|
102
|
-
this.onDone();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
protected parseProperties(
|
|
107
|
-
properties: Record<string | symbol, unknown>,
|
|
108
|
-
): SerovalObjectRecordNode {
|
|
109
|
-
const entries = Object.entries(properties);
|
|
110
|
-
const keyNodes: SerovalObjectRecordKey[] = [];
|
|
111
|
-
const valueNodes: SerovalNode[] = [];
|
|
112
|
-
for (let i = 0, len = entries.length; i < len; i++) {
|
|
113
|
-
keyNodes.push(serializeString(entries[i][0]));
|
|
114
|
-
valueNodes.push(this.parse(entries[i][1]));
|
|
115
|
-
}
|
|
116
|
-
// Check special properties, symbols in this case
|
|
117
|
-
let symbol = Symbol.iterator;
|
|
118
|
-
if (symbol in properties) {
|
|
119
|
-
keyNodes.push(this.parseWellKnownSymbol(symbol));
|
|
120
|
-
valueNodes.push(
|
|
121
|
-
createIteratorFactoryInstanceNode(
|
|
122
|
-
this.parseIteratorFactory(),
|
|
123
|
-
this.parse(
|
|
124
|
-
iteratorToSequence(properties as unknown as Iterable<unknown>),
|
|
125
|
-
),
|
|
126
|
-
),
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
symbol = Symbol.asyncIterator;
|
|
130
|
-
if (symbol in properties) {
|
|
131
|
-
keyNodes.push(this.parseWellKnownSymbol(symbol));
|
|
132
|
-
valueNodes.push(
|
|
133
|
-
createAsyncIteratorFactoryInstanceNode(
|
|
134
|
-
this.parseAsyncIteratorFactory(),
|
|
135
|
-
this.parse(
|
|
136
|
-
createStreamFromAsyncIterable(
|
|
137
|
-
properties as unknown as AsyncIterable<unknown>,
|
|
138
|
-
),
|
|
139
|
-
),
|
|
140
|
-
),
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
symbol = Symbol.toStringTag;
|
|
144
|
-
if (symbol in properties) {
|
|
145
|
-
keyNodes.push(this.parseWellKnownSymbol(symbol));
|
|
146
|
-
valueNodes.push(createStringNode(properties[symbol] as string));
|
|
147
|
-
}
|
|
148
|
-
symbol = Symbol.isConcatSpreadable;
|
|
149
|
-
if (symbol in properties) {
|
|
150
|
-
keyNodes.push(this.parseWellKnownSymbol(symbol));
|
|
151
|
-
valueNodes.push(properties[symbol] ? TRUE_NODE : FALSE_NODE);
|
|
152
|
-
}
|
|
153
|
-
return {
|
|
154
|
-
k: keyNodes,
|
|
155
|
-
v: valueNodes,
|
|
156
|
-
s: keyNodes.length,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
protected handlePromiseSuccess(id: number, data: unknown): void {
|
|
161
|
-
const parsed = this.parseWithError(data);
|
|
162
|
-
if (parsed) {
|
|
163
|
-
this.onParse(
|
|
164
|
-
createSerovalNode(
|
|
165
|
-
SerovalNodeType.PromiseSuccess,
|
|
166
|
-
id,
|
|
167
|
-
NIL,
|
|
168
|
-
NIL,
|
|
169
|
-
NIL,
|
|
170
|
-
NIL,
|
|
171
|
-
NIL,
|
|
172
|
-
NIL,
|
|
173
|
-
[this.parseSpecialReference(SpecialReference.PromiseSuccess), parsed],
|
|
174
|
-
NIL,
|
|
175
|
-
NIL,
|
|
176
|
-
NIL,
|
|
177
|
-
),
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
this.popPendingState();
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
protected handlePromiseFailure(id: number, data: unknown): void {
|
|
184
|
-
if (this.alive) {
|
|
185
|
-
const parsed = this.parseWithError(data);
|
|
186
|
-
if (parsed) {
|
|
187
|
-
this.onParse(
|
|
188
|
-
createSerovalNode(
|
|
189
|
-
SerovalNodeType.PromiseFailure,
|
|
190
|
-
id,
|
|
191
|
-
NIL,
|
|
192
|
-
NIL,
|
|
193
|
-
NIL,
|
|
194
|
-
NIL,
|
|
195
|
-
NIL,
|
|
196
|
-
NIL,
|
|
197
|
-
[
|
|
198
|
-
this.parseSpecialReference(SpecialReference.PromiseFailure),
|
|
199
|
-
parsed,
|
|
200
|
-
],
|
|
201
|
-
NIL,
|
|
202
|
-
NIL,
|
|
203
|
-
NIL,
|
|
204
|
-
),
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
this.popPendingState();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
protected parsePromise(
|
|
212
|
-
id: number,
|
|
213
|
-
current: Promise<unknown>,
|
|
214
|
-
): SerovalPromiseConstructorNode {
|
|
215
|
-
const resolver = this.createIndex({});
|
|
216
|
-
current.then(
|
|
217
|
-
this.handlePromiseSuccess.bind(this, resolver),
|
|
218
|
-
this.handlePromiseFailure.bind(this, resolver),
|
|
219
|
-
);
|
|
220
|
-
this.pushPendingState();
|
|
221
|
-
return this.createPromiseConstructorNode(id, resolver);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
protected parsePlugin(
|
|
225
|
-
id: number,
|
|
226
|
-
current: unknown,
|
|
227
|
-
): SerovalPluginNode | undefined {
|
|
228
|
-
const currentPlugins = this.plugins;
|
|
229
|
-
if (currentPlugins) {
|
|
230
|
-
for (let i = 0, len = currentPlugins.length; i < len; i++) {
|
|
231
|
-
const plugin = currentPlugins[i];
|
|
232
|
-
if (plugin.parse.stream && plugin.test(current)) {
|
|
233
|
-
return createPluginNode(
|
|
234
|
-
id,
|
|
235
|
-
plugin.tag,
|
|
236
|
-
plugin.parse.stream(current, this, {
|
|
237
|
-
id,
|
|
238
|
-
}),
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return NIL;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
protected parseStream(id: number, current: Stream<unknown>): SerovalNode {
|
|
247
|
-
const result = createStreamConstructorNode(
|
|
248
|
-
id,
|
|
249
|
-
this.parseSpecialReference(SpecialReference.StreamConstructor),
|
|
250
|
-
[],
|
|
251
|
-
);
|
|
252
|
-
this.pushPendingState();
|
|
253
|
-
current.on({
|
|
254
|
-
next: value => {
|
|
255
|
-
if (this.alive) {
|
|
256
|
-
const parsed = this.parseWithError(value);
|
|
257
|
-
if (parsed) {
|
|
258
|
-
this.onParse(createStreamNextNode(id, parsed));
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
},
|
|
262
|
-
throw: value => {
|
|
263
|
-
if (this.alive) {
|
|
264
|
-
const parsed = this.parseWithError(value);
|
|
265
|
-
if (parsed) {
|
|
266
|
-
this.onParse(createStreamThrowNode(id, parsed));
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
this.popPendingState();
|
|
270
|
-
},
|
|
271
|
-
return: value => {
|
|
272
|
-
if (this.alive) {
|
|
273
|
-
const parsed = this.parseWithError(value);
|
|
274
|
-
if (parsed) {
|
|
275
|
-
this.onParse(createStreamReturnNode(id, parsed));
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
this.popPendingState();
|
|
279
|
-
},
|
|
280
|
-
});
|
|
281
|
-
return result;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
parseWithError<T>(current: T): SerovalNode | undefined {
|
|
285
|
-
try {
|
|
286
|
-
return this.parse(current);
|
|
287
|
-
} catch (err) {
|
|
288
|
-
this.onError(err);
|
|
289
|
-
return NIL;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* @private
|
|
295
|
-
*/
|
|
296
|
-
start<T>(current: T): void {
|
|
297
|
-
const parsed = this.parseWithError(current);
|
|
298
|
-
if (parsed) {
|
|
299
|
-
this.onParseInternal(parsed, true);
|
|
300
|
-
this.initial = false;
|
|
301
|
-
this.flush();
|
|
302
|
-
|
|
303
|
-
// Check if there's any pending pushes
|
|
304
|
-
if (this.pending <= 0) {
|
|
305
|
-
this.destroy();
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* @private
|
|
312
|
-
*/
|
|
313
|
-
destroy(): void {
|
|
314
|
-
if (this.alive) {
|
|
315
|
-
this.onDone();
|
|
316
|
-
this.alive = false;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
isAlive(): boolean {
|
|
321
|
-
return this.alive;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
@@ -1,404 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createAggregateErrorNode,
|
|
3
|
-
createArrayBufferNode,
|
|
4
|
-
createArrayNode,
|
|
5
|
-
createAsyncIteratorFactoryInstanceNode,
|
|
6
|
-
createBigIntNode,
|
|
7
|
-
createBigIntTypedArrayNode,
|
|
8
|
-
createBoxedNode,
|
|
9
|
-
createDataViewNode,
|
|
10
|
-
createDateNode,
|
|
11
|
-
createErrorNode,
|
|
12
|
-
createIteratorFactoryInstanceNode,
|
|
13
|
-
createNumberNode,
|
|
14
|
-
createPluginNode,
|
|
15
|
-
createRegExpNode,
|
|
16
|
-
createSetNode,
|
|
17
|
-
createStreamConstructorNode,
|
|
18
|
-
createStringNode,
|
|
19
|
-
createTypedArrayNode,
|
|
20
|
-
} from '../../base-primitives';
|
|
21
|
-
import { Feature } from '../../compat';
|
|
22
|
-
import { NIL } from '../../constants';
|
|
23
|
-
import { SerovalParserError, SerovalUnsupportedTypeError } from '../../errors';
|
|
24
|
-
import {
|
|
25
|
-
FALSE_NODE,
|
|
26
|
-
NULL_NODE,
|
|
27
|
-
TRUE_NODE,
|
|
28
|
-
UNDEFINED_NODE,
|
|
29
|
-
} from '../../literals';
|
|
30
|
-
import { OpaqueReference } from '../../opaque-reference';
|
|
31
|
-
import { SpecialReference } from '../../special-reference';
|
|
32
|
-
import type { Stream } from '../../stream';
|
|
33
|
-
import { createStream, isStream } from '../../stream';
|
|
34
|
-
import { serializeString } from '../../string';
|
|
35
|
-
import type {
|
|
36
|
-
SerovalAggregateErrorNode,
|
|
37
|
-
SerovalArrayNode,
|
|
38
|
-
SerovalBigIntTypedArrayNode,
|
|
39
|
-
SerovalBoxedNode,
|
|
40
|
-
SerovalDataViewNode,
|
|
41
|
-
SerovalErrorNode,
|
|
42
|
-
SerovalMapNode,
|
|
43
|
-
SerovalNode,
|
|
44
|
-
SerovalNullConstructorNode,
|
|
45
|
-
SerovalObjectNode,
|
|
46
|
-
SerovalObjectRecordKey,
|
|
47
|
-
SerovalObjectRecordNode,
|
|
48
|
-
SerovalPluginNode,
|
|
49
|
-
SerovalPromiseConstructorNode,
|
|
50
|
-
SerovalSetNode,
|
|
51
|
-
SerovalTypedArrayNode,
|
|
52
|
-
} from '../../types';
|
|
53
|
-
import { getErrorOptions } from '../../utils/error';
|
|
54
|
-
import { iteratorToSequence } from '../../utils/iterator-to-sequence';
|
|
55
|
-
import type {
|
|
56
|
-
BigIntTypedArrayValue,
|
|
57
|
-
TypedArrayValue,
|
|
58
|
-
} from '../../utils/typed-array';
|
|
59
|
-
import type { BaseParserContextOptions } from '../parser';
|
|
60
|
-
import { BaseParserContext, ParserNodeType } from '../parser';
|
|
61
|
-
|
|
62
|
-
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
|
|
63
|
-
|
|
64
|
-
export type BaseSyncParserContextOptions = BaseParserContextOptions;
|
|
65
|
-
|
|
66
|
-
export default abstract class BaseSyncParserContext extends BaseParserContext {
|
|
67
|
-
protected parseItems(current: unknown[]): SerovalNode[] {
|
|
68
|
-
const nodes = [];
|
|
69
|
-
for (let i = 0, len = current.length; i < len; i++) {
|
|
70
|
-
if (i in current) {
|
|
71
|
-
nodes[i] = this.parse(current[i]);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return nodes;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
protected parseArray(id: number, current: unknown[]): SerovalArrayNode {
|
|
78
|
-
return createArrayNode(id, current, this.parseItems(current));
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
protected parseProperties(
|
|
82
|
-
properties: Record<string | symbol, unknown>,
|
|
83
|
-
): SerovalObjectRecordNode {
|
|
84
|
-
const entries = Object.entries(properties);
|
|
85
|
-
const keyNodes: SerovalObjectRecordKey[] = [];
|
|
86
|
-
const valueNodes: SerovalNode[] = [];
|
|
87
|
-
for (let i = 0, len = entries.length; i < len; i++) {
|
|
88
|
-
keyNodes.push(serializeString(entries[i][0]));
|
|
89
|
-
valueNodes.push(this.parse(entries[i][1]));
|
|
90
|
-
}
|
|
91
|
-
// Check special properties, symbols in this case
|
|
92
|
-
let symbol = Symbol.iterator;
|
|
93
|
-
if (symbol in properties) {
|
|
94
|
-
keyNodes.push(this.parseWellKnownSymbol(symbol));
|
|
95
|
-
valueNodes.push(
|
|
96
|
-
createIteratorFactoryInstanceNode(
|
|
97
|
-
this.parseIteratorFactory(),
|
|
98
|
-
this.parse(
|
|
99
|
-
iteratorToSequence(properties as unknown as Iterable<unknown>),
|
|
100
|
-
),
|
|
101
|
-
),
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
symbol = Symbol.asyncIterator;
|
|
105
|
-
if (symbol in properties) {
|
|
106
|
-
keyNodes.push(this.parseWellKnownSymbol(symbol));
|
|
107
|
-
valueNodes.push(
|
|
108
|
-
createAsyncIteratorFactoryInstanceNode(
|
|
109
|
-
this.parseAsyncIteratorFactory(),
|
|
110
|
-
this.parse(createStream()),
|
|
111
|
-
),
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
symbol = Symbol.toStringTag;
|
|
115
|
-
if (symbol in properties) {
|
|
116
|
-
keyNodes.push(this.parseWellKnownSymbol(symbol));
|
|
117
|
-
valueNodes.push(createStringNode(properties[symbol] as string));
|
|
118
|
-
}
|
|
119
|
-
symbol = Symbol.isConcatSpreadable;
|
|
120
|
-
if (symbol in properties) {
|
|
121
|
-
keyNodes.push(this.parseWellKnownSymbol(symbol));
|
|
122
|
-
valueNodes.push(properties[symbol] ? TRUE_NODE : FALSE_NODE);
|
|
123
|
-
}
|
|
124
|
-
return {
|
|
125
|
-
k: keyNodes,
|
|
126
|
-
v: valueNodes,
|
|
127
|
-
s: keyNodes.length,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
protected parsePlainObject(
|
|
132
|
-
id: number,
|
|
133
|
-
current: Record<string, unknown>,
|
|
134
|
-
empty: boolean,
|
|
135
|
-
): ObjectLikeNode {
|
|
136
|
-
return this.createObjectNode(
|
|
137
|
-
id,
|
|
138
|
-
current,
|
|
139
|
-
empty,
|
|
140
|
-
this.parseProperties(current),
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
protected parseBoxed(id: number, current: object): SerovalBoxedNode {
|
|
145
|
-
return createBoxedNode(id, this.parse(current.valueOf()));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
protected parseTypedArray(
|
|
149
|
-
id: number,
|
|
150
|
-
current: TypedArrayValue,
|
|
151
|
-
): SerovalTypedArrayNode {
|
|
152
|
-
return createTypedArrayNode(id, current, this.parse(current.buffer));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
protected parseBigIntTypedArray(
|
|
156
|
-
id: number,
|
|
157
|
-
current: BigIntTypedArrayValue,
|
|
158
|
-
): SerovalBigIntTypedArrayNode {
|
|
159
|
-
return createBigIntTypedArrayNode(id, current, this.parse(current.buffer));
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
protected parseDataView(id: number, current: DataView): SerovalDataViewNode {
|
|
163
|
-
return createDataViewNode(id, current, this.parse(current.buffer));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
protected parseError(id: number, current: Error): SerovalErrorNode {
|
|
167
|
-
const options = getErrorOptions(current, this.features);
|
|
168
|
-
return createErrorNode(
|
|
169
|
-
id,
|
|
170
|
-
current,
|
|
171
|
-
options ? this.parseProperties(options) : NIL,
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
protected parseAggregateError(
|
|
176
|
-
id: number,
|
|
177
|
-
current: AggregateError,
|
|
178
|
-
): SerovalAggregateErrorNode {
|
|
179
|
-
const options = getErrorOptions(current, this.features);
|
|
180
|
-
return createAggregateErrorNode(
|
|
181
|
-
id,
|
|
182
|
-
current,
|
|
183
|
-
options ? this.parseProperties(options) : NIL,
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
protected parseMap(
|
|
188
|
-
id: number,
|
|
189
|
-
current: Map<unknown, unknown>,
|
|
190
|
-
): SerovalMapNode {
|
|
191
|
-
const keyNodes: SerovalNode[] = [];
|
|
192
|
-
const valueNodes: SerovalNode[] = [];
|
|
193
|
-
for (const [key, value] of current.entries()) {
|
|
194
|
-
keyNodes.push(this.parse(key));
|
|
195
|
-
valueNodes.push(this.parse(value));
|
|
196
|
-
}
|
|
197
|
-
return this.createMapNode(id, keyNodes, valueNodes, current.size);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
protected parseSet(id: number, current: Set<unknown>): SerovalSetNode {
|
|
201
|
-
const items: SerovalNode[] = [];
|
|
202
|
-
for (const item of current.keys()) {
|
|
203
|
-
items.push(this.parse(item));
|
|
204
|
-
}
|
|
205
|
-
return createSetNode(id, current.size, items);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
protected parsePlugin(
|
|
209
|
-
id: number,
|
|
210
|
-
current: unknown,
|
|
211
|
-
): SerovalPluginNode | undefined {
|
|
212
|
-
const currentPlugins = this.plugins;
|
|
213
|
-
if (currentPlugins) {
|
|
214
|
-
for (let i = 0, len = currentPlugins.length; i < len; i++) {
|
|
215
|
-
const plugin = currentPlugins[i];
|
|
216
|
-
if (plugin.parse.sync && plugin.test(current)) {
|
|
217
|
-
return createPluginNode(
|
|
218
|
-
id,
|
|
219
|
-
plugin.tag,
|
|
220
|
-
plugin.parse.sync(current, this, {
|
|
221
|
-
id,
|
|
222
|
-
}),
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
protected parseStream(id: number, _current: Stream<unknown>): SerovalNode {
|
|
231
|
-
return createStreamConstructorNode(
|
|
232
|
-
id,
|
|
233
|
-
this.parseSpecialReference(SpecialReference.StreamConstructor),
|
|
234
|
-
[],
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
protected parsePromise(
|
|
239
|
-
id: number,
|
|
240
|
-
_current: Promise<unknown>,
|
|
241
|
-
): SerovalPromiseConstructorNode {
|
|
242
|
-
return this.createPromiseConstructorNode(id, this.createIndex({}));
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: ehh
|
|
246
|
-
protected parseObject(id: number, current: object): SerovalNode {
|
|
247
|
-
if (Array.isArray(current)) {
|
|
248
|
-
return this.parseArray(id, current);
|
|
249
|
-
}
|
|
250
|
-
if (isStream(current)) {
|
|
251
|
-
return this.parseStream(id, current);
|
|
252
|
-
}
|
|
253
|
-
const currentClass = current.constructor;
|
|
254
|
-
if (currentClass === OpaqueReference) {
|
|
255
|
-
return this.parse(
|
|
256
|
-
(current as OpaqueReference<unknown, unknown>).replacement,
|
|
257
|
-
);
|
|
258
|
-
}
|
|
259
|
-
const parsed = this.parsePlugin(id, current);
|
|
260
|
-
if (parsed) {
|
|
261
|
-
return parsed;
|
|
262
|
-
}
|
|
263
|
-
switch (currentClass) {
|
|
264
|
-
case Object:
|
|
265
|
-
return this.parsePlainObject(
|
|
266
|
-
id,
|
|
267
|
-
current as Record<string, unknown>,
|
|
268
|
-
false,
|
|
269
|
-
);
|
|
270
|
-
case undefined:
|
|
271
|
-
return this.parsePlainObject(
|
|
272
|
-
id,
|
|
273
|
-
current as Record<string, unknown>,
|
|
274
|
-
true,
|
|
275
|
-
);
|
|
276
|
-
case Date:
|
|
277
|
-
return createDateNode(id, current as unknown as Date);
|
|
278
|
-
case RegExp:
|
|
279
|
-
return createRegExpNode(id, current as unknown as RegExp);
|
|
280
|
-
case Error:
|
|
281
|
-
case EvalError:
|
|
282
|
-
case RangeError:
|
|
283
|
-
case ReferenceError:
|
|
284
|
-
case SyntaxError:
|
|
285
|
-
case TypeError:
|
|
286
|
-
case URIError:
|
|
287
|
-
return this.parseError(id, current as unknown as Error);
|
|
288
|
-
case Number:
|
|
289
|
-
case Boolean:
|
|
290
|
-
case String:
|
|
291
|
-
case BigInt:
|
|
292
|
-
return this.parseBoxed(id, current);
|
|
293
|
-
case ArrayBuffer:
|
|
294
|
-
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
295
|
-
case Int8Array:
|
|
296
|
-
case Int16Array:
|
|
297
|
-
case Int32Array:
|
|
298
|
-
case Uint8Array:
|
|
299
|
-
case Uint16Array:
|
|
300
|
-
case Uint32Array:
|
|
301
|
-
case Uint8ClampedArray:
|
|
302
|
-
case Float32Array:
|
|
303
|
-
case Float64Array:
|
|
304
|
-
return this.parseTypedArray(id, current as unknown as TypedArrayValue);
|
|
305
|
-
case DataView:
|
|
306
|
-
return this.parseDataView(id, current as unknown as DataView);
|
|
307
|
-
case Map:
|
|
308
|
-
return this.parseMap(id, current as unknown as Map<unknown, unknown>);
|
|
309
|
-
case Set:
|
|
310
|
-
return this.parseSet(id, current as unknown as Set<unknown>);
|
|
311
|
-
default:
|
|
312
|
-
break;
|
|
313
|
-
}
|
|
314
|
-
// Promises
|
|
315
|
-
if (currentClass === Promise || current instanceof Promise) {
|
|
316
|
-
return this.parsePromise(id, current as unknown as Promise<unknown>);
|
|
317
|
-
}
|
|
318
|
-
const currentFeatures = this.features;
|
|
319
|
-
// BigInt Typed Arrays
|
|
320
|
-
if (currentFeatures & Feature.BigIntTypedArray) {
|
|
321
|
-
switch (currentClass) {
|
|
322
|
-
case BigInt64Array:
|
|
323
|
-
case BigUint64Array:
|
|
324
|
-
return this.parseBigIntTypedArray(
|
|
325
|
-
id,
|
|
326
|
-
current as unknown as BigIntTypedArrayValue,
|
|
327
|
-
);
|
|
328
|
-
default:
|
|
329
|
-
break;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
if (
|
|
333
|
-
currentFeatures & Feature.AggregateError &&
|
|
334
|
-
typeof AggregateError !== 'undefined' &&
|
|
335
|
-
(currentClass === AggregateError || current instanceof AggregateError)
|
|
336
|
-
) {
|
|
337
|
-
return this.parseAggregateError(id, current as unknown as AggregateError);
|
|
338
|
-
}
|
|
339
|
-
// Slow path. We only need to handle Errors and Iterators
|
|
340
|
-
// since they have very broad implementations.
|
|
341
|
-
if (current instanceof Error) {
|
|
342
|
-
return this.parseError(id, current);
|
|
343
|
-
}
|
|
344
|
-
// Generator functions don't have a global constructor
|
|
345
|
-
// despite existing
|
|
346
|
-
if (Symbol.iterator in current || Symbol.asyncIterator in current) {
|
|
347
|
-
return this.parsePlainObject(id, current, !!currentClass);
|
|
348
|
-
}
|
|
349
|
-
throw new SerovalUnsupportedTypeError(current);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
protected parseFunction(current: unknown): SerovalNode {
|
|
353
|
-
const ref = this.getReference(current);
|
|
354
|
-
if (ref.type !== ParserNodeType.Fresh) {
|
|
355
|
-
return ref.value;
|
|
356
|
-
}
|
|
357
|
-
const plugin = this.parsePlugin(ref.value, current);
|
|
358
|
-
if (plugin) {
|
|
359
|
-
return plugin;
|
|
360
|
-
}
|
|
361
|
-
throw new SerovalUnsupportedTypeError(current);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
parse<T>(current: T): SerovalNode {
|
|
365
|
-
switch (typeof current) {
|
|
366
|
-
case 'boolean':
|
|
367
|
-
return current ? TRUE_NODE : FALSE_NODE;
|
|
368
|
-
case 'undefined':
|
|
369
|
-
return UNDEFINED_NODE;
|
|
370
|
-
case 'string':
|
|
371
|
-
return createStringNode(current as string);
|
|
372
|
-
case 'number':
|
|
373
|
-
return createNumberNode(current as number);
|
|
374
|
-
case 'bigint':
|
|
375
|
-
return createBigIntNode(current as bigint);
|
|
376
|
-
case 'object': {
|
|
377
|
-
if (current) {
|
|
378
|
-
const ref = this.getReference(current);
|
|
379
|
-
return ref.type === ParserNodeType.Fresh
|
|
380
|
-
? this.parseObject(ref.value, current as object)
|
|
381
|
-
: ref.value;
|
|
382
|
-
}
|
|
383
|
-
return NULL_NODE;
|
|
384
|
-
}
|
|
385
|
-
case 'symbol':
|
|
386
|
-
return this.parseWellKnownSymbol(current);
|
|
387
|
-
case 'function': {
|
|
388
|
-
return this.parseFunction(current);
|
|
389
|
-
}
|
|
390
|
-
default:
|
|
391
|
-
throw new SerovalUnsupportedTypeError(current);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
parseTop<T>(current: T): SerovalNode {
|
|
396
|
-
try {
|
|
397
|
-
return this.parse(current);
|
|
398
|
-
} catch (error) {
|
|
399
|
-
throw error instanceof SerovalParserError
|
|
400
|
-
? error
|
|
401
|
-
: new SerovalParserError(error);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|