seroval 0.12.3 → 0.13.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/dist/cjs/development/index.cjs +1432 -958
- package/dist/cjs/development/index.cjs.map +3 -3
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +1432 -958
- package/dist/esm/development/index.mjs.map +3 -3
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/core/Serializer.d.ts +2 -1
- package/dist/types/core/Serializer.d.ts.map +1 -1
- package/dist/types/core/base-primitives.d.ts +12 -1
- package/dist/types/core/base-primitives.d.ts.map +1 -1
- package/dist/types/core/compat.d.ts +0 -2
- package/dist/types/core/compat.d.ts.map +1 -1
- package/dist/types/core/constants.d.ts +8 -2
- package/dist/types/core/constants.d.ts.map +1 -1
- package/dist/types/core/{tree/deserialize.d.ts → context/deserializer.d.ts} +19 -13
- package/dist/types/core/context/deserializer.d.ts.map +1 -0
- package/dist/types/core/{base → context/parser}/async.d.ts +6 -5
- package/dist/types/core/context/parser/async.d.ts.map +1 -0
- package/dist/types/core/{base → context/parser}/stream.d.ts +2 -1
- package/dist/types/core/context/parser/stream.d.ts.map +1 -0
- package/dist/types/core/{base → context/parser}/sync.d.ts +7 -9
- package/dist/types/core/context/parser/sync.d.ts.map +1 -0
- package/dist/types/core/context/parser.d.ts +27 -0
- package/dist/types/core/context/parser.d.ts.map +1 -0
- package/dist/types/core/{serializer-context.old.d.ts → context/serializer.d.ts} +21 -22
- package/dist/types/core/context/serializer.d.ts.map +1 -0
- package/dist/types/core/cross/async.d.ts +2 -2
- package/dist/types/core/cross/async.d.ts.map +1 -1
- package/dist/types/core/cross/deserializer.d.ts +9 -0
- package/dist/types/core/cross/deserializer.d.ts.map +1 -0
- package/dist/types/core/cross/index.d.ts +11 -1
- package/dist/types/core/cross/index.d.ts.map +1 -1
- package/dist/types/core/cross/parser.d.ts +6 -0
- package/dist/types/core/cross/parser.d.ts.map +1 -0
- package/dist/types/core/cross/{serialize.d.ts → serializer.d.ts} +6 -5
- package/dist/types/core/cross/serializer.d.ts.map +1 -0
- package/dist/types/core/cross/stream.d.ts +2 -2
- package/dist/types/core/cross/stream.d.ts.map +1 -1
- package/dist/types/core/cross/sync.d.ts +2 -2
- package/dist/types/core/cross/sync.d.ts.map +1 -1
- package/dist/types/core/keys.d.ts +3 -1
- package/dist/types/core/keys.d.ts.map +1 -1
- package/dist/types/core/plugin.d.ts +6 -7
- package/dist/types/core/plugin.d.ts.map +1 -1
- package/dist/types/core/special-reference.d.ts +6 -0
- package/dist/types/core/special-reference.d.ts.map +1 -0
- package/dist/types/core/tree/async.d.ts +2 -2
- package/dist/types/core/tree/async.d.ts.map +1 -1
- package/dist/types/core/tree/deserializer.d.ts +13 -0
- package/dist/types/core/tree/deserializer.d.ts.map +1 -0
- package/dist/types/core/tree/{serialize.d.ts → serializer.d.ts} +4 -4
- package/dist/types/core/tree/serializer.d.ts.map +1 -0
- package/dist/types/core/tree/sync.d.ts +2 -2
- package/dist/types/core/tree/sync.d.ts.map +1 -1
- package/dist/types/core/types.d.ts +47 -6
- package/dist/types/core/types.d.ts.map +1 -1
- package/dist/types/core/utils/assert.d.ts.map +1 -0
- package/dist/types/core/utils/constructors.d.ts.map +1 -0
- package/dist/types/core/utils/deferred.d.ts +14 -0
- package/dist/types/core/utils/deferred.d.ts.map +1 -0
- package/dist/types/core/utils/error.d.ts +5 -0
- package/dist/types/core/utils/error.d.ts.map +1 -0
- package/dist/types/core/utils/get-identifier.d.ts.map +1 -0
- package/dist/types/core/utils/get-object-flag.d.ts +3 -0
- package/dist/types/core/utils/get-object-flag.d.ts.map +1 -0
- package/dist/types/core/utils/is-valid-identifier.d.ts +2 -0
- package/dist/types/core/utils/is-valid-identifier.d.ts.map +1 -0
- package/dist/types/core/utils/iterator-to-sequence.d.ts +20 -0
- package/dist/types/core/utils/iterator-to-sequence.d.ts.map +1 -0
- package/dist/types/core/utils/promise-to-result.d.ts.map +1 -0
- package/dist/types/core/utils/typed-array.d.ts +4 -0
- package/dist/types/core/utils/typed-array.d.ts.map +1 -0
- package/dist/types/core/web-api.d.ts +4 -1
- package/dist/types/core/web-api.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/core/Serializer.ts +3 -1
- package/src/core/base-primitives.ts +229 -1
- package/src/core/compat.ts +0 -2
- package/src/core/constants.ts +7 -2
- package/src/core/{tree/deserialize.ts → context/deserializer.ts} +159 -66
- package/src/core/{base → context/parser}/async.ts +181 -309
- package/src/core/{base → context/parser}/stream.ts +86 -11
- package/src/core/{base → context/parser}/sync.ts +120 -281
- package/src/core/context/parser.ts +259 -0
- package/src/core/{serializer-context.old.ts → context/serializer.ts} +241 -166
- package/src/core/cross/async.ts +2 -2
- package/src/core/cross/deserializer.ts +19 -0
- package/src/core/cross/index.ts +68 -47
- package/src/core/cross/parser.ts +7 -0
- package/src/core/cross/{serialize.ts → serializer.ts} +31 -12
- package/src/core/cross/stream.ts +2 -2
- package/src/core/cross/sync.ts +2 -2
- package/src/core/is-serializable.new.ts +1 -1
- package/src/core/keys.ts +8 -2
- package/src/core/plugin.ts +7 -7
- package/src/core/reference.ts +1 -1
- package/src/core/special-reference.ts +9 -0
- package/src/core/tree/async.ts +2 -2
- package/src/core/tree/deserializer.ts +31 -0
- package/src/core/tree/index.ts +2 -2
- package/src/core/tree/{serialize.ts → serializer.ts} +5 -16
- package/src/core/tree/sync.ts +2 -2
- package/src/core/types.ts +60 -7
- package/src/core/utils/deferred.ts +49 -0
- package/src/core/{shared.ts → utils/error.ts} +3 -60
- package/src/core/utils/get-object-flag.ts +14 -0
- package/src/core/utils/is-valid-identifier.ts +11 -0
- package/src/core/utils/iterator-to-sequence.ts +238 -0
- package/src/core/utils/typed-array.ts +30 -0
- package/src/core/web-api.ts +75 -1
- package/src/example.ts +0 -3
- package/dist/types/core/assert.d.ts.map +0 -1
- package/dist/types/core/base/async.d.ts.map +0 -1
- package/dist/types/core/base/stream.d.ts.map +0 -1
- package/dist/types/core/base/sync.d.ts.map +0 -1
- package/dist/types/core/constructors.d.ts.map +0 -1
- package/dist/types/core/cross/cross-parser.d.ts +0 -8
- package/dist/types/core/cross/cross-parser.d.ts.map +0 -1
- package/dist/types/core/cross/serialize.d.ts.map +0 -1
- package/dist/types/core/get-identifier.d.ts.map +0 -1
- package/dist/types/core/parser-context.d.ts +0 -23
- package/dist/types/core/parser-context.d.ts.map +0 -1
- package/dist/types/core/promise-to-result.d.ts.map +0 -1
- package/dist/types/core/serializer-context.old.d.ts.map +0 -1
- package/dist/types/core/shared.d.ts +0 -10
- package/dist/types/core/shared.d.ts.map +0 -1
- package/dist/types/core/tree/deserialize.d.ts.map +0 -1
- package/dist/types/core/tree/serialize.d.ts.map +0 -1
- package/src/core/cross/cross-parser.ts +0 -9
- package/src/core/parser-context.ts +0 -131
- package/src/core/serializer-context.new.ts +0 -1168
- package/src/core/tree/parser.ts +0 -45
- /package/dist/types/core/{assert.d.ts → utils/assert.d.ts} +0 -0
- /package/dist/types/core/{constructors.d.ts → utils/constructors.d.ts} +0 -0
- /package/dist/types/core/{get-identifier.d.ts → utils/get-identifier.d.ts} +0 -0
- /package/dist/types/core/{promise-to-result.d.ts → utils/promise-to-result.d.ts} +0 -0
- /package/src/core/{assert.ts → utils/assert.ts} +0 -0
- /package/src/core/{constructors.ts → utils/constructors.ts} +0 -0
- /package/src/core/{get-identifier.ts → utils/get-identifier.ts} +0 -0
- /package/src/core/{promise-to-result.ts → utils/promise-to-result.ts} +0 -0
|
@@ -1,1168 +0,0 @@
|
|
|
1
|
-
import { Feature } from './compat';
|
|
2
|
-
import {
|
|
3
|
-
CONSTANT_STRING,
|
|
4
|
-
ERROR_CONSTRUCTOR_STRING,
|
|
5
|
-
SYMBOL_STRING,
|
|
6
|
-
SerovalNodeType,
|
|
7
|
-
SerovalObjectFlags,
|
|
8
|
-
} from './constants';
|
|
9
|
-
import getIdentifier from './get-identifier';
|
|
10
|
-
import { REFERENCES_KEY } from './keys';
|
|
11
|
-
import type { Plugin, PluginAccessOptions, SerovalMode } from './plugin';
|
|
12
|
-
import { isValidIdentifier } from './shared';
|
|
13
|
-
import type {
|
|
14
|
-
SerovalArrayNode,
|
|
15
|
-
SerovalIndexedValueNode,
|
|
16
|
-
SerovalNode,
|
|
17
|
-
SerovalObjectRecordKey,
|
|
18
|
-
SerovalObjectRecordNode,
|
|
19
|
-
SerovalReferenceNode,
|
|
20
|
-
SerovalObjectNode,
|
|
21
|
-
SerovalNullConstructorNode,
|
|
22
|
-
SerovalRegExpNode,
|
|
23
|
-
SerovalDateNode,
|
|
24
|
-
SerovalSetNode,
|
|
25
|
-
SerovalMapNode,
|
|
26
|
-
SerovalArrayBufferNode,
|
|
27
|
-
SerovalTypedArrayNode,
|
|
28
|
-
SerovalBigIntTypedArrayNode,
|
|
29
|
-
SerovalDataViewNode,
|
|
30
|
-
SerovalAggregateErrorNode,
|
|
31
|
-
SerovalErrorNode,
|
|
32
|
-
SerovalPromiseNode,
|
|
33
|
-
SerovalWKSymbolNode,
|
|
34
|
-
SerovalURLNode,
|
|
35
|
-
SerovalURLSearchParamsNode,
|
|
36
|
-
SerovalBlobNode,
|
|
37
|
-
SerovalFileNode,
|
|
38
|
-
SerovalHeadersNode,
|
|
39
|
-
SerovalFormDataNode,
|
|
40
|
-
SerovalBoxedNode,
|
|
41
|
-
SerovalRequestNode,
|
|
42
|
-
SerovalResponseNode,
|
|
43
|
-
SerovalEventNode,
|
|
44
|
-
SerovalCustomEventNode,
|
|
45
|
-
SerovalDOMExceptionNode,
|
|
46
|
-
SerovalPluginNode,
|
|
47
|
-
SerovalPromiseConstructorNode,
|
|
48
|
-
SerovalPromiseResolveNode,
|
|
49
|
-
SerovalPromiseRejectNode,
|
|
50
|
-
SerovalReadableStreamConstructorNode,
|
|
51
|
-
SerovalReadableStreamEnqueueNode,
|
|
52
|
-
SerovalReadableStreamErrorNode,
|
|
53
|
-
SerovalReadableStreamCloseNode,
|
|
54
|
-
} from './types';
|
|
55
|
-
import {
|
|
56
|
-
SerovalObjectRecordSpecialKey,
|
|
57
|
-
} from './types';
|
|
58
|
-
|
|
59
|
-
interface IndexAssignment {
|
|
60
|
-
t: 'index';
|
|
61
|
-
s: string;
|
|
62
|
-
k: undefined;
|
|
63
|
-
v: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface SetAssignment {
|
|
67
|
-
t: 'set';
|
|
68
|
-
s: string;
|
|
69
|
-
k: string;
|
|
70
|
-
v: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
interface AddAssignment {
|
|
74
|
-
t: 'add';
|
|
75
|
-
s: string;
|
|
76
|
-
k: undefined;
|
|
77
|
-
v: string;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
interface DeleteAssignment {
|
|
81
|
-
t: 'delete';
|
|
82
|
-
s: string;
|
|
83
|
-
k: string;
|
|
84
|
-
v: undefined;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Array of assignments to be done (used for recursion)
|
|
88
|
-
type Assignment =
|
|
89
|
-
| IndexAssignment
|
|
90
|
-
| AddAssignment
|
|
91
|
-
| SetAssignment
|
|
92
|
-
| DeleteAssignment;
|
|
93
|
-
|
|
94
|
-
export interface FlaggedObject {
|
|
95
|
-
type: SerovalObjectFlags;
|
|
96
|
-
value: string;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function getAssignmentExpression(assignment: Assignment): string {
|
|
100
|
-
switch (assignment.t) {
|
|
101
|
-
case 'index':
|
|
102
|
-
return assignment.s + '=' + assignment.v;
|
|
103
|
-
case 'set':
|
|
104
|
-
return assignment.s + '.set(' + assignment.k + ',' + assignment.v + ')';
|
|
105
|
-
case 'add':
|
|
106
|
-
return assignment.s + '.add(' + assignment.v + ')';
|
|
107
|
-
case 'delete':
|
|
108
|
-
return assignment.s + '.delete(' + assignment.k + ')';
|
|
109
|
-
default:
|
|
110
|
-
return '';
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function mergeAssignments(assignments: Assignment[]): Assignment[] {
|
|
115
|
-
const newAssignments: Assignment[] = [];
|
|
116
|
-
let current = assignments[0];
|
|
117
|
-
for (let i = 1, len = assignments.length, item: Assignment, prev = current; i < len; i++) {
|
|
118
|
-
item = assignments[i];
|
|
119
|
-
if (item.t === 'index' && item.v === prev.v) {
|
|
120
|
-
// Merge if the right-hand value is the same
|
|
121
|
-
// saves at least 2 chars
|
|
122
|
-
current = {
|
|
123
|
-
t: 'index',
|
|
124
|
-
s: item.s,
|
|
125
|
-
k: undefined,
|
|
126
|
-
v: getAssignmentExpression(current),
|
|
127
|
-
} as IndexAssignment;
|
|
128
|
-
} else if (item.t === 'set' && item.s === prev.s) {
|
|
129
|
-
// Maps has chaining methods, merge if source is the same
|
|
130
|
-
current = {
|
|
131
|
-
t: 'set',
|
|
132
|
-
s: getAssignmentExpression(current),
|
|
133
|
-
k: item.k,
|
|
134
|
-
v: item.v,
|
|
135
|
-
} as SetAssignment;
|
|
136
|
-
} else if (item.t === 'add' && item.s === prev.s) {
|
|
137
|
-
// Sets has chaining methods too
|
|
138
|
-
current = {
|
|
139
|
-
t: 'add',
|
|
140
|
-
s: getAssignmentExpression(current),
|
|
141
|
-
k: undefined,
|
|
142
|
-
v: item.v,
|
|
143
|
-
} as AddAssignment;
|
|
144
|
-
} else if (item.t === 'delete' && item.s === prev.s) {
|
|
145
|
-
// Maps has chaining methods, merge if source is the same
|
|
146
|
-
current = {
|
|
147
|
-
t: 'delete',
|
|
148
|
-
s: getAssignmentExpression(current),
|
|
149
|
-
k: item.k,
|
|
150
|
-
v: undefined,
|
|
151
|
-
} as DeleteAssignment;
|
|
152
|
-
} else {
|
|
153
|
-
// Different assignment, push current
|
|
154
|
-
newAssignments.push(current);
|
|
155
|
-
current = item;
|
|
156
|
-
}
|
|
157
|
-
prev = item;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
newAssignments.push(current);
|
|
161
|
-
|
|
162
|
-
return newAssignments;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function resolveAssignments(assignments: Assignment[]): string | undefined {
|
|
166
|
-
if (assignments.length) {
|
|
167
|
-
let result = '';
|
|
168
|
-
const merged = mergeAssignments(assignments);
|
|
169
|
-
for (let i = 0, len = merged.length; i < len; i++) {
|
|
170
|
-
result += getAssignmentExpression(merged[i]) + ',';
|
|
171
|
-
}
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
|
-
return undefined;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const SET_CONSTRUCTOR = 'new Set';
|
|
178
|
-
const MAP_CONSTRUCTOR = 'new Map';
|
|
179
|
-
|
|
180
|
-
const enum SpecialReference {
|
|
181
|
-
Sentinel = 0,
|
|
182
|
-
Symbol = 1,
|
|
183
|
-
SymbolIterator = 2,
|
|
184
|
-
Object = 3,
|
|
185
|
-
ObjectFreeze = 4,
|
|
186
|
-
ObjectSeal = 5,
|
|
187
|
-
ObjectPreventExtensions = 6,
|
|
188
|
-
ObjectAssign = 7,
|
|
189
|
-
ObjectCreate = 8,
|
|
190
|
-
Promise = 9,
|
|
191
|
-
PromiseResolve = 10,
|
|
192
|
-
PromiseReject = 11,
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const OBJECT_FLAG_CONSTRUCTOR: Record<SerovalObjectFlags, SpecialReference | undefined> = {
|
|
196
|
-
[SerovalObjectFlags.Frozen]: SpecialReference.ObjectFreeze,
|
|
197
|
-
[SerovalObjectFlags.Sealed]: SpecialReference.ObjectSeal,
|
|
198
|
-
[SerovalObjectFlags.NonExtensible]: SpecialReference.ObjectPreventExtensions,
|
|
199
|
-
[SerovalObjectFlags.None]: undefined,
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
export interface BaseSerializerContextOptions extends PluginAccessOptions {
|
|
203
|
-
features: number;
|
|
204
|
-
markedRefs: number[] | Set<number>;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export default abstract class BaseSerializerContext implements PluginAccessOptions {
|
|
208
|
-
/**
|
|
209
|
-
* @private
|
|
210
|
-
*/
|
|
211
|
-
features: number;
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* To check if an object is synchronously referencing itself
|
|
215
|
-
* @private
|
|
216
|
-
*/
|
|
217
|
-
stack: number[] = [];
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Array of object mutations
|
|
221
|
-
* @private
|
|
222
|
-
*/
|
|
223
|
-
flags: FlaggedObject[] = [];
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Array of assignments to be done (used for recursion)
|
|
227
|
-
* @private
|
|
228
|
-
*/
|
|
229
|
-
assignments: Assignment[] = [];
|
|
230
|
-
|
|
231
|
-
plugins?: Plugin<any, any>[] | undefined;
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Refs that are...referenced
|
|
235
|
-
* @private
|
|
236
|
-
*/
|
|
237
|
-
marked: Set<number>;
|
|
238
|
-
|
|
239
|
-
constructor(options: BaseSerializerContextOptions) {
|
|
240
|
-
this.plugins = options.plugins;
|
|
241
|
-
this.features = options.features;
|
|
242
|
-
this.marked = new Set(options.markedRefs);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
abstract readonly mode: SerovalMode;
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* A tiny function that tells if a reference
|
|
249
|
-
* is to be accessed. This is a requirement for
|
|
250
|
-
* deciding whether or not we should generate
|
|
251
|
-
* an identifier for the object
|
|
252
|
-
*/
|
|
253
|
-
protected markRef(id: number): void {
|
|
254
|
-
this.marked.add(id);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
protected isMarked(id: number): boolean {
|
|
258
|
-
return this.marked.has(id);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Converts the ID of a reference into a identifier string
|
|
263
|
-
* that is used to refer to the object instance in the
|
|
264
|
-
* generated script.
|
|
265
|
-
*/
|
|
266
|
-
abstract getRefParam(id: number | string): string;
|
|
267
|
-
|
|
268
|
-
private specials = new Set<SpecialReference>();
|
|
269
|
-
|
|
270
|
-
protected getSpecialReferenceValue(ref: SpecialReference): string {
|
|
271
|
-
switch (ref) {
|
|
272
|
-
case SpecialReference.Sentinel:
|
|
273
|
-
return '[]';
|
|
274
|
-
case SpecialReference.Symbol:
|
|
275
|
-
return 'Symbol';
|
|
276
|
-
case SpecialReference.SymbolIterator:
|
|
277
|
-
return this.getSpecialReference(SpecialReference.Symbol, true) + '.iterator';
|
|
278
|
-
case SpecialReference.Object:
|
|
279
|
-
return 'Object';
|
|
280
|
-
case SpecialReference.ObjectFreeze:
|
|
281
|
-
return this.getSpecialReference(SpecialReference.Object, true) + '.freeze';
|
|
282
|
-
case SpecialReference.ObjectSeal:
|
|
283
|
-
return this.getSpecialReference(SpecialReference.Object, true) + '.seal';
|
|
284
|
-
case SpecialReference.ObjectPreventExtensions:
|
|
285
|
-
return this.getSpecialReference(SpecialReference.Object, true) + '.preventExtensions';
|
|
286
|
-
case SpecialReference.ObjectAssign:
|
|
287
|
-
return this.getSpecialReference(SpecialReference.Object, true) + '.assign';
|
|
288
|
-
case SpecialReference.ObjectCreate:
|
|
289
|
-
return this.getSpecialReference(SpecialReference.Object, true) + '.create';
|
|
290
|
-
case SpecialReference.Promise:
|
|
291
|
-
return 'Promise';
|
|
292
|
-
case SpecialReference.PromiseResolve:
|
|
293
|
-
return this.getSpecialReference(SpecialReference.Promise, true) + '.resolve.bind(' + this.getSpecialReference(SpecialReference.Promise, false) + ')';
|
|
294
|
-
case SpecialReference.PromiseReject:
|
|
295
|
-
return this.getSpecialReference(SpecialReference.Promise, true) + '.reject.bind(' + this.getSpecialReference(SpecialReference.Promise, false) + ')';
|
|
296
|
-
default:
|
|
297
|
-
throw new Error('unknown special reference');
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Generates special references that isn't provided by the user
|
|
303
|
-
* but by the script.
|
|
304
|
-
*/
|
|
305
|
-
protected getSpecialReference(ref: SpecialReference, call: boolean): string {
|
|
306
|
-
const param = this.getRefParam('_' + getIdentifier(ref));
|
|
307
|
-
if (this.specials.has(ref)) {
|
|
308
|
-
return param;
|
|
309
|
-
}
|
|
310
|
-
this.specials.add(ref);
|
|
311
|
-
const expr = param + '=' + this.getSpecialReferenceValue(ref);
|
|
312
|
-
if (call) {
|
|
313
|
-
return '(' + expr + ')';
|
|
314
|
-
}
|
|
315
|
-
return expr;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
protected pushObjectFlag(flag: SerovalObjectFlags, id: number): void {
|
|
319
|
-
if (flag !== SerovalObjectFlags.None) {
|
|
320
|
-
this.markRef(id);
|
|
321
|
-
this.flags.push({
|
|
322
|
-
type: flag,
|
|
323
|
-
value: this.getRefParam(id),
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
private resolveFlags(): string | undefined {
|
|
329
|
-
let result = '';
|
|
330
|
-
for (let i = 0, current = this.flags, len = current.length; i < len; i++) {
|
|
331
|
-
const flag = current[i];
|
|
332
|
-
const constructor = OBJECT_FLAG_CONSTRUCTOR[flag.type];
|
|
333
|
-
if (constructor) {
|
|
334
|
-
const ref = this.getSpecialReference(constructor, true);
|
|
335
|
-
result += ref + '(' + flag.value + '),';
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return result;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
protected resolvePatches(): string | undefined {
|
|
342
|
-
const assignments = resolveAssignments(this.assignments);
|
|
343
|
-
const flags = this.resolveFlags();
|
|
344
|
-
if (assignments) {
|
|
345
|
-
if (flags) {
|
|
346
|
-
return assignments + flags;
|
|
347
|
-
}
|
|
348
|
-
return assignments;
|
|
349
|
-
}
|
|
350
|
-
return flags;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Generates the inlined assignment for the reference
|
|
355
|
-
* This is different from the assignments array as this one
|
|
356
|
-
* signifies creation rather than mutation
|
|
357
|
-
*/
|
|
358
|
-
protected createAssignment(
|
|
359
|
-
source: string,
|
|
360
|
-
value: string,
|
|
361
|
-
): void {
|
|
362
|
-
this.assignments.push({
|
|
363
|
-
t: 'index',
|
|
364
|
-
s: source,
|
|
365
|
-
k: undefined,
|
|
366
|
-
v: value,
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
protected createAddAssignment(
|
|
371
|
-
ref: number,
|
|
372
|
-
value: string,
|
|
373
|
-
): void {
|
|
374
|
-
this.assignments.push({
|
|
375
|
-
t: 'add',
|
|
376
|
-
s: this.getRefParam(ref),
|
|
377
|
-
k: undefined,
|
|
378
|
-
v: value,
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
protected createSetAssignment(
|
|
383
|
-
ref: number,
|
|
384
|
-
key: string,
|
|
385
|
-
value: string,
|
|
386
|
-
): void {
|
|
387
|
-
this.assignments.push({
|
|
388
|
-
t: 'set',
|
|
389
|
-
s: this.getRefParam(ref),
|
|
390
|
-
k: key,
|
|
391
|
-
v: value,
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
protected createDeleteAssignment(
|
|
396
|
-
ref: number,
|
|
397
|
-
key: string,
|
|
398
|
-
): void {
|
|
399
|
-
this.assignments.push({
|
|
400
|
-
t: 'delete',
|
|
401
|
-
s: this.getRefParam(ref),
|
|
402
|
-
k: key,
|
|
403
|
-
v: undefined,
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
protected createArrayAssign(
|
|
408
|
-
ref: number,
|
|
409
|
-
index: number | string,
|
|
410
|
-
value: string,
|
|
411
|
-
): void {
|
|
412
|
-
this.createAssignment(this.getRefParam(ref) + '[' + index + ']', value);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
protected createObjectAssign(
|
|
416
|
-
ref: number,
|
|
417
|
-
key: string,
|
|
418
|
-
value: string,
|
|
419
|
-
): void {
|
|
420
|
-
this.createAssignment(this.getRefParam(ref) + '.' + key, value);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Checks if the value is in the stack. Stack here is a reference
|
|
425
|
-
* structure to know if a object is to be accessed in a TDZ.
|
|
426
|
-
*/
|
|
427
|
-
isIndexedValueInStack(
|
|
428
|
-
node: SerovalNode,
|
|
429
|
-
): boolean {
|
|
430
|
-
return node.t === SerovalNodeType.IndexedValue && this.stack.includes(node.i);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Produces an assignment expression. `id` generates a reference
|
|
435
|
-
* parameter (through `getRefParam`) and has the option to
|
|
436
|
-
* return the reference parameter directly or assign a value to
|
|
437
|
-
* it.
|
|
438
|
-
*/
|
|
439
|
-
protected abstract assignIndexedValue(
|
|
440
|
-
id: number,
|
|
441
|
-
value: string,
|
|
442
|
-
): string;
|
|
443
|
-
|
|
444
|
-
protected serializeReference(
|
|
445
|
-
node: SerovalReferenceNode,
|
|
446
|
-
): string {
|
|
447
|
-
return this.assignIndexedValue(node.i, REFERENCES_KEY + '.get("' + node.s + '")');
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
protected getIterableAccess(): string {
|
|
451
|
-
return this.features & Feature.ArrayPrototypeValues
|
|
452
|
-
? '.values()'
|
|
453
|
-
: '[' + this.getSpecialReference(SpecialReference.SymbolIterator, false) + ']()';
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
protected serializeIterable(
|
|
457
|
-
node: SerovalNode,
|
|
458
|
-
): string {
|
|
459
|
-
const key = '[' + this.getSpecialReference(SpecialReference.SymbolIterator, false) + ']';
|
|
460
|
-
const parent = this.stack;
|
|
461
|
-
this.stack = [];
|
|
462
|
-
let serialized = this.serialize(node) + this.getIterableAccess();
|
|
463
|
-
this.stack = parent;
|
|
464
|
-
if (this.features & Feature.ArrowFunction) {
|
|
465
|
-
serialized = ':()=>' + serialized;
|
|
466
|
-
} else if (this.features & Feature.MethodShorthand) {
|
|
467
|
-
serialized = '(){return ' + serialized + '}';
|
|
468
|
-
} else {
|
|
469
|
-
serialized = ':function(){return ' + serialized + '}';
|
|
470
|
-
}
|
|
471
|
-
return key + serialized;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
protected serializeArrayItem(
|
|
475
|
-
id: number,
|
|
476
|
-
item: SerovalNode | undefined,
|
|
477
|
-
index: number,
|
|
478
|
-
): string {
|
|
479
|
-
// Check if index is a hole
|
|
480
|
-
if (item) {
|
|
481
|
-
// Check if item is a parent
|
|
482
|
-
if (this.isIndexedValueInStack(item)) {
|
|
483
|
-
this.markRef(id);
|
|
484
|
-
this.createArrayAssign(id, index, this.getRefParam((item as SerovalIndexedValueNode).i));
|
|
485
|
-
return '';
|
|
486
|
-
}
|
|
487
|
-
return this.serialize(item);
|
|
488
|
-
}
|
|
489
|
-
return '';
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
protected serializeArray(
|
|
493
|
-
node: SerovalArrayNode,
|
|
494
|
-
): string {
|
|
495
|
-
const id = node.i;
|
|
496
|
-
if (node.l) {
|
|
497
|
-
this.stack.push(id);
|
|
498
|
-
// This is different than Map and Set
|
|
499
|
-
// because we also need to serialize
|
|
500
|
-
// the holes of the Array
|
|
501
|
-
const list = node.a;
|
|
502
|
-
let values = this.serializeArrayItem(id, list[0], 0);
|
|
503
|
-
let isHoley = values === '';
|
|
504
|
-
for (let i = 1, len = node.l, item: string; i < len; i++) {
|
|
505
|
-
item = this.serializeArrayItem(id, list[i], i);
|
|
506
|
-
values += ',' + item;
|
|
507
|
-
isHoley = item === '';
|
|
508
|
-
}
|
|
509
|
-
this.stack.pop();
|
|
510
|
-
this.pushObjectFlag(node.o, node.i);
|
|
511
|
-
return this.assignIndexedValue(id, '[' + values + (isHoley ? ',]' : ']'));
|
|
512
|
-
}
|
|
513
|
-
return this.assignIndexedValue(id, '[]');
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
protected serializeProperty(
|
|
517
|
-
id: number,
|
|
518
|
-
key: SerovalObjectRecordKey,
|
|
519
|
-
val: SerovalNode,
|
|
520
|
-
): string {
|
|
521
|
-
// Only reason this is a switch is so that
|
|
522
|
-
// in the future, maybe other Symbols are going
|
|
523
|
-
// to be introduced and/or has merit to be added
|
|
524
|
-
// E.g. Symbol.asyncIterator
|
|
525
|
-
switch (key) {
|
|
526
|
-
case SerovalObjectRecordSpecialKey.SymbolIterator:
|
|
527
|
-
return this.serializeIterable(val);
|
|
528
|
-
default: {
|
|
529
|
-
const check = Number(key);
|
|
530
|
-
// Test if key is a valid number or JS identifier
|
|
531
|
-
// so that we don't have to serialize the key and wrap with brackets
|
|
532
|
-
const isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
533
|
-
if (this.isIndexedValueInStack(val)) {
|
|
534
|
-
const refParam = this.getRefParam((val as SerovalIndexedValueNode).i);
|
|
535
|
-
this.markRef(id);
|
|
536
|
-
// eslint-disable-next-line no-self-compare
|
|
537
|
-
if (isIdentifier && check !== check) {
|
|
538
|
-
this.createObjectAssign(id, key, refParam);
|
|
539
|
-
} else {
|
|
540
|
-
this.createArrayAssign(id, isIdentifier ? key : ('"' + key + '"'), refParam);
|
|
541
|
-
}
|
|
542
|
-
return '';
|
|
543
|
-
}
|
|
544
|
-
return (isIdentifier ? key : ('"' + key + '"')) + ':' + this.serialize(val);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
protected serializeProperties(
|
|
550
|
-
sourceID: number,
|
|
551
|
-
node: SerovalObjectRecordNode,
|
|
552
|
-
): string {
|
|
553
|
-
const len = node.s;
|
|
554
|
-
if (len) {
|
|
555
|
-
this.stack.push(sourceID);
|
|
556
|
-
const keys = node.k;
|
|
557
|
-
const values = node.v;
|
|
558
|
-
let result = this.serializeProperty(sourceID, keys[0], values[0]);
|
|
559
|
-
for (let i = 1, item = result; i < len; i++) {
|
|
560
|
-
item = this.serializeProperty(sourceID, keys[i], values[i]);
|
|
561
|
-
result += (item && result && ',') + item;
|
|
562
|
-
}
|
|
563
|
-
this.stack.pop();
|
|
564
|
-
return '{' + result + '}';
|
|
565
|
-
}
|
|
566
|
-
return '{}';
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
protected serializeObject(
|
|
570
|
-
node: SerovalObjectNode,
|
|
571
|
-
): string {
|
|
572
|
-
this.pushObjectFlag(node.o, node.i);
|
|
573
|
-
return this.assignIndexedValue(node.i, this.serializeProperties(node.i, node.p));
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
protected serializeWithObjectAssign(
|
|
577
|
-
value: SerovalObjectRecordNode,
|
|
578
|
-
id: number,
|
|
579
|
-
serialized: string,
|
|
580
|
-
): string {
|
|
581
|
-
const fields = this.serializeProperties(id, value);
|
|
582
|
-
if (fields !== '{}') {
|
|
583
|
-
return this.getSpecialReference(SpecialReference.ObjectAssign, true) + '(' + serialized + ',' + fields + ')';
|
|
584
|
-
}
|
|
585
|
-
return serialized;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
protected serializeAssignment(
|
|
589
|
-
sourceID: number,
|
|
590
|
-
mainAssignments: Assignment[],
|
|
591
|
-
key: SerovalObjectRecordKey,
|
|
592
|
-
value: SerovalNode,
|
|
593
|
-
): void {
|
|
594
|
-
switch (key) {
|
|
595
|
-
case SerovalObjectRecordSpecialKey.SymbolIterator: {
|
|
596
|
-
const parent = this.stack;
|
|
597
|
-
this.stack = [];
|
|
598
|
-
const serialized = this.serialize(value) + this.getIterableAccess();
|
|
599
|
-
this.stack = parent;
|
|
600
|
-
const parentAssignment = this.assignments;
|
|
601
|
-
this.assignments = mainAssignments;
|
|
602
|
-
this.createArrayAssign(
|
|
603
|
-
sourceID,
|
|
604
|
-
this.getSpecialReference(SpecialReference.Sentinel, false),
|
|
605
|
-
this.features & Feature.ArrowFunction
|
|
606
|
-
? '()=>' + serialized
|
|
607
|
-
: 'function(){return ' + serialized + '}',
|
|
608
|
-
);
|
|
609
|
-
this.assignments = parentAssignment;
|
|
610
|
-
}
|
|
611
|
-
break;
|
|
612
|
-
default: {
|
|
613
|
-
const serialized = this.serialize(value);
|
|
614
|
-
const check = Number(key);
|
|
615
|
-
// Test if key is a valid number or JS identifier
|
|
616
|
-
// so that we don't have to serialize the key and wrap with brackets
|
|
617
|
-
const isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
618
|
-
if (this.isIndexedValueInStack(value)) {
|
|
619
|
-
// eslint-disable-next-line no-self-compare
|
|
620
|
-
if (isIdentifier && check !== check) {
|
|
621
|
-
this.createObjectAssign(sourceID, key, serialized);
|
|
622
|
-
} else {
|
|
623
|
-
this.createArrayAssign(sourceID, isIdentifier ? key : ('"' + key + '"'), serialized);
|
|
624
|
-
}
|
|
625
|
-
} else {
|
|
626
|
-
const parentAssignment = this.assignments;
|
|
627
|
-
this.assignments = mainAssignments;
|
|
628
|
-
if (isIdentifier) {
|
|
629
|
-
this.createObjectAssign(sourceID, key, serialized);
|
|
630
|
-
} else {
|
|
631
|
-
this.createArrayAssign(sourceID, isIdentifier ? key : ('"' + key + '"'), serialized);
|
|
632
|
-
}
|
|
633
|
-
this.assignments = parentAssignment;
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
protected serializeAssignments(
|
|
640
|
-
sourceID: number,
|
|
641
|
-
node: SerovalObjectRecordNode,
|
|
642
|
-
): string | undefined {
|
|
643
|
-
const len = node.s;
|
|
644
|
-
if (len) {
|
|
645
|
-
this.stack.push(sourceID);
|
|
646
|
-
const mainAssignments: Assignment[] = [];
|
|
647
|
-
const keys = node.k;
|
|
648
|
-
const values = node.v;
|
|
649
|
-
for (let i = 0; i < len; i++) {
|
|
650
|
-
this.serializeAssignment(sourceID, mainAssignments, keys[i], values[i]);
|
|
651
|
-
}
|
|
652
|
-
this.stack.pop();
|
|
653
|
-
return resolveAssignments(mainAssignments);
|
|
654
|
-
}
|
|
655
|
-
return undefined;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
protected serializeDictionary(
|
|
659
|
-
i: number,
|
|
660
|
-
p: SerovalObjectRecordNode | undefined,
|
|
661
|
-
init: string,
|
|
662
|
-
): string {
|
|
663
|
-
if (p) {
|
|
664
|
-
if (this.features & Feature.ObjectAssign) {
|
|
665
|
-
init = this.serializeWithObjectAssign(p, i, init);
|
|
666
|
-
} else {
|
|
667
|
-
this.markRef(i);
|
|
668
|
-
const assignments = this.serializeAssignments(i, p);
|
|
669
|
-
if (assignments) {
|
|
670
|
-
return '(' + this.assignIndexedValue(i, init) + ',' + assignments + this.getRefParam(i) + ')';
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
return this.assignIndexedValue(i, init);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
protected serializeNullConstructor(
|
|
678
|
-
node: SerovalNullConstructorNode,
|
|
679
|
-
): string {
|
|
680
|
-
this.pushObjectFlag(node.o, node.i);
|
|
681
|
-
return this.serializeDictionary(node.i, node.p, this.getSpecialReference(SpecialReference.ObjectCreate, true) + '(null)');
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
protected serializeDate(
|
|
685
|
-
node: SerovalDateNode,
|
|
686
|
-
): string {
|
|
687
|
-
return this.assignIndexedValue(node.i, 'new Date("' + node.s + '")');
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
protected serializeRegExp(
|
|
691
|
-
node: SerovalRegExpNode,
|
|
692
|
-
): string {
|
|
693
|
-
return this.assignIndexedValue(node.i, '/' + node.c + '/' + node.m);
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
protected serializeSetItem(
|
|
697
|
-
id: number,
|
|
698
|
-
item: SerovalNode,
|
|
699
|
-
): string {
|
|
700
|
-
if (this.isIndexedValueInStack(item)) {
|
|
701
|
-
this.markRef(id);
|
|
702
|
-
this.createAddAssignment(id, this.getRefParam((item as SerovalIndexedValueNode).i));
|
|
703
|
-
return '';
|
|
704
|
-
}
|
|
705
|
-
return this.serialize(item);
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
protected serializeSet(
|
|
709
|
-
node: SerovalSetNode,
|
|
710
|
-
): string {
|
|
711
|
-
let serialized = SET_CONSTRUCTOR;
|
|
712
|
-
const size = node.l;
|
|
713
|
-
const id = node.i;
|
|
714
|
-
if (size) {
|
|
715
|
-
const items = node.a;
|
|
716
|
-
this.stack.push(id);
|
|
717
|
-
let result = this.serializeSetItem(id, items[0]);
|
|
718
|
-
for (let i = 1, item = result; i < size; i++) {
|
|
719
|
-
item = this.serializeSetItem(id, items[i]);
|
|
720
|
-
result += (item && result && ',') + item;
|
|
721
|
-
}
|
|
722
|
-
this.stack.pop();
|
|
723
|
-
if (result) {
|
|
724
|
-
serialized += '([' + result + '])';
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
return this.assignIndexedValue(id, serialized);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
protected serializeMapEntry(
|
|
731
|
-
id: number,
|
|
732
|
-
key: SerovalNode,
|
|
733
|
-
val: SerovalNode,
|
|
734
|
-
): string {
|
|
735
|
-
if (this.isIndexedValueInStack(key)) {
|
|
736
|
-
// Create reference for the map instance
|
|
737
|
-
const keyRef = this.getRefParam((key as SerovalIndexedValueNode).i);
|
|
738
|
-
this.markRef(id);
|
|
739
|
-
// Check if value is a parent
|
|
740
|
-
if (this.isIndexedValueInStack(val)) {
|
|
741
|
-
const valueRef = this.getRefParam((val as SerovalIndexedValueNode).i);
|
|
742
|
-
// Register an assignment since
|
|
743
|
-
// both key and value are a parent of this
|
|
744
|
-
// Map instance
|
|
745
|
-
this.createSetAssignment(id, keyRef, valueRef);
|
|
746
|
-
return '';
|
|
747
|
-
}
|
|
748
|
-
// Reset the stack
|
|
749
|
-
// This is required because the serialized
|
|
750
|
-
// value is no longer part of the expression
|
|
751
|
-
// tree and has been moved to the deferred
|
|
752
|
-
// assignment
|
|
753
|
-
if (val.t !== SerovalNodeType.IndexedValue && val.i != null && this.isMarked(val.i)) {
|
|
754
|
-
// We use a trick here using sequence (or comma) expressions
|
|
755
|
-
// basically we serialize the intended object in place WITHOUT
|
|
756
|
-
// actually returning it, this is by returning a placeholder
|
|
757
|
-
// value that we will remove sometime after.
|
|
758
|
-
const serialized = '(' + this.serialize(val) + ',[' + this.getSpecialReference(SpecialReference.Sentinel, false) + ',' + this.getSpecialReference(SpecialReference.Sentinel, false) + '])';
|
|
759
|
-
this.createSetAssignment(id, keyRef, this.getRefParam(val.i));
|
|
760
|
-
this.createDeleteAssignment(id, this.getSpecialReference(SpecialReference.Sentinel, false));
|
|
761
|
-
return serialized;
|
|
762
|
-
}
|
|
763
|
-
const parent = this.stack;
|
|
764
|
-
this.stack = [];
|
|
765
|
-
this.createSetAssignment(id, keyRef, this.serialize(val));
|
|
766
|
-
this.stack = parent;
|
|
767
|
-
return '';
|
|
768
|
-
}
|
|
769
|
-
if (this.isIndexedValueInStack(val)) {
|
|
770
|
-
// Create ref for the Map instance
|
|
771
|
-
const valueRef = this.getRefParam((val as SerovalIndexedValueNode).i);
|
|
772
|
-
this.markRef(id);
|
|
773
|
-
if (key.t !== SerovalNodeType.IndexedValue && key.i != null && this.isMarked(key.i)) {
|
|
774
|
-
const serialized = '(' + this.serialize(key) + ',[' + this.getSpecialReference(SpecialReference.Sentinel, false) + ',' + this.getSpecialReference(SpecialReference.Sentinel, false) + '])';
|
|
775
|
-
this.createSetAssignment(id, this.getRefParam(key.i), valueRef);
|
|
776
|
-
this.createDeleteAssignment(id, this.getSpecialReference(SpecialReference.Sentinel, false));
|
|
777
|
-
return serialized;
|
|
778
|
-
}
|
|
779
|
-
// Reset stack for the key serialization
|
|
780
|
-
const parent = this.stack;
|
|
781
|
-
this.stack = [];
|
|
782
|
-
this.createSetAssignment(id, this.serialize(key), valueRef);
|
|
783
|
-
this.stack = parent;
|
|
784
|
-
return '';
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
return '[' + this.serialize(key) + ',' + this.serialize(val) + ']';
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
protected serializeMap(
|
|
791
|
-
node: SerovalMapNode,
|
|
792
|
-
): string {
|
|
793
|
-
let serialized = MAP_CONSTRUCTOR;
|
|
794
|
-
const size = node.e.s;
|
|
795
|
-
const id = node.i;
|
|
796
|
-
if (size) {
|
|
797
|
-
const keys = node.e.k;
|
|
798
|
-
const vals = node.e.v;
|
|
799
|
-
this.stack.push(id);
|
|
800
|
-
let result = this.serializeMapEntry(id, keys[0], vals[0]);
|
|
801
|
-
for (let i = 1, item = result; i < size; i++) {
|
|
802
|
-
item = this.serializeMapEntry(id, keys[i], vals[i]);
|
|
803
|
-
result += (item && result && ',') + item;
|
|
804
|
-
}
|
|
805
|
-
this.stack.pop();
|
|
806
|
-
// Check if there are any values
|
|
807
|
-
// so that the empty Map constructor
|
|
808
|
-
// can be used instead
|
|
809
|
-
if (result) {
|
|
810
|
-
serialized += '([' + result + '])';
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
return this.assignIndexedValue(id, serialized);
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
protected serializeArrayBuffer(
|
|
817
|
-
node: SerovalArrayBufferNode,
|
|
818
|
-
): string {
|
|
819
|
-
let result = 'new Uint8Array(';
|
|
820
|
-
const buffer = node.s;
|
|
821
|
-
const len = buffer.length;
|
|
822
|
-
if (len) {
|
|
823
|
-
result += '[' + buffer[0];
|
|
824
|
-
for (let i = 1; i < len; i++) {
|
|
825
|
-
result += ',' + buffer[i];
|
|
826
|
-
}
|
|
827
|
-
result += ']';
|
|
828
|
-
}
|
|
829
|
-
return this.assignIndexedValue(node.i, result + ').buffer');
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
protected serializeTypedArray(
|
|
833
|
-
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
|
|
834
|
-
): string {
|
|
835
|
-
return this.assignIndexedValue(
|
|
836
|
-
node.i,
|
|
837
|
-
'new ' + node.c + '(' + this.serialize(node.f) + ',' + node.b + ',' + node.l + ')',
|
|
838
|
-
);
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
protected serializeDataView(
|
|
842
|
-
node: SerovalDataViewNode,
|
|
843
|
-
): string {
|
|
844
|
-
return this.assignIndexedValue(
|
|
845
|
-
node.i,
|
|
846
|
-
'new DataView(' + this.serialize(node.f) + ',' + node.b + ',' + node.l + ')',
|
|
847
|
-
);
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
protected serializeAggregateError(
|
|
851
|
-
node: SerovalAggregateErrorNode,
|
|
852
|
-
): string {
|
|
853
|
-
// Serialize the required arguments
|
|
854
|
-
const id = node.i;
|
|
855
|
-
this.stack.push(id);
|
|
856
|
-
const serialized = 'new AggregateError([],"' + node.m + '")';
|
|
857
|
-
this.stack.pop();
|
|
858
|
-
// `AggregateError` might've been extended
|
|
859
|
-
// either through class or custom properties
|
|
860
|
-
// Make sure to assign extra properties
|
|
861
|
-
return this.serializeDictionary(id, node.p, serialized);
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
protected serializeError(
|
|
865
|
-
node: SerovalErrorNode,
|
|
866
|
-
): string {
|
|
867
|
-
return this.serializeDictionary(node.i, node.p, 'new ' + ERROR_CONSTRUCTOR_STRING[node.s] + '("' + node.m + '")');
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
protected serializePromise(
|
|
871
|
-
node: SerovalPromiseNode,
|
|
872
|
-
): string {
|
|
873
|
-
let serialized: string;
|
|
874
|
-
// Check if resolved value is a parent expression
|
|
875
|
-
const fulfilled = node.f;
|
|
876
|
-
const id = node.i;
|
|
877
|
-
const specialRef = node.s ? SpecialReference.PromiseResolve : SpecialReference.PromiseReject;
|
|
878
|
-
const constructor = this.getSpecialReference(specialRef, true);
|
|
879
|
-
if (this.isIndexedValueInStack(fulfilled)) {
|
|
880
|
-
// A Promise trick, reference the value
|
|
881
|
-
// inside the `then` expression so that
|
|
882
|
-
// the Promise evaluates after the parent
|
|
883
|
-
// has initialized
|
|
884
|
-
const ref = this.getRefParam((fulfilled as SerovalIndexedValueNode).i);
|
|
885
|
-
if (this.features & Feature.ArrowFunction) {
|
|
886
|
-
if (node.s) {
|
|
887
|
-
serialized = constructor + '().then(()=>' + ref + ')';
|
|
888
|
-
} else {
|
|
889
|
-
serialized = constructor + '().catch(()=>{throw ' + ref + '})';
|
|
890
|
-
}
|
|
891
|
-
} else if (node.s) {
|
|
892
|
-
serialized = constructor + '().then(function(){return ' + ref + '})';
|
|
893
|
-
} else {
|
|
894
|
-
serialized = constructor + '().catch(function(){throw ' + ref + '})';
|
|
895
|
-
}
|
|
896
|
-
} else {
|
|
897
|
-
this.stack.push(id);
|
|
898
|
-
const result = this.serialize(fulfilled);
|
|
899
|
-
this.stack.pop();
|
|
900
|
-
// just inline the value/reference here
|
|
901
|
-
serialized = constructor + '(' + result + ')';
|
|
902
|
-
}
|
|
903
|
-
return this.assignIndexedValue(id, serialized);
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
protected serializeWKSymbol(
|
|
907
|
-
node: SerovalWKSymbolNode,
|
|
908
|
-
): string {
|
|
909
|
-
return this.assignIndexedValue(node.i, SYMBOL_STRING[node.s]);
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
protected serializeURL(
|
|
913
|
-
node: SerovalURLNode,
|
|
914
|
-
): string {
|
|
915
|
-
return this.assignIndexedValue(node.i, 'new URL("' + node.s + '")');
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
protected serializeURLSearchParams(
|
|
919
|
-
node: SerovalURLSearchParamsNode,
|
|
920
|
-
): string {
|
|
921
|
-
return this.assignIndexedValue(
|
|
922
|
-
node.i,
|
|
923
|
-
node.s ? 'new URLSearchParams("' + node.s + '")' : 'new URLSearchParams',
|
|
924
|
-
);
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
protected serializeBlob(
|
|
928
|
-
node: SerovalBlobNode,
|
|
929
|
-
): string {
|
|
930
|
-
return this.assignIndexedValue(
|
|
931
|
-
node.i,
|
|
932
|
-
'new Blob([' + this.serialize(node.f) + '],{type:"' + node.c + '"})',
|
|
933
|
-
);
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
protected serializeFile(
|
|
937
|
-
node: SerovalFileNode,
|
|
938
|
-
): string {
|
|
939
|
-
return this.assignIndexedValue(
|
|
940
|
-
node.i,
|
|
941
|
-
'new File([' + this.serialize(node.f) + '],"' + node.m + '",{type:"' + node.c + '",lastModified:' + node.b + '})',
|
|
942
|
-
);
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
protected serializeHeaders(
|
|
946
|
-
node: SerovalHeadersNode,
|
|
947
|
-
): string {
|
|
948
|
-
return this.assignIndexedValue(
|
|
949
|
-
node.i,
|
|
950
|
-
'new Headers(' + this.serializeProperties(node.i, node.e) + ')',
|
|
951
|
-
);
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
protected serializeFormDataEntry(id: number, key: string, value: SerovalNode): string {
|
|
955
|
-
return this.getRefParam(id) + '.append("' + key + '",' + this.serialize(value) + ')';
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
protected serializeFormDataEntries(
|
|
959
|
-
node: SerovalFormDataNode,
|
|
960
|
-
size: number,
|
|
961
|
-
): string {
|
|
962
|
-
const keys = node.e.k;
|
|
963
|
-
const vals = node.e.v;
|
|
964
|
-
const id = node.i;
|
|
965
|
-
let result = this.serializeFormDataEntry(id, keys[0], vals[0]);
|
|
966
|
-
for (let i = 1; i < size; i++) {
|
|
967
|
-
result += ',' + this.serializeFormDataEntry(id, keys[i], vals[i]);
|
|
968
|
-
}
|
|
969
|
-
return result;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
protected serializeFormData(
|
|
973
|
-
node: SerovalFormDataNode,
|
|
974
|
-
): string {
|
|
975
|
-
const size = node.e.s;
|
|
976
|
-
const id = node.i;
|
|
977
|
-
if (size) {
|
|
978
|
-
this.markRef(id);
|
|
979
|
-
}
|
|
980
|
-
const result = this.assignIndexedValue(id, 'new FormData()');
|
|
981
|
-
if (size) {
|
|
982
|
-
const entries = this.serializeFormDataEntries(node, size);
|
|
983
|
-
return '(' + result + ',' + (entries ? entries + ',' : '') + this.getRefParam(id) + ')';
|
|
984
|
-
}
|
|
985
|
-
return result;
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
protected serializeBoxed(
|
|
989
|
-
node: SerovalBoxedNode,
|
|
990
|
-
): string {
|
|
991
|
-
return this.assignIndexedValue(node.i, 'Object(' + this.serialize(node.f) + ')');
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
protected serializeRequest(
|
|
995
|
-
node: SerovalRequestNode,
|
|
996
|
-
): string {
|
|
997
|
-
return this.assignIndexedValue(node.i, 'new Request("' + node.s + '",' + this.serialize(node.f) + ')');
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
protected serializeResponse(
|
|
1001
|
-
node: SerovalResponseNode,
|
|
1002
|
-
): string {
|
|
1003
|
-
return this.assignIndexedValue(
|
|
1004
|
-
node.i,
|
|
1005
|
-
'new Response(' + this.serialize(node.a[0]) + ',' + this.serialize(node.a[1]) + ')',
|
|
1006
|
-
);
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
protected serializeEvent(
|
|
1010
|
-
node: SerovalEventNode,
|
|
1011
|
-
): string {
|
|
1012
|
-
return this.assignIndexedValue(
|
|
1013
|
-
node.i,
|
|
1014
|
-
'new Event("' + node.s + '",' + this.serialize(node.f) + ')',
|
|
1015
|
-
);
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
protected serializeCustomEvent(
|
|
1019
|
-
node: SerovalCustomEventNode,
|
|
1020
|
-
): string {
|
|
1021
|
-
return this.assignIndexedValue(
|
|
1022
|
-
node.i,
|
|
1023
|
-
'new CustomEvent("' + node.s + '",' + this.serialize(node.f) + ')',
|
|
1024
|
-
);
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
protected serializeDOMException(
|
|
1028
|
-
node: SerovalDOMExceptionNode,
|
|
1029
|
-
): string {
|
|
1030
|
-
return this.assignIndexedValue(
|
|
1031
|
-
node.i,
|
|
1032
|
-
'new DOMException("' + node.s + '","' + node.c + '")',
|
|
1033
|
-
);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
protected serializePlugin(
|
|
1037
|
-
node: SerovalPluginNode,
|
|
1038
|
-
): string {
|
|
1039
|
-
const currentPlugins = this.plugins;
|
|
1040
|
-
if (currentPlugins) {
|
|
1041
|
-
for (let i = 0, len = currentPlugins.length; i < len; i++) {
|
|
1042
|
-
const plugin = currentPlugins[i];
|
|
1043
|
-
if (plugin.tag === node.c) {
|
|
1044
|
-
return plugin.serialize(node.s, this, {
|
|
1045
|
-
id: node.i,
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
throw new Error('Missing plugin for tag "' + node.c + '".');
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
protected abstract serializePromiseConstructor(
|
|
1054
|
-
node: SerovalPromiseConstructorNode,
|
|
1055
|
-
): string;
|
|
1056
|
-
|
|
1057
|
-
protected abstract serializePromiseResolve(
|
|
1058
|
-
node: SerovalPromiseResolveNode,
|
|
1059
|
-
): string;
|
|
1060
|
-
|
|
1061
|
-
protected abstract serializePromiseReject(
|
|
1062
|
-
node: SerovalPromiseRejectNode,
|
|
1063
|
-
): string;
|
|
1064
|
-
|
|
1065
|
-
protected abstract serializeReadableStreamConstructor(
|
|
1066
|
-
node: SerovalReadableStreamConstructorNode,
|
|
1067
|
-
): string;
|
|
1068
|
-
|
|
1069
|
-
protected abstract serializeReadableStreamEnqueue(
|
|
1070
|
-
node: SerovalReadableStreamEnqueueNode,
|
|
1071
|
-
): string;
|
|
1072
|
-
|
|
1073
|
-
protected abstract serializeReadableStreamError(
|
|
1074
|
-
node: SerovalReadableStreamErrorNode,
|
|
1075
|
-
): string;
|
|
1076
|
-
|
|
1077
|
-
protected abstract serializeReadableStreamClose(
|
|
1078
|
-
node: SerovalReadableStreamCloseNode,
|
|
1079
|
-
): string;
|
|
1080
|
-
|
|
1081
|
-
serialize(node: SerovalNode): string {
|
|
1082
|
-
switch (node.t) {
|
|
1083
|
-
case SerovalNodeType.Constant:
|
|
1084
|
-
return CONSTANT_STRING[node.s];
|
|
1085
|
-
case SerovalNodeType.Number:
|
|
1086
|
-
return '' + node.s;
|
|
1087
|
-
case SerovalNodeType.String:
|
|
1088
|
-
return '"' + node.s + '"';
|
|
1089
|
-
case SerovalNodeType.BigInt:
|
|
1090
|
-
return node.s + 'n';
|
|
1091
|
-
case SerovalNodeType.IndexedValue:
|
|
1092
|
-
return this.getRefParam(node.i);
|
|
1093
|
-
case SerovalNodeType.Reference:
|
|
1094
|
-
return this.serializeReference(node);
|
|
1095
|
-
case SerovalNodeType.Array:
|
|
1096
|
-
return this.serializeArray(node);
|
|
1097
|
-
case SerovalNodeType.Object:
|
|
1098
|
-
return this.serializeObject(node);
|
|
1099
|
-
case SerovalNodeType.NullConstructor:
|
|
1100
|
-
return this.serializeNullConstructor(node);
|
|
1101
|
-
case SerovalNodeType.Date:
|
|
1102
|
-
return this.serializeDate(node);
|
|
1103
|
-
case SerovalNodeType.RegExp:
|
|
1104
|
-
return this.serializeRegExp(node);
|
|
1105
|
-
case SerovalNodeType.Set:
|
|
1106
|
-
return this.serializeSet(node);
|
|
1107
|
-
case SerovalNodeType.Map:
|
|
1108
|
-
return this.serializeMap(node);
|
|
1109
|
-
case SerovalNodeType.ArrayBuffer:
|
|
1110
|
-
return this.serializeArrayBuffer(node);
|
|
1111
|
-
case SerovalNodeType.BigIntTypedArray:
|
|
1112
|
-
case SerovalNodeType.TypedArray:
|
|
1113
|
-
return this.serializeTypedArray(node);
|
|
1114
|
-
case SerovalNodeType.DataView:
|
|
1115
|
-
return this.serializeDataView(node);
|
|
1116
|
-
case SerovalNodeType.AggregateError:
|
|
1117
|
-
return this.serializeAggregateError(node);
|
|
1118
|
-
case SerovalNodeType.Error:
|
|
1119
|
-
return this.serializeError(node);
|
|
1120
|
-
case SerovalNodeType.Promise:
|
|
1121
|
-
return this.serializePromise(node);
|
|
1122
|
-
case SerovalNodeType.WKSymbol:
|
|
1123
|
-
return this.serializeWKSymbol(node);
|
|
1124
|
-
case SerovalNodeType.URL:
|
|
1125
|
-
return this.serializeURL(node);
|
|
1126
|
-
case SerovalNodeType.URLSearchParams:
|
|
1127
|
-
return this.serializeURLSearchParams(node);
|
|
1128
|
-
case SerovalNodeType.Blob:
|
|
1129
|
-
return this.serializeBlob(node);
|
|
1130
|
-
case SerovalNodeType.File:
|
|
1131
|
-
return this.serializeFile(node);
|
|
1132
|
-
case SerovalNodeType.Headers:
|
|
1133
|
-
return this.serializeHeaders(node);
|
|
1134
|
-
case SerovalNodeType.FormData:
|
|
1135
|
-
return this.serializeFormData(node);
|
|
1136
|
-
case SerovalNodeType.Boxed:
|
|
1137
|
-
return this.serializeBoxed(node);
|
|
1138
|
-
case SerovalNodeType.PromiseConstructor:
|
|
1139
|
-
return this.serializePromiseConstructor(node);
|
|
1140
|
-
case SerovalNodeType.PromiseResolve:
|
|
1141
|
-
return this.serializePromiseResolve(node);
|
|
1142
|
-
case SerovalNodeType.PromiseReject:
|
|
1143
|
-
return this.serializePromiseReject(node);
|
|
1144
|
-
case SerovalNodeType.ReadableStreamConstructor:
|
|
1145
|
-
return this.serializeReadableStreamConstructor(node);
|
|
1146
|
-
case SerovalNodeType.ReadableStreamEnqueue:
|
|
1147
|
-
return this.serializeReadableStreamEnqueue(node);
|
|
1148
|
-
case SerovalNodeType.ReadableStreamError:
|
|
1149
|
-
return this.serializeReadableStreamError(node);
|
|
1150
|
-
case SerovalNodeType.ReadableStreamClose:
|
|
1151
|
-
return this.serializeReadableStreamClose(node);
|
|
1152
|
-
case SerovalNodeType.Request:
|
|
1153
|
-
return this.serializeRequest(node);
|
|
1154
|
-
case SerovalNodeType.Response:
|
|
1155
|
-
return this.serializeResponse(node);
|
|
1156
|
-
case SerovalNodeType.Event:
|
|
1157
|
-
return this.serializeEvent(node);
|
|
1158
|
-
case SerovalNodeType.CustomEvent:
|
|
1159
|
-
return this.serializeCustomEvent(node);
|
|
1160
|
-
case SerovalNodeType.DOMException:
|
|
1161
|
-
return this.serializeDOMException(node);
|
|
1162
|
-
case SerovalNodeType.Plugin:
|
|
1163
|
-
return this.serializePlugin(node);
|
|
1164
|
-
default:
|
|
1165
|
-
throw new Error('invariant');
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
}
|