seroval 0.11.6 → 0.12.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.
- package/README.md +29 -16
- package/dist/cjs/development/index.cjs +3072 -4875
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +3069 -4874
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/core/Serializer.d.ts +2 -0
- package/dist/types/core/Serializer.d.ts.map +1 -0
- package/dist/types/core/UnsupportedTypeError.d.ts +1 -0
- package/dist/types/core/UnsupportedTypeError.d.ts.map +1 -0
- package/dist/types/core/assert.d.ts +1 -0
- package/dist/types/core/assert.d.ts.map +1 -0
- package/dist/types/core/base/async.d.ts +30 -0
- package/dist/types/core/base/async.d.ts.map +1 -0
- package/dist/types/core/base/stream.d.ts +40 -0
- package/dist/types/core/base/stream.d.ts.map +1 -0
- package/dist/types/core/base/sync.d.ts +32 -0
- package/dist/types/core/base/sync.d.ts.map +1 -0
- package/dist/types/core/base-primitives.d.ts +3 -1
- package/dist/types/core/base-primitives.d.ts.map +1 -0
- package/dist/types/core/compat.d.ts +1 -0
- package/dist/types/core/compat.d.ts.map +1 -0
- package/dist/types/core/constants.d.ts +19 -4
- package/dist/types/core/constants.d.ts.map +1 -0
- package/dist/types/core/constructors.d.ts +1 -0
- package/dist/types/core/constructors.d.ts.map +1 -0
- package/dist/types/core/cross/async.d.ts +8 -3
- package/dist/types/core/cross/async.d.ts.map +1 -0
- package/dist/types/core/cross/cross-parser.d.ts +8 -0
- package/dist/types/core/cross/cross-parser.d.ts.map +1 -0
- package/dist/types/core/cross/index.d.ts +12 -5
- package/dist/types/core/cross/index.d.ts.map +1 -0
- package/dist/types/core/cross/serialize.d.ts +23 -5
- package/dist/types/core/cross/serialize.d.ts.map +1 -0
- package/dist/types/core/cross/stream.d.ts +8 -3
- package/dist/types/core/cross/stream.d.ts.map +1 -0
- package/dist/types/core/cross/sync.d.ts +8 -3
- package/dist/types/core/cross/sync.d.ts.map +1 -0
- package/dist/types/core/get-identifier.d.ts +1 -0
- package/dist/types/core/get-identifier.d.ts.map +1 -0
- package/dist/types/core/keys.d.ts +1 -0
- package/dist/types/core/keys.d.ts.map +1 -0
- package/dist/types/core/literals.d.ts +1 -0
- package/dist/types/core/literals.d.ts.map +1 -0
- package/dist/types/core/parser-context.d.ts +23 -0
- package/dist/types/core/parser-context.d.ts.map +1 -0
- package/dist/types/core/plugin.d.ts +26 -0
- package/dist/types/core/plugin.d.ts.map +1 -0
- package/dist/types/core/promise-to-result.d.ts +1 -0
- package/dist/types/core/promise-to-result.d.ts.map +1 -0
- package/dist/types/core/reference.d.ts +1 -0
- package/dist/types/core/reference.d.ts.map +1 -0
- package/dist/types/core/serializer-context.old.d.ts +165 -0
- package/dist/types/core/serializer-context.old.d.ts.map +1 -0
- package/dist/types/core/shared.d.ts +4 -7
- package/dist/types/core/shared.d.ts.map +1 -0
- package/dist/types/core/string.d.ts +1 -0
- package/dist/types/core/string.d.ts.map +1 -0
- package/dist/types/core/tree/async.d.ts +8 -3
- package/dist/types/core/tree/async.d.ts.map +1 -0
- package/dist/types/core/tree/deserialize.d.ts +49 -2
- package/dist/types/core/tree/deserialize.d.ts.map +1 -0
- package/dist/types/core/tree/index.d.ts +10 -7
- package/dist/types/core/tree/index.d.ts.map +1 -0
- package/dist/types/core/tree/serialize.d.ts +37 -4
- package/dist/types/core/tree/serialize.d.ts.map +1 -0
- package/dist/types/core/tree/sync.d.ts +8 -3
- package/dist/types/core/tree/sync.d.ts.map +1 -0
- package/dist/types/core/types.d.ts +10 -3
- package/dist/types/core/types.d.ts.map +1 -0
- package/dist/types/core/web-api.d.ts +1 -0
- package/dist/types/core/web-api.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/types.d.ts +1 -0
- package/dist/types/types.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/core/Serializer.ts +2 -0
- package/src/core/base/async.ts +804 -0
- package/src/core/base/stream.ts +496 -0
- package/src/core/base/sync.ts +675 -0
- package/src/core/base-primitives.ts +22 -0
- package/src/core/constants.ts +61 -45
- package/src/core/cross/async.ts +6 -751
- package/src/core/cross/cross-parser.ts +9 -0
- package/src/core/cross/index.ts +62 -84
- package/src/core/cross/serialize.ts +71 -862
- package/src/core/cross/stream.ts +6 -873
- package/src/core/cross/sync.ts +6 -624
- package/src/core/is-serializable.new.ts +208 -0
- package/src/core/keys.ts +1 -1
- package/src/core/parser-context.ts +131 -0
- package/src/core/plugin.ts +55 -0
- package/src/core/serializer-context.new.ts +1168 -0
- package/src/core/serializer-context.old.ts +1126 -0
- package/src/core/shared.ts +46 -123
- package/src/core/tree/async.ts +6 -750
- package/src/core/tree/deserialize.ts +423 -420
- package/src/core/tree/index.ts +49 -91
- package/src/core/tree/parser.ts +45 -0
- package/src/core/tree/serialize.ts +122 -828
- package/src/core/tree/sync.ts +6 -624
- package/src/core/types.ts +13 -2
- package/src/example.ts +28 -0
- package/src/index.ts +3 -0
- package/dist/types/core/assignments.d.ts +0 -33
- package/dist/types/core/context.d.ts +0 -9
- package/dist/types/core/cross/context.d.ts +0 -37
- package/dist/types/core/cross/primitives.d.ts +0 -9
- package/dist/types/core/cross/web-api.d.ts +0 -4
- package/dist/types/core/tree/context.d.ts +0 -44
- package/dist/types/core/tree/primitives.d.ts +0 -9
- package/dist/types/core/tree/web-api.d.ts +0 -4
- package/src/core/assignments.ts +0 -159
- package/src/core/context.ts +0 -15
- package/src/core/cross/context.ts +0 -102
- package/src/core/cross/primitives.ts +0 -128
- package/src/core/cross/web-api.ts +0 -50
- package/src/core/tree/context.ts +0 -125
- package/src/core/tree/primitives.ts +0 -123
- package/src/core/tree/web-api.ts +0 -50
package/src/core/tree/sync.ts
CHANGED
|
@@ -1,627 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import type {
|
|
4
|
-
import { createIndexedValue } from './context';
|
|
5
|
-
import { serializeString } from '../string';
|
|
6
|
-
import type { BigIntTypedArrayValue, TypedArrayValue } from '../../types';
|
|
7
|
-
import UnsupportedTypeError from '../UnsupportedTypeError';
|
|
8
|
-
import {
|
|
9
|
-
TRUE_NODE,
|
|
10
|
-
FALSE_NODE,
|
|
11
|
-
UNDEFINED_NODE,
|
|
12
|
-
NULL_NODE,
|
|
13
|
-
} from '../literals';
|
|
14
|
-
import {
|
|
15
|
-
createBigIntTypedArrayNode,
|
|
16
|
-
createTypedArrayNode,
|
|
17
|
-
createDataViewNode,
|
|
18
|
-
createSymbolNode,
|
|
19
|
-
createFunctionNode,
|
|
20
|
-
} from './primitives';
|
|
21
|
-
import {
|
|
22
|
-
hasReferenceID,
|
|
23
|
-
} from '../reference';
|
|
24
|
-
import {
|
|
25
|
-
getErrorConstructorName,
|
|
26
|
-
getErrorOptions,
|
|
27
|
-
getObjectFlag,
|
|
28
|
-
isIterable,
|
|
29
|
-
} from '../shared';
|
|
30
|
-
import type {
|
|
31
|
-
SerovalAggregateErrorNode,
|
|
32
|
-
SerovalArrayNode,
|
|
33
|
-
SerovalBoxedNode,
|
|
34
|
-
SerovalCustomEventNode,
|
|
35
|
-
SerovalErrorNode,
|
|
36
|
-
SerovalEventNode,
|
|
37
|
-
SerovalFormDataNode,
|
|
38
|
-
SerovalHeadersNode,
|
|
39
|
-
SerovalMapNode,
|
|
40
|
-
SerovalNullConstructorNode,
|
|
41
|
-
SerovalObjectNode,
|
|
42
|
-
SerovalObjectRecordKey,
|
|
43
|
-
SerovalObjectRecordNode,
|
|
44
|
-
SerovalPlainRecordNode,
|
|
45
|
-
SerovalSetNode,
|
|
46
|
-
SerovalSyncNode,
|
|
47
|
-
} from '../types';
|
|
48
|
-
import {
|
|
49
|
-
SerovalObjectRecordSpecialKey,
|
|
50
|
-
} from '../types';
|
|
51
|
-
import { SerovalNodeType } from '../constants';
|
|
52
|
-
import {
|
|
53
|
-
createArrayBufferNode,
|
|
54
|
-
createBigIntNode,
|
|
55
|
-
createDateNode,
|
|
56
|
-
createIndexedValueNode,
|
|
57
|
-
createNumberNode,
|
|
58
|
-
createReferenceNode,
|
|
59
|
-
createRegExpNode,
|
|
60
|
-
createStringNode,
|
|
61
|
-
} from '../base-primitives';
|
|
62
|
-
import { createDOMExceptionNode, createURLNode, createURLSearchParamsNode } from '../web-api';
|
|
63
|
-
import { createCustomEventOptions, createEventOptions } from '../constructors';
|
|
1
|
+
import BaseSyncParserContext from '../base/sync';
|
|
2
|
+
import type { BaseParserContextOptions } from '../parser-context';
|
|
3
|
+
import type { SerovalMode } from '../plugin';
|
|
64
4
|
|
|
65
|
-
type
|
|
5
|
+
export type SyncParserContextOptions = Omit<BaseParserContextOptions, 'refs'>;
|
|
66
6
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const nodes = new Array<SerovalSyncNode>(size);
|
|
70
|
-
const deferred = new Array<unknown>(size);
|
|
71
|
-
let item: unknown;
|
|
72
|
-
for (let i = 0; i < size; i++) {
|
|
73
|
-
if (i in current) {
|
|
74
|
-
item = current[i];
|
|
75
|
-
if (isIterable(ctx, item)) {
|
|
76
|
-
deferred[i] = item;
|
|
77
|
-
} else {
|
|
78
|
-
nodes[i] = parseSync(ctx, item);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
for (let i = 0; i < size; i++) {
|
|
83
|
-
if (i in deferred) {
|
|
84
|
-
nodes[i] = parseSync(ctx, deferred[i]);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return nodes;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function generateArrayNode(
|
|
91
|
-
ctx: ParserContext,
|
|
92
|
-
id: number,
|
|
93
|
-
current: unknown[],
|
|
94
|
-
): SerovalArrayNode {
|
|
95
|
-
return {
|
|
96
|
-
t: SerovalNodeType.Array,
|
|
97
|
-
i: id,
|
|
98
|
-
s: undefined,
|
|
99
|
-
l: current.length,
|
|
100
|
-
c: undefined,
|
|
101
|
-
m: undefined,
|
|
102
|
-
p: undefined,
|
|
103
|
-
e: undefined,
|
|
104
|
-
a: generateNodeList(ctx, current),
|
|
105
|
-
f: undefined,
|
|
106
|
-
b: undefined,
|
|
107
|
-
o: getObjectFlag(current),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function generateMapNode(
|
|
112
|
-
ctx: ParserContext,
|
|
113
|
-
id: number,
|
|
114
|
-
current: Map<unknown, unknown>,
|
|
115
|
-
): SerovalMapNode {
|
|
116
|
-
const len = current.size;
|
|
117
|
-
const keyNodes = new Array<SerovalSyncNode>(len);
|
|
118
|
-
const valueNodes = new Array<SerovalSyncNode>(len);
|
|
119
|
-
const deferredKey = new Array<unknown>(len);
|
|
120
|
-
const deferredValue = new Array<unknown>(len);
|
|
121
|
-
let deferredSize = 0;
|
|
122
|
-
let nodeSize = 0;
|
|
123
|
-
for (const [key, value] of current.entries()) {
|
|
124
|
-
// Either key or value might be an iterable
|
|
125
|
-
if (isIterable(ctx, key) || isIterable(ctx, value)) {
|
|
126
|
-
deferredKey[deferredSize] = key;
|
|
127
|
-
deferredValue[deferredSize] = value;
|
|
128
|
-
deferredSize++;
|
|
129
|
-
} else {
|
|
130
|
-
keyNodes[nodeSize] = parseSync(ctx, key);
|
|
131
|
-
valueNodes[nodeSize] = parseSync(ctx, value);
|
|
132
|
-
nodeSize++;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
for (let i = 0; i < deferredSize; i++) {
|
|
136
|
-
keyNodes[nodeSize + i] = parseSync(ctx, deferredKey[i]);
|
|
137
|
-
valueNodes[nodeSize + i] = parseSync(ctx, deferredValue[i]);
|
|
138
|
-
}
|
|
139
|
-
return {
|
|
140
|
-
t: SerovalNodeType.Map,
|
|
141
|
-
i: id,
|
|
142
|
-
s: undefined,
|
|
143
|
-
l: undefined,
|
|
144
|
-
c: undefined,
|
|
145
|
-
m: undefined,
|
|
146
|
-
p: undefined,
|
|
147
|
-
e: { k: keyNodes, v: valueNodes, s: len },
|
|
148
|
-
a: undefined,
|
|
149
|
-
f: undefined,
|
|
150
|
-
b: undefined,
|
|
151
|
-
o: undefined,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function generateSetNode(
|
|
156
|
-
ctx: ParserContext,
|
|
157
|
-
id: number,
|
|
158
|
-
current: Set<unknown>,
|
|
159
|
-
): SerovalSetNode {
|
|
160
|
-
const len = current.size;
|
|
161
|
-
const nodes = new Array<SerovalSyncNode>(len);
|
|
162
|
-
const deferred = new Array<unknown>(len);
|
|
163
|
-
let deferredSize = 0;
|
|
164
|
-
let nodeSize = 0;
|
|
165
|
-
for (const item of current.keys()) {
|
|
166
|
-
// Iterables are lazy, so the evaluation must be deferred
|
|
167
|
-
if (isIterable(ctx, item)) {
|
|
168
|
-
deferred[deferredSize++] = item;
|
|
169
|
-
} else {
|
|
170
|
-
nodes[nodeSize++] = parseSync(ctx, item);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// Parse deferred items
|
|
174
|
-
for (let i = 0; i < deferredSize; i++) {
|
|
175
|
-
nodes[nodeSize + i] = parseSync(ctx, deferred[i]);
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
t: SerovalNodeType.Set,
|
|
179
|
-
i: id,
|
|
180
|
-
s: undefined,
|
|
181
|
-
l: len,
|
|
182
|
-
c: undefined,
|
|
183
|
-
m: undefined,
|
|
184
|
-
p: undefined,
|
|
185
|
-
e: undefined,
|
|
186
|
-
a: nodes,
|
|
187
|
-
f: undefined,
|
|
188
|
-
b: undefined,
|
|
189
|
-
o: undefined,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function generateProperties(
|
|
194
|
-
ctx: ParserContext,
|
|
195
|
-
properties: Record<string, unknown>,
|
|
196
|
-
): SerovalObjectRecordNode {
|
|
197
|
-
const keys = Object.keys(properties);
|
|
198
|
-
let size = keys.length;
|
|
199
|
-
const keyNodes = new Array<SerovalObjectRecordKey>(size);
|
|
200
|
-
const valueNodes = new Array<SerovalSyncNode>(size);
|
|
201
|
-
const deferredKeys = new Array<SerovalObjectRecordKey>(size);
|
|
202
|
-
const deferredValues = new Array<unknown>(size);
|
|
203
|
-
let deferredSize = 0;
|
|
204
|
-
let nodesSize = 0;
|
|
205
|
-
let item: unknown;
|
|
206
|
-
let escaped: SerovalObjectRecordKey;
|
|
207
|
-
for (const key of keys) {
|
|
208
|
-
item = properties[key];
|
|
209
|
-
escaped = serializeString(key);
|
|
210
|
-
if (isIterable(ctx, item)) {
|
|
211
|
-
deferredKeys[deferredSize] = escaped;
|
|
212
|
-
deferredValues[deferredSize] = item;
|
|
213
|
-
deferredSize++;
|
|
214
|
-
} else {
|
|
215
|
-
keyNodes[nodesSize] = escaped;
|
|
216
|
-
valueNodes[nodesSize] = parseSync(ctx, item);
|
|
217
|
-
nodesSize++;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
for (let i = 0; i < deferredSize; i++) {
|
|
221
|
-
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
222
|
-
valueNodes[nodesSize + i] = parseSync(ctx, deferredValues[i]);
|
|
223
|
-
}
|
|
224
|
-
if (ctx.features & Feature.Symbol) {
|
|
225
|
-
if (Symbol.iterator in properties) {
|
|
226
|
-
keyNodes[size] = SerovalObjectRecordSpecialKey.SymbolIterator;
|
|
227
|
-
const items = Array.from(properties as Iterable<unknown>);
|
|
228
|
-
const id = createIndexedValue(ctx, items);
|
|
229
|
-
valueNodes[size] = generateArrayNode(ctx, id, items);
|
|
230
|
-
size++;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return {
|
|
234
|
-
k: keyNodes,
|
|
235
|
-
v: valueNodes,
|
|
236
|
-
s: size,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function generatePlainProperties(
|
|
241
|
-
ctx: ParserContext,
|
|
242
|
-
properties: Record<string, unknown>,
|
|
243
|
-
): SerovalPlainRecordNode {
|
|
244
|
-
const keys = Object.keys(properties);
|
|
245
|
-
const size = keys.length;
|
|
246
|
-
const keyNodes = new Array<string>(size);
|
|
247
|
-
const valueNodes = new Array<SerovalSyncNode>(size);
|
|
248
|
-
const deferredKeys = new Array<string>(size);
|
|
249
|
-
const deferredValues = new Array<unknown>(size);
|
|
250
|
-
let deferredSize = 0;
|
|
251
|
-
let nodesSize = 0;
|
|
252
|
-
let item: unknown;
|
|
253
|
-
let escaped: string;
|
|
254
|
-
for (const key of keys) {
|
|
255
|
-
item = properties[key];
|
|
256
|
-
escaped = serializeString(key);
|
|
257
|
-
if (isIterable(ctx, item)) {
|
|
258
|
-
deferredKeys[deferredSize] = escaped;
|
|
259
|
-
deferredValues[deferredSize] = item;
|
|
260
|
-
deferredSize++;
|
|
261
|
-
} else {
|
|
262
|
-
keyNodes[nodesSize] = escaped;
|
|
263
|
-
valueNodes[nodesSize] = parseSync(ctx, item);
|
|
264
|
-
nodesSize++;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
for (let i = 0; i < deferredSize; i++) {
|
|
268
|
-
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
269
|
-
valueNodes[nodesSize + i] = parseSync(ctx, deferredValues[i]);
|
|
270
|
-
}
|
|
271
|
-
return {
|
|
272
|
-
k: keyNodes,
|
|
273
|
-
v: valueNodes,
|
|
274
|
-
s: size,
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function generateObjectNode(
|
|
279
|
-
ctx: ParserContext,
|
|
280
|
-
id: number,
|
|
281
|
-
current: Record<string, unknown>,
|
|
282
|
-
empty: boolean,
|
|
283
|
-
): ObjectLikeNode {
|
|
284
|
-
return {
|
|
285
|
-
t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
286
|
-
i: id,
|
|
287
|
-
s: undefined,
|
|
288
|
-
l: undefined,
|
|
289
|
-
c: undefined,
|
|
290
|
-
m: undefined,
|
|
291
|
-
p: generateProperties(ctx, current),
|
|
292
|
-
e: undefined,
|
|
293
|
-
a: undefined,
|
|
294
|
-
f: undefined,
|
|
295
|
-
b: undefined,
|
|
296
|
-
o: getObjectFlag(current),
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function generateAggregateErrorNode(
|
|
301
|
-
ctx: ParserContext,
|
|
302
|
-
id: number,
|
|
303
|
-
current: AggregateError,
|
|
304
|
-
): SerovalAggregateErrorNode {
|
|
305
|
-
const options = getErrorOptions(ctx, current);
|
|
306
|
-
const optionsNode = options
|
|
307
|
-
? generateProperties(ctx, options)
|
|
308
|
-
: undefined;
|
|
309
|
-
return {
|
|
310
|
-
t: SerovalNodeType.AggregateError,
|
|
311
|
-
i: id,
|
|
312
|
-
s: undefined,
|
|
313
|
-
l: undefined,
|
|
314
|
-
c: undefined,
|
|
315
|
-
m: serializeString(current.message),
|
|
316
|
-
p: optionsNode,
|
|
317
|
-
e: undefined,
|
|
318
|
-
a: undefined,
|
|
319
|
-
f: undefined,
|
|
320
|
-
b: undefined,
|
|
321
|
-
o: undefined,
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function generateErrorNode(
|
|
326
|
-
ctx: ParserContext,
|
|
327
|
-
id: number,
|
|
328
|
-
current: Error,
|
|
329
|
-
): SerovalErrorNode {
|
|
330
|
-
const options = getErrorOptions(ctx, current);
|
|
331
|
-
const optionsNode = options
|
|
332
|
-
? generateProperties(ctx, options)
|
|
333
|
-
: undefined;
|
|
334
|
-
return {
|
|
335
|
-
t: SerovalNodeType.Error,
|
|
336
|
-
i: id,
|
|
337
|
-
s: undefined,
|
|
338
|
-
l: undefined,
|
|
339
|
-
c: getErrorConstructorName(current),
|
|
340
|
-
m: serializeString(current.message),
|
|
341
|
-
p: optionsNode,
|
|
342
|
-
e: undefined,
|
|
343
|
-
a: undefined,
|
|
344
|
-
f: undefined,
|
|
345
|
-
b: undefined,
|
|
346
|
-
o: undefined,
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
function generateHeadersNode(
|
|
351
|
-
ctx: ParserContext,
|
|
352
|
-
id: number,
|
|
353
|
-
current: Headers,
|
|
354
|
-
): SerovalHeadersNode {
|
|
355
|
-
const items: Record<string, string> = {};
|
|
356
|
-
// TS Headers not an Iterable
|
|
357
|
-
current.forEach((value, key) => {
|
|
358
|
-
items[key] = value;
|
|
359
|
-
});
|
|
360
|
-
return {
|
|
361
|
-
t: SerovalNodeType.Headers,
|
|
362
|
-
i: id,
|
|
363
|
-
s: undefined,
|
|
364
|
-
l: undefined,
|
|
365
|
-
c: undefined,
|
|
366
|
-
m: undefined,
|
|
367
|
-
p: undefined,
|
|
368
|
-
e: generatePlainProperties(ctx, items),
|
|
369
|
-
a: undefined,
|
|
370
|
-
f: undefined,
|
|
371
|
-
b: undefined,
|
|
372
|
-
o: undefined,
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function generateFormDataNode(
|
|
377
|
-
ctx: ParserContext,
|
|
378
|
-
id: number,
|
|
379
|
-
current: FormData,
|
|
380
|
-
): SerovalFormDataNode {
|
|
381
|
-
const items: Record<string, FormDataEntryValue> = {};
|
|
382
|
-
// TS FormData isn't an Iterable sadly
|
|
383
|
-
current.forEach((value, key) => {
|
|
384
|
-
items[key] = value;
|
|
385
|
-
});
|
|
386
|
-
return {
|
|
387
|
-
t: SerovalNodeType.FormData,
|
|
388
|
-
i: id,
|
|
389
|
-
s: undefined,
|
|
390
|
-
l: undefined,
|
|
391
|
-
c: undefined,
|
|
392
|
-
m: undefined,
|
|
393
|
-
p: undefined,
|
|
394
|
-
e: generatePlainProperties(ctx, items),
|
|
395
|
-
a: undefined,
|
|
396
|
-
f: undefined,
|
|
397
|
-
b: undefined,
|
|
398
|
-
o: undefined,
|
|
399
|
-
};
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
function generateBoxedNode(
|
|
403
|
-
ctx: ParserContext,
|
|
404
|
-
id: number,
|
|
405
|
-
current: object,
|
|
406
|
-
): SerovalBoxedNode {
|
|
407
|
-
return {
|
|
408
|
-
t: SerovalNodeType.Boxed,
|
|
409
|
-
i: id,
|
|
410
|
-
s: undefined,
|
|
411
|
-
l: undefined,
|
|
412
|
-
c: undefined,
|
|
413
|
-
m: undefined,
|
|
414
|
-
p: undefined,
|
|
415
|
-
e: undefined,
|
|
416
|
-
a: undefined,
|
|
417
|
-
f: parseSync(ctx, current.valueOf()),
|
|
418
|
-
b: undefined,
|
|
419
|
-
o: undefined,
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
function generateEventNode(ctx: ParserContext, id: number, current: Event): SerovalEventNode {
|
|
424
|
-
return {
|
|
425
|
-
t: SerovalNodeType.Event,
|
|
426
|
-
i: id,
|
|
427
|
-
s: serializeString(current.type),
|
|
428
|
-
l: undefined,
|
|
429
|
-
c: undefined,
|
|
430
|
-
m: undefined,
|
|
431
|
-
p: undefined,
|
|
432
|
-
e: undefined,
|
|
433
|
-
a: undefined,
|
|
434
|
-
f: parseObject(ctx, createEventOptions(current)),
|
|
435
|
-
b: undefined,
|
|
436
|
-
o: undefined,
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
function generateCustomEventNode(
|
|
441
|
-
ctx: ParserContext,
|
|
442
|
-
id: number,
|
|
443
|
-
current: CustomEvent,
|
|
444
|
-
): SerovalCustomEventNode {
|
|
445
|
-
return {
|
|
446
|
-
t: SerovalNodeType.CustomEvent,
|
|
447
|
-
i: id,
|
|
448
|
-
s: serializeString(current.type),
|
|
449
|
-
l: undefined,
|
|
450
|
-
c: undefined,
|
|
451
|
-
m: undefined,
|
|
452
|
-
p: undefined,
|
|
453
|
-
e: undefined,
|
|
454
|
-
a: undefined,
|
|
455
|
-
f: parseObject(ctx, createCustomEventOptions(current)),
|
|
456
|
-
b: undefined,
|
|
457
|
-
o: undefined,
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
function parseObject(
|
|
462
|
-
ctx: ParserContext,
|
|
463
|
-
current: object | null,
|
|
464
|
-
): SerovalSyncNode {
|
|
465
|
-
if (!current) {
|
|
466
|
-
return NULL_NODE;
|
|
467
|
-
}
|
|
468
|
-
// Non-primitive values needs a reference ID
|
|
469
|
-
// mostly because the values themselves are stateful
|
|
470
|
-
const id = createIndexedValue(ctx, current);
|
|
471
|
-
if (ctx.reference.marked.has(id)) {
|
|
472
|
-
return createIndexedValueNode(id);
|
|
473
|
-
}
|
|
474
|
-
if (hasReferenceID(current)) {
|
|
475
|
-
return createReferenceNode(id, current);
|
|
476
|
-
}
|
|
477
|
-
// Well well well
|
|
478
|
-
if (Array.isArray(current)) {
|
|
479
|
-
return generateArrayNode(ctx, id, current);
|
|
480
|
-
}
|
|
481
|
-
const currentClass = current.constructor;
|
|
482
|
-
// Fast path
|
|
483
|
-
switch (currentClass) {
|
|
484
|
-
case Number:
|
|
485
|
-
case Boolean:
|
|
486
|
-
case String:
|
|
487
|
-
case BigInt:
|
|
488
|
-
return generateBoxedNode(ctx, id, current);
|
|
489
|
-
case Date:
|
|
490
|
-
return createDateNode(id, current as unknown as Date);
|
|
491
|
-
case RegExp:
|
|
492
|
-
return createRegExpNode(id, current as unknown as RegExp);
|
|
493
|
-
case Object:
|
|
494
|
-
return generateObjectNode(
|
|
495
|
-
ctx,
|
|
496
|
-
id,
|
|
497
|
-
current as unknown as Record<string, unknown>,
|
|
498
|
-
false,
|
|
499
|
-
);
|
|
500
|
-
case undefined:
|
|
501
|
-
return generateObjectNode(
|
|
502
|
-
ctx,
|
|
503
|
-
id,
|
|
504
|
-
current as unknown as Record<string, unknown>,
|
|
505
|
-
true,
|
|
506
|
-
);
|
|
507
|
-
case Error:
|
|
508
|
-
case EvalError:
|
|
509
|
-
case RangeError:
|
|
510
|
-
case ReferenceError:
|
|
511
|
-
case SyntaxError:
|
|
512
|
-
case TypeError:
|
|
513
|
-
case URIError:
|
|
514
|
-
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
515
|
-
default:
|
|
516
|
-
break;
|
|
517
|
-
}
|
|
518
|
-
// Typed Arrays
|
|
519
|
-
if (ctx.features & Feature.TypedArray) {
|
|
520
|
-
switch (currentClass) {
|
|
521
|
-
case ArrayBuffer:
|
|
522
|
-
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
523
|
-
case Int8Array:
|
|
524
|
-
case Int16Array:
|
|
525
|
-
case Int32Array:
|
|
526
|
-
case Uint8Array:
|
|
527
|
-
case Uint16Array:
|
|
528
|
-
case Uint32Array:
|
|
529
|
-
case Uint8ClampedArray:
|
|
530
|
-
case Float32Array:
|
|
531
|
-
case Float64Array:
|
|
532
|
-
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
533
|
-
case DataView:
|
|
534
|
-
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
535
|
-
default:
|
|
536
|
-
break;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
// BigInt Typed Arrays
|
|
540
|
-
if ((ctx.features & BIGINT_FLAG) === BIGINT_FLAG) {
|
|
541
|
-
switch (currentClass) {
|
|
542
|
-
case BigInt64Array:
|
|
543
|
-
case BigUint64Array:
|
|
544
|
-
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
545
|
-
default:
|
|
546
|
-
break;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
// ES Collection
|
|
550
|
-
if (ctx.features & Feature.Map && currentClass === Map) {
|
|
551
|
-
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
552
|
-
}
|
|
553
|
-
if (ctx.features & Feature.Set && currentClass === Set) {
|
|
554
|
-
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
555
|
-
}
|
|
556
|
-
// Web APIs
|
|
557
|
-
if (ctx.features & Feature.WebAPI) {
|
|
558
|
-
if (typeof URL !== 'undefined' && currentClass === URL) {
|
|
559
|
-
return createURLNode(id, current as unknown as URL);
|
|
560
|
-
}
|
|
561
|
-
if (typeof URLSearchParams !== 'undefined' && currentClass === URLSearchParams) {
|
|
562
|
-
return createURLSearchParamsNode(id, current as unknown as URLSearchParams);
|
|
563
|
-
}
|
|
564
|
-
if (typeof Headers !== 'undefined' && currentClass === Headers) {
|
|
565
|
-
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
566
|
-
}
|
|
567
|
-
if (typeof FormData !== 'undefined' && currentClass === FormData) {
|
|
568
|
-
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
569
|
-
}
|
|
570
|
-
if (typeof Event !== 'undefined' && currentClass === Event) {
|
|
571
|
-
return generateEventNode(ctx, id, current as unknown as Event);
|
|
572
|
-
}
|
|
573
|
-
if (typeof CustomEvent !== 'undefined' && currentClass === CustomEvent) {
|
|
574
|
-
return generateCustomEventNode(ctx, id, current as unknown as CustomEvent);
|
|
575
|
-
}
|
|
576
|
-
if (typeof DOMException !== 'undefined' && currentClass === DOMException) {
|
|
577
|
-
return createDOMExceptionNode(id, current as unknown as DOMException);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
if (
|
|
581
|
-
(ctx.features & Feature.AggregateError)
|
|
582
|
-
&& typeof AggregateError !== 'undefined'
|
|
583
|
-
&& (currentClass === AggregateError || current instanceof AggregateError)
|
|
584
|
-
) {
|
|
585
|
-
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
586
|
-
}
|
|
587
|
-
// Slow path. We only need to handle Errors and Iterators
|
|
588
|
-
// since they have very broad implementations.
|
|
589
|
-
if (current instanceof Error) {
|
|
590
|
-
return generateErrorNode(ctx, id, current);
|
|
591
|
-
}
|
|
592
|
-
// Generator functions don't have a global constructor
|
|
593
|
-
// despite existing
|
|
594
|
-
if ((ctx.features & Feature.Symbol) && Symbol.iterator in current) {
|
|
595
|
-
return generateObjectNode(ctx, id, current, !!currentClass);
|
|
596
|
-
}
|
|
597
|
-
throw new UnsupportedTypeError(current);
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
export default function parseSync<T>(
|
|
601
|
-
ctx: ParserContext,
|
|
602
|
-
current: T,
|
|
603
|
-
): SerovalSyncNode {
|
|
604
|
-
const t = typeof current;
|
|
605
|
-
if (ctx.features & Feature.BigInt && t === 'bigint') {
|
|
606
|
-
return createBigIntNode(current as bigint);
|
|
607
|
-
}
|
|
608
|
-
switch (t) {
|
|
609
|
-
case 'boolean':
|
|
610
|
-
return current ? TRUE_NODE : FALSE_NODE;
|
|
611
|
-
case 'undefined':
|
|
612
|
-
return UNDEFINED_NODE;
|
|
613
|
-
case 'string':
|
|
614
|
-
return createStringNode(current as string);
|
|
615
|
-
case 'number':
|
|
616
|
-
return createNumberNode(current as number);
|
|
617
|
-
case 'object':
|
|
618
|
-
return parseObject(ctx, current as object);
|
|
619
|
-
case 'symbol':
|
|
620
|
-
return createSymbolNode(ctx, current as symbol);
|
|
621
|
-
case 'function':
|
|
622
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
623
|
-
return createFunctionNode(ctx, current as Function);
|
|
624
|
-
default:
|
|
625
|
-
throw new UnsupportedTypeError(current);
|
|
626
|
-
}
|
|
7
|
+
export default class SyncParserContext extends BaseSyncParserContext {
|
|
8
|
+
readonly mode: SerovalMode = 'vanilla';
|
|
627
9
|
}
|
package/src/core/types.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
SerovalObjectFlags,
|
|
4
4
|
SerovalConstant,
|
|
5
5
|
Symbols,
|
|
6
|
+
ErrorConstructorTag,
|
|
6
7
|
} from './constants';
|
|
7
8
|
|
|
8
9
|
export interface SerovalBaseNode {
|
|
@@ -204,7 +205,7 @@ export interface SerovalPromiseNode extends SerovalBaseNode {
|
|
|
204
205
|
export interface SerovalErrorNode extends SerovalBaseNode {
|
|
205
206
|
t: SerovalNodeType.Error;
|
|
206
207
|
// constructor name
|
|
207
|
-
|
|
208
|
+
s: ErrorConstructorTag;
|
|
208
209
|
// message
|
|
209
210
|
m: string;
|
|
210
211
|
// other properties
|
|
@@ -382,6 +383,15 @@ export interface SerovalDOMExceptionNode extends SerovalBaseNode {
|
|
|
382
383
|
c: string;
|
|
383
384
|
}
|
|
384
385
|
|
|
386
|
+
export interface SerovalPluginNode extends SerovalBaseNode {
|
|
387
|
+
t: SerovalNodeType.Plugin;
|
|
388
|
+
i: number;
|
|
389
|
+
// value
|
|
390
|
+
s: unknown;
|
|
391
|
+
// tag name
|
|
392
|
+
c: string;
|
|
393
|
+
}
|
|
394
|
+
|
|
385
395
|
export type SerovalSyncNode =
|
|
386
396
|
| SerovalPrimitiveNode
|
|
387
397
|
| SerovalIndexedValueNode
|
|
@@ -407,7 +417,8 @@ export type SerovalSyncNode =
|
|
|
407
417
|
| SerovalBoxedNode
|
|
408
418
|
| SerovalEventNode
|
|
409
419
|
| SerovalCustomEventNode
|
|
410
|
-
| SerovalDOMExceptionNode
|
|
420
|
+
| SerovalDOMExceptionNode
|
|
421
|
+
| SerovalPluginNode;
|
|
411
422
|
|
|
412
423
|
export type SerovalAsyncNode =
|
|
413
424
|
| SerovalPromiseNode
|
package/src/example.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createPlugin, type SerovalNode } from '..';
|
|
2
|
+
|
|
3
|
+
const BufferPlugin = createPlugin<Buffer, SerovalNode>({
|
|
4
|
+
tag: 'Buffer',
|
|
5
|
+
test(value) {
|
|
6
|
+
return value instanceof Buffer;
|
|
7
|
+
},
|
|
8
|
+
parse: {
|
|
9
|
+
sync(value, ctx) {
|
|
10
|
+
return ctx.parse(value.toString('base64'));
|
|
11
|
+
},
|
|
12
|
+
async async(value, ctx) {
|
|
13
|
+
return ctx.parse(value.toString('base64'));
|
|
14
|
+
},
|
|
15
|
+
stream(value, ctx) {
|
|
16
|
+
return ctx.parse(value.toString('base64'));
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
serialize(node, ctx) {
|
|
20
|
+
return `Buffer.from(${ctx.serialize(node)}, "base64")`;
|
|
21
|
+
},
|
|
22
|
+
deserialize(node, ctx) {
|
|
23
|
+
return Buffer.from(ctx.deserialize(node) as string, 'base64');
|
|
24
|
+
},
|
|
25
|
+
isIterable() {
|
|
26
|
+
return true;
|
|
27
|
+
},
|
|
28
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -17,5 +17,8 @@ export * from './core/cross';
|
|
|
17
17
|
export { GLOBAL_CONTEXT_API_SCRIPT, getCrossReferenceHeader } from './core/keys';
|
|
18
18
|
|
|
19
19
|
export { default as Serializer } from './core/Serializer';
|
|
20
|
+
export * from './core/plugin';
|
|
21
|
+
|
|
22
|
+
export type { SerovalNode } from './core/types';
|
|
20
23
|
|
|
21
24
|
export default serialize;
|