seroval 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/development/index.cjs +2637 -2682
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -17
- package/dist/esm/development/index.mjs +2637 -2682
- 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 +1 -2
- package/dist/types/core/base-primitives.d.ts.map +1 -1
- package/dist/types/core/compat.d.ts +1 -1
- package/dist/types/core/compat.d.ts.map +1 -1
- package/dist/types/core/constants.d.ts +1 -0
- 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 +19 -0
- package/dist/types/core/context/async-parser.d.ts.map +1 -0
- package/dist/types/core/context/deserializer.d.ts +35 -37
- package/dist/types/core/context/deserializer.d.ts.map +1 -1
- package/dist/types/core/context/parser.d.ts +32 -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.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/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/symbols.d.ts +14 -0
- package/dist/types/core/symbols.d.ts.map +1 -0
- package/dist/types/core/tree/index.d.ts +3 -2
- package/dist/types/core/tree/index.d.ts.map +1 -1
- package/dist/types/core/types.d.ts +3 -1
- 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 +17 -19
- package/src/core/base-primitives.ts +0 -27
- package/src/core/compat.ts +2 -1
- package/src/core/constants.ts +28 -26
- package/src/core/constructors.ts +269 -0
- package/src/core/context/async-parser.ts +586 -0
- package/src/core/context/deserializer.ts +504 -307
- package/src/core/context/parser.ts +243 -180
- package/src/core/context/serializer.ts +1058 -827
- package/src/core/context/sync-parser.ts +833 -0
- package/src/core/cross/index.ts +63 -47
- package/src/core/errors.ts +73 -12
- package/src/core/function-string.ts +11 -10
- package/src/core/plugin.ts +20 -11
- package/src/core/reference.ts +8 -5
- package/src/core/special-reference.ts +18 -90
- package/src/core/stream.ts +18 -152
- package/src/core/symbols.ts +18 -0
- package/src/core/tree/index.ts +45 -31
- package/src/core/types.ts +7 -2
- package/src/core/utils/iterator-to-sequence.ts +6 -28
- package/src/index.ts +29 -11
- 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/context/parser/async.ts +0 -499
- package/src/core/context/parser/stream.ts +0 -323
- package/src/core/context/parser/sync.ts +0 -408
- package/src/core/cross/async.ts +0 -9
- package/src/core/cross/deserializer.ts +0 -16
- 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/tree/async.ts +0 -9
- package/src/core/tree/deserializer.ts +0 -26
- package/src/core/tree/serializer.ts +0 -98
- package/src/core/tree/sync.ts +0 -9
- package/src/core/utils/assert.ts +0 -5
- package/src/core/utils/deferred.ts +0 -22
|
@@ -3,19 +3,25 @@ import {
|
|
|
3
3
|
CONSTANT_STRING,
|
|
4
4
|
ERROR_CONSTRUCTOR_STRING,
|
|
5
5
|
NIL,
|
|
6
|
-
SYMBOL_STRING,
|
|
7
6
|
SerovalNodeType,
|
|
8
7
|
SerovalObjectFlags,
|
|
8
|
+
SYMBOL_STRING,
|
|
9
9
|
} from '../constants';
|
|
10
|
+
import {
|
|
11
|
+
SERIALIZED_ASYNC_ITERATOR_CONSTRUCTOR,
|
|
12
|
+
SERIALIZED_ITERATOR_CONSTRUCTOR,
|
|
13
|
+
} from '../constructors';
|
|
10
14
|
import {
|
|
11
15
|
SerovalMissingPluginError,
|
|
12
16
|
SerovalSerializationError,
|
|
13
17
|
SerovalUnsupportedNodeError,
|
|
14
18
|
} from '../errors';
|
|
15
19
|
import { createEffectfulFunction, createFunction } from '../function-string';
|
|
16
|
-
import { REFERENCES_KEY } from '../keys';
|
|
17
|
-
import type {
|
|
18
|
-
import {
|
|
20
|
+
import { GLOBAL_CONTEXT_REFERENCES, REFERENCES_KEY } from '../keys';
|
|
21
|
+
import type { PluginAccessOptions } from '../plugin';
|
|
22
|
+
import { SerovalMode } from '../plugin';
|
|
23
|
+
import { SPECIAL_REF_STRING } from '../special-reference';
|
|
24
|
+
import { serializeString } from '../string';
|
|
19
25
|
import type {
|
|
20
26
|
SerovalAggregateErrorNode,
|
|
21
27
|
SerovalArrayBufferNode,
|
|
@@ -45,14 +51,13 @@ import type {
|
|
|
45
51
|
SerovalReferenceNode,
|
|
46
52
|
SerovalRegExpNode,
|
|
47
53
|
SerovalSetNode,
|
|
48
|
-
SerovalSpecialReferenceNode,
|
|
49
54
|
SerovalStreamConstructorNode,
|
|
50
55
|
SerovalStreamNextNode,
|
|
51
56
|
SerovalStreamReturnNode,
|
|
52
57
|
SerovalStreamThrowNode,
|
|
53
58
|
SerovalTypedArrayNode,
|
|
54
|
-
SerovalWKSymbolNode,
|
|
55
59
|
} from '../types';
|
|
60
|
+
import getIdentifier from '../utils/get-identifier';
|
|
56
61
|
import { isValidIdentifier } from '../utils/is-valid-identifier';
|
|
57
62
|
|
|
58
63
|
const enum AssignmentType {
|
|
@@ -208,318 +213,377 @@ export interface BaseSerializerContextOptions extends PluginAccessOptions {
|
|
|
208
213
|
markedRefs: number[] | Set<number>;
|
|
209
214
|
}
|
|
210
215
|
|
|
211
|
-
export
|
|
212
|
-
|
|
213
|
-
{
|
|
214
|
-
/**
|
|
215
|
-
* @private
|
|
216
|
-
*/
|
|
217
|
-
features: number;
|
|
216
|
+
export interface BaseSerializerContext extends PluginAccessOptions {
|
|
217
|
+
readonly mode: SerovalMode;
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
features: number;
|
|
220
|
+
/*
|
|
220
221
|
* To check if an object is synchronously referencing itself
|
|
221
|
-
* @private
|
|
222
222
|
*/
|
|
223
|
-
stack: number[]
|
|
224
|
-
|
|
223
|
+
stack: number[];
|
|
225
224
|
/**
|
|
226
225
|
* Array of object mutations
|
|
227
|
-
* @private
|
|
228
226
|
*/
|
|
229
|
-
flags: FlaggedObject[]
|
|
230
|
-
|
|
227
|
+
flags: FlaggedObject[];
|
|
231
228
|
/**
|
|
232
229
|
* Array of assignments to be done (used for recursion)
|
|
233
|
-
* @private
|
|
234
230
|
*/
|
|
235
|
-
assignments: Assignment[]
|
|
236
|
-
|
|
237
|
-
plugins?: Plugin<any, any>[] | undefined;
|
|
238
|
-
|
|
231
|
+
assignments: Assignment[];
|
|
239
232
|
/**
|
|
240
233
|
* Refs that are...referenced
|
|
241
|
-
* @private
|
|
242
234
|
*/
|
|
243
235
|
marked: Set<number>;
|
|
236
|
+
}
|
|
244
237
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
this.marked = new Set(options.markedRefs);
|
|
249
|
-
}
|
|
238
|
+
export interface CrossContextOptions {
|
|
239
|
+
scopeId?: string;
|
|
240
|
+
}
|
|
250
241
|
|
|
251
|
-
|
|
242
|
+
export function createBaseSerializerContext(
|
|
243
|
+
mode: SerovalMode,
|
|
244
|
+
options: BaseSerializerContextOptions,
|
|
245
|
+
): BaseSerializerContext {
|
|
246
|
+
return {
|
|
247
|
+
mode,
|
|
248
|
+
plugins: options.plugins,
|
|
249
|
+
features: options.features,
|
|
250
|
+
marked: new Set(options.markedRefs),
|
|
251
|
+
stack: [],
|
|
252
|
+
flags: [],
|
|
253
|
+
assignments: [],
|
|
254
|
+
};
|
|
255
|
+
}
|
|
252
256
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
257
|
+
export interface VanillaSerializerState {
|
|
258
|
+
valid: Map<number, number>;
|
|
259
|
+
vars: string[];
|
|
260
|
+
}
|
|
256
261
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
262
|
+
function createVanillaSerializerState(): VanillaSerializerState {
|
|
263
|
+
return {
|
|
264
|
+
valid: new Map(),
|
|
265
|
+
vars: [],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
260
268
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
protected markRef(id: number): void {
|
|
268
|
-
this.marked.add(id);
|
|
269
|
-
}
|
|
269
|
+
export interface VanillaSerializerContext {
|
|
270
|
+
mode: SerovalMode.Vanilla;
|
|
271
|
+
base: BaseSerializerContext;
|
|
272
|
+
state: VanillaSerializerState;
|
|
273
|
+
child: SerializePluginContext | undefined;
|
|
274
|
+
}
|
|
270
275
|
|
|
271
|
-
|
|
272
|
-
return this.marked.has(id);
|
|
273
|
-
}
|
|
276
|
+
export type VanillaSerializerContextOptions = BaseSerializerContextOptions;
|
|
274
277
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
this.flags.push({
|
|
286
|
-
type: flag,
|
|
287
|
-
value: this.getRefParam(id),
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
}
|
|
278
|
+
export function createVanillaSerializerContext(
|
|
279
|
+
options: VanillaSerializerContextOptions,
|
|
280
|
+
): VanillaSerializerContext {
|
|
281
|
+
return {
|
|
282
|
+
mode: SerovalMode.Vanilla,
|
|
283
|
+
base: createBaseSerializerContext(SerovalMode.Vanilla, options),
|
|
284
|
+
state: createVanillaSerializerState(),
|
|
285
|
+
child: undefined,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
291
288
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
return result;
|
|
299
|
-
}
|
|
289
|
+
export interface CrossSerializerContext {
|
|
290
|
+
mode: SerovalMode.Cross;
|
|
291
|
+
base: BaseSerializerContext;
|
|
292
|
+
state: CrossContextOptions;
|
|
293
|
+
child: SerializePluginContext | undefined;
|
|
294
|
+
}
|
|
300
295
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
296
|
+
export interface CrossSerializerContextOptions
|
|
297
|
+
extends BaseSerializerContextOptions,
|
|
298
|
+
CrossContextOptions {
|
|
299
|
+
// empty
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function createCrossSerializerContext(
|
|
303
|
+
options: CrossSerializerContextOptions,
|
|
304
|
+
): CrossSerializerContext {
|
|
305
|
+
return {
|
|
306
|
+
mode: SerovalMode.Cross,
|
|
307
|
+
base: createBaseSerializerContext(SerovalMode.Cross, options),
|
|
308
|
+
state: options,
|
|
309
|
+
child: undefined,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
type SerializerContext = VanillaSerializerContext | CrossSerializerContext;
|
|
314
|
+
|
|
315
|
+
export class SerializePluginContext {
|
|
316
|
+
constructor(private _p: SerializerContext) {}
|
|
317
|
+
|
|
318
|
+
serialize(node: SerovalNode) {
|
|
319
|
+
return serialize(this._p, node);
|
|
311
320
|
}
|
|
321
|
+
}
|
|
312
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Creates the reference param (identifier) from the given reference ID
|
|
325
|
+
* Calling this function means the value has been referenced somewhere
|
|
326
|
+
*/
|
|
327
|
+
function getVanillaRefParam(
|
|
328
|
+
state: VanillaSerializerState,
|
|
329
|
+
index: number,
|
|
330
|
+
): string {
|
|
313
331
|
/**
|
|
314
|
-
*
|
|
315
|
-
* This
|
|
316
|
-
*
|
|
332
|
+
* Creates a new reference ID from a given reference ID
|
|
333
|
+
* This new reference ID means that the reference itself
|
|
334
|
+
* has been referenced at least once, and is used to generate
|
|
335
|
+
* the variables
|
|
317
336
|
*/
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
k: NIL,
|
|
323
|
-
v: value,
|
|
324
|
-
});
|
|
337
|
+
let actualIndex = state.valid.get(index);
|
|
338
|
+
if (actualIndex == null) {
|
|
339
|
+
actualIndex = state.valid.size;
|
|
340
|
+
state.valid.set(index, actualIndex);
|
|
325
341
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
s: this.getRefParam(ref),
|
|
331
|
-
k: NIL,
|
|
332
|
-
v: value,
|
|
333
|
-
});
|
|
342
|
+
let identifier = state.vars[actualIndex];
|
|
343
|
+
if (identifier == null) {
|
|
344
|
+
identifier = getIdentifier(actualIndex);
|
|
345
|
+
state.vars[actualIndex] = identifier;
|
|
334
346
|
}
|
|
347
|
+
return identifier;
|
|
348
|
+
}
|
|
335
349
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
350
|
+
function getCrossRefParam(id: number): string {
|
|
351
|
+
return GLOBAL_CONTEXT_REFERENCES + '[' + id + ']';
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Converts the ID of a reference into a identifier string
|
|
356
|
+
* that is used to refer to the object instance in the
|
|
357
|
+
* generated script.
|
|
358
|
+
*/
|
|
359
|
+
function getRefParam(ctx: SerializerContext, id: number): string {
|
|
360
|
+
return ctx.mode === SerovalMode.Vanilla
|
|
361
|
+
? getVanillaRefParam(ctx.state, id)
|
|
362
|
+
: getCrossRefParam(id);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function markSerializerRef(ctx: BaseSerializerContext, id: number): void {
|
|
366
|
+
ctx.marked.add(id);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function isSerializerRefMarked(
|
|
370
|
+
ctx: BaseSerializerContext,
|
|
371
|
+
id: number,
|
|
372
|
+
): boolean {
|
|
373
|
+
return ctx.marked.has(id);
|
|
374
|
+
}
|
|
344
375
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
376
|
+
function pushObjectFlag(
|
|
377
|
+
ctx: SerializerContext,
|
|
378
|
+
flag: SerovalObjectFlags,
|
|
379
|
+
id: number,
|
|
380
|
+
): void {
|
|
381
|
+
if (flag !== SerovalObjectFlags.None) {
|
|
382
|
+
markSerializerRef(ctx.base, id);
|
|
383
|
+
ctx.base.flags.push({
|
|
384
|
+
type: flag,
|
|
385
|
+
value: getRefParam(ctx, id),
|
|
351
386
|
});
|
|
352
387
|
}
|
|
388
|
+
}
|
|
353
389
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
this.createAssignment(this.getRefParam(ref) + '[' + index + ']', value);
|
|
390
|
+
function resolveFlags(ctx: BaseSerializerContext): string | undefined {
|
|
391
|
+
let result = '';
|
|
392
|
+
for (let i = 0, current = ctx.flags, len = current.length; i < len; i++) {
|
|
393
|
+
const flag = current[i];
|
|
394
|
+
result += OBJECT_FLAG_CONSTRUCTOR[flag.type] + '(' + flag.value + '),';
|
|
360
395
|
}
|
|
396
|
+
return result;
|
|
397
|
+
}
|
|
361
398
|
|
|
362
|
-
|
|
363
|
-
|
|
399
|
+
function resolvePatches(ctx: BaseSerializerContext): string | undefined {
|
|
400
|
+
const assignments = resolveAssignments(ctx.assignments);
|
|
401
|
+
const flags = resolveFlags(ctx);
|
|
402
|
+
if (assignments) {
|
|
403
|
+
if (flags) {
|
|
404
|
+
return assignments + flags;
|
|
405
|
+
}
|
|
406
|
+
return assignments;
|
|
364
407
|
}
|
|
408
|
+
return flags;
|
|
409
|
+
}
|
|
365
410
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
411
|
+
/**
|
|
412
|
+
* Generates the inlined assignment for the reference
|
|
413
|
+
* This is different from the assignments array as this one
|
|
414
|
+
* signifies creation rather than mutation
|
|
415
|
+
*/
|
|
416
|
+
function createAssignment(
|
|
417
|
+
ctx: BaseSerializerContext,
|
|
418
|
+
source: string,
|
|
419
|
+
value: string,
|
|
420
|
+
): void {
|
|
421
|
+
ctx.assignments.push({
|
|
422
|
+
t: AssignmentType.Index,
|
|
423
|
+
s: source,
|
|
424
|
+
k: NIL,
|
|
425
|
+
v: value,
|
|
426
|
+
});
|
|
427
|
+
}
|
|
375
428
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
429
|
+
function createAddAssignment(
|
|
430
|
+
ctx: SerializerContext,
|
|
431
|
+
ref: number,
|
|
432
|
+
value: string,
|
|
433
|
+
): void {
|
|
434
|
+
ctx.base.assignments.push({
|
|
435
|
+
t: AssignmentType.Add,
|
|
436
|
+
s: getRefParam(ctx, ref),
|
|
437
|
+
k: NIL,
|
|
438
|
+
v: value,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
383
441
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
442
|
+
function createSetAssignment(
|
|
443
|
+
ctx: SerializerContext,
|
|
444
|
+
ref: number,
|
|
445
|
+
key: string,
|
|
446
|
+
value: string,
|
|
447
|
+
): void {
|
|
448
|
+
ctx.base.assignments.push({
|
|
449
|
+
t: AssignmentType.Set,
|
|
450
|
+
s: getRefParam(ctx, ref),
|
|
451
|
+
k: key,
|
|
452
|
+
v: value,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
390
455
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
index,
|
|
404
|
-
this.getRefParam((item as SerovalIndexedValueNode).i),
|
|
405
|
-
);
|
|
406
|
-
return '';
|
|
407
|
-
}
|
|
408
|
-
return this.serialize(item);
|
|
409
|
-
}
|
|
410
|
-
return '';
|
|
411
|
-
}
|
|
456
|
+
function createDeleteAssignment(
|
|
457
|
+
ctx: SerializerContext,
|
|
458
|
+
ref: number,
|
|
459
|
+
key: string,
|
|
460
|
+
): void {
|
|
461
|
+
ctx.base.assignments.push({
|
|
462
|
+
t: AssignmentType.Delete,
|
|
463
|
+
s: getRefParam(ctx, ref),
|
|
464
|
+
k: key,
|
|
465
|
+
v: NIL,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
412
468
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
// the holes of the Array
|
|
422
|
-
let isHoley = values === '';
|
|
423
|
-
for (let i = 1, len = node.l, item: string; i < len; i++) {
|
|
424
|
-
item = this.serializeArrayItem(id, list[i], i);
|
|
425
|
-
values += ',' + item;
|
|
426
|
-
isHoley = item === '';
|
|
427
|
-
}
|
|
428
|
-
this.stack.pop();
|
|
429
|
-
this.pushObjectFlag(node.o, node.i);
|
|
430
|
-
return this.assignIndexedValue(id, '[' + values + (isHoley ? ',]' : ']'));
|
|
431
|
-
}
|
|
432
|
-
return this.assignIndexedValue(id, '[]');
|
|
433
|
-
}
|
|
469
|
+
function createArrayAssign(
|
|
470
|
+
ctx: SerializerContext,
|
|
471
|
+
ref: number,
|
|
472
|
+
index: number | string,
|
|
473
|
+
value: string,
|
|
474
|
+
): void {
|
|
475
|
+
createAssignment(ctx.base, getRefParam(ctx, ref) + '[' + index + ']', value);
|
|
476
|
+
}
|
|
434
477
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
// Test if key is a valid positive number or JS identifier
|
|
444
|
-
// so that we don't have to serialize the key and wrap with brackets
|
|
445
|
-
(check >= 0 &&
|
|
446
|
-
// It's also important to consider that if the key is
|
|
447
|
-
// indeed numeric, we need to make sure that when
|
|
448
|
-
// converted back into a string, it's still the same
|
|
449
|
-
// to the original key. This allows us to differentiate
|
|
450
|
-
// keys that has numeric formats but in a different
|
|
451
|
-
// format, which can cause unintentional key declaration
|
|
452
|
-
// Example: { 0x1: 1 } vs { '0x1': 1 }
|
|
453
|
-
check.toString() === key) ||
|
|
454
|
-
isValidIdentifier(key);
|
|
455
|
-
if (this.isIndexedValueInStack(val)) {
|
|
456
|
-
const refParam = this.getRefParam((val as SerovalIndexedValueNode).i);
|
|
457
|
-
this.markRef(source.i);
|
|
458
|
-
// Strict identifier check, make sure
|
|
459
|
-
// that it isn't numeric (except NaN)
|
|
460
|
-
if (isIdentifier && check !== check) {
|
|
461
|
-
this.createObjectAssign(source.i, key, refParam);
|
|
462
|
-
} else {
|
|
463
|
-
this.createArrayAssign(
|
|
464
|
-
source.i,
|
|
465
|
-
isIdentifier ? key : '"' + key + '"',
|
|
466
|
-
refParam,
|
|
467
|
-
);
|
|
468
|
-
}
|
|
469
|
-
return '';
|
|
470
|
-
}
|
|
471
|
-
return (isIdentifier ? key : '"' + key + '"') + ':' + this.serialize(val);
|
|
472
|
-
}
|
|
473
|
-
return '[' + this.serialize(key) + ']:' + this.serialize(val);
|
|
474
|
-
}
|
|
478
|
+
function createObjectAssign(
|
|
479
|
+
ctx: SerializerContext,
|
|
480
|
+
ref: number,
|
|
481
|
+
key: string,
|
|
482
|
+
value: string,
|
|
483
|
+
): void {
|
|
484
|
+
createAssignment(ctx.base, getRefParam(ctx, ref) + '.' + key, value);
|
|
485
|
+
}
|
|
475
486
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
487
|
+
/**
|
|
488
|
+
* Checks if the value is in the stack. Stack here is a reference
|
|
489
|
+
* structure to know if a object is to be accessed in a TDZ.
|
|
490
|
+
*/
|
|
491
|
+
function isIndexedValueInStack(
|
|
492
|
+
ctx: BaseSerializerContext,
|
|
493
|
+
node: SerovalNode,
|
|
494
|
+
): boolean {
|
|
495
|
+
return node.t === SerovalNodeType.IndexedValue && ctx.stack.includes(node.i);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Produces an assignment expression. `id` generates a reference
|
|
500
|
+
* parameter (through `getRefParam`) and has the option to
|
|
501
|
+
* return the reference parameter directly or assign a value to
|
|
502
|
+
* it.
|
|
503
|
+
*/
|
|
504
|
+
function assignIndexedValue(
|
|
505
|
+
ctx: SerializerContext,
|
|
506
|
+
index: number,
|
|
507
|
+
value: string,
|
|
508
|
+
): string {
|
|
509
|
+
if (
|
|
510
|
+
ctx.mode === SerovalMode.Vanilla &&
|
|
511
|
+
!isSerializerRefMarked(ctx.base, index)
|
|
512
|
+
) {
|
|
513
|
+
return value;
|
|
494
514
|
}
|
|
515
|
+
/**
|
|
516
|
+
* In cross-reference, we have to assume that
|
|
517
|
+
* every reference are going to be referenced
|
|
518
|
+
* in the future, and so we need to store
|
|
519
|
+
* all of it into the reference array.
|
|
520
|
+
*
|
|
521
|
+
* otherwise in vanilla, we only do this if it
|
|
522
|
+
* is actually referenced
|
|
523
|
+
*/
|
|
524
|
+
return getRefParam(ctx, index) + '=' + value;
|
|
525
|
+
}
|
|
495
526
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
527
|
+
function serializeReference(node: SerovalReferenceNode): string {
|
|
528
|
+
return REFERENCES_KEY + '.get("' + node.s + '")';
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function serializeArrayItem(
|
|
532
|
+
ctx: SerializerContext,
|
|
533
|
+
id: number,
|
|
534
|
+
item: SerovalNode | undefined,
|
|
535
|
+
index: number,
|
|
536
|
+
): string {
|
|
537
|
+
// Check if index is a hole
|
|
538
|
+
if (item) {
|
|
539
|
+
// Check if item is a parent
|
|
540
|
+
if (isIndexedValueInStack(ctx.base, item)) {
|
|
541
|
+
markSerializerRef(ctx.base, id);
|
|
542
|
+
createArrayAssign(
|
|
543
|
+
ctx,
|
|
544
|
+
id,
|
|
545
|
+
index,
|
|
546
|
+
getRefParam(ctx, (item as SerovalIndexedValueNode).i),
|
|
547
|
+
);
|
|
548
|
+
return '';
|
|
549
|
+
}
|
|
550
|
+
return serialize(ctx, item);
|
|
502
551
|
}
|
|
552
|
+
return '';
|
|
553
|
+
}
|
|
503
554
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
555
|
+
function serializeArray(
|
|
556
|
+
ctx: SerializerContext,
|
|
557
|
+
node: SerovalArrayNode,
|
|
558
|
+
): string {
|
|
559
|
+
const id = node.i;
|
|
560
|
+
if (node.l) {
|
|
561
|
+
ctx.base.stack.push(id);
|
|
562
|
+
const list = node.a;
|
|
563
|
+
let values = serializeArrayItem(ctx, id, list[0], 0);
|
|
564
|
+
// This is different than Map and Set
|
|
565
|
+
// because we also need to serialize
|
|
566
|
+
// the holes of the Array
|
|
567
|
+
let isHoley = values === '';
|
|
568
|
+
for (let i = 1, len = node.l, item: string; i < len; i++) {
|
|
569
|
+
item = serializeArrayItem(ctx, id, list[i], i);
|
|
570
|
+
values += ',' + item;
|
|
571
|
+
isHoley = item === '';
|
|
512
572
|
}
|
|
513
|
-
|
|
573
|
+
ctx.base.stack.pop();
|
|
574
|
+
pushObjectFlag(ctx, node.o, node.i);
|
|
575
|
+
return '[' + values + (isHoley ? ',]' : ']');
|
|
514
576
|
}
|
|
577
|
+
return '[]';
|
|
578
|
+
}
|
|
515
579
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
580
|
+
function serializeProperty(
|
|
581
|
+
ctx: SerializerContext,
|
|
582
|
+
source: SerovalNodeWithProperties,
|
|
583
|
+
key: SerovalObjectRecordKey,
|
|
584
|
+
val: SerovalNode,
|
|
585
|
+
): string {
|
|
586
|
+
if (typeof key === 'string') {
|
|
523
587
|
const check = Number(key);
|
|
524
588
|
const isIdentifier =
|
|
525
589
|
// Test if key is a valid positive number or JS identifier
|
|
@@ -534,647 +598,814 @@ export default abstract class BaseSerializerContext
|
|
|
534
598
|
// Example: { 0x1: 1 } vs { '0x1': 1 }
|
|
535
599
|
check.toString() === key) ||
|
|
536
600
|
isValidIdentifier(key);
|
|
537
|
-
if (
|
|
601
|
+
if (isIndexedValueInStack(ctx.base, val)) {
|
|
602
|
+
const refParam = getRefParam(ctx, (val as SerovalIndexedValueNode).i);
|
|
603
|
+
markSerializerRef(ctx.base, source.i);
|
|
538
604
|
// Strict identifier check, make sure
|
|
539
605
|
// that it isn't numeric (except NaN)
|
|
540
606
|
if (isIdentifier && check !== check) {
|
|
541
|
-
|
|
542
|
-
} else {
|
|
543
|
-
this.createArrayAssign(
|
|
544
|
-
source.i,
|
|
545
|
-
isIdentifier ? key : '"' + key + '"',
|
|
546
|
-
serialized,
|
|
547
|
-
);
|
|
548
|
-
}
|
|
549
|
-
} else {
|
|
550
|
-
const parentAssignment = this.assignments;
|
|
551
|
-
this.assignments = mainAssignments;
|
|
552
|
-
if (isIdentifier && check !== check) {
|
|
553
|
-
this.createObjectAssign(source.i, key, serialized);
|
|
607
|
+
createObjectAssign(ctx, source.i, key, refParam);
|
|
554
608
|
} else {
|
|
555
|
-
|
|
609
|
+
createArrayAssign(
|
|
610
|
+
ctx,
|
|
556
611
|
source.i,
|
|
557
612
|
isIdentifier ? key : '"' + key + '"',
|
|
558
|
-
|
|
613
|
+
refParam,
|
|
559
614
|
);
|
|
560
615
|
}
|
|
561
|
-
|
|
616
|
+
return '';
|
|
562
617
|
}
|
|
618
|
+
return (isIdentifier ? key : '"' + key + '"') + ':' + serialize(ctx, val);
|
|
563
619
|
}
|
|
620
|
+
return '[' + serialize(ctx, key) + ']:' + serialize(ctx, val);
|
|
621
|
+
}
|
|
564
622
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
this.assignments = mainAssignments;
|
|
580
|
-
this.createArrayAssign(source.i, this.serialize(key), serialized);
|
|
581
|
-
this.assignments = parentAssignment;
|
|
623
|
+
function serializeProperties(
|
|
624
|
+
ctx: SerializerContext,
|
|
625
|
+
source: SerovalNodeWithProperties,
|
|
626
|
+
record: SerovalObjectRecordNode,
|
|
627
|
+
): string {
|
|
628
|
+
const len = record.s;
|
|
629
|
+
if (len) {
|
|
630
|
+
const keys = record.k;
|
|
631
|
+
const values = record.v;
|
|
632
|
+
ctx.base.stack.push(source.i);
|
|
633
|
+
let result = serializeProperty(ctx, source, keys[0], values[0]);
|
|
634
|
+
for (let i = 1, item = result; i < len; i++) {
|
|
635
|
+
item = serializeProperty(ctx, source, keys[i], values[i]);
|
|
636
|
+
result += (item && result && ',') + item;
|
|
582
637
|
}
|
|
638
|
+
ctx.base.stack.pop();
|
|
639
|
+
return '{' + result + '}';
|
|
583
640
|
}
|
|
641
|
+
return '{}';
|
|
642
|
+
}
|
|
584
643
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
return
|
|
644
|
+
function serializeObject(
|
|
645
|
+
ctx: SerializerContext,
|
|
646
|
+
node: SerovalObjectNode,
|
|
647
|
+
): string {
|
|
648
|
+
pushObjectFlag(ctx, node.o, node.i);
|
|
649
|
+
return serializeProperties(ctx, node, node.p);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function serializeWithObjectAssign(
|
|
653
|
+
ctx: SerializerContext,
|
|
654
|
+
source: SerovalNodeWithProperties,
|
|
655
|
+
value: SerovalObjectRecordNode,
|
|
656
|
+
serialized: string,
|
|
657
|
+
): string {
|
|
658
|
+
const fields = serializeProperties(ctx, source, value);
|
|
659
|
+
if (fields !== '{}') {
|
|
660
|
+
return 'Object.assign(' + serialized + ',' + fields + ')';
|
|
602
661
|
}
|
|
662
|
+
return serialized;
|
|
663
|
+
}
|
|
603
664
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
}
|
|
665
|
+
function serializeStringKeyAssignment(
|
|
666
|
+
ctx: SerializerContext,
|
|
667
|
+
source: SerovalNodeWithProperties,
|
|
668
|
+
mainAssignments: Assignment[],
|
|
669
|
+
key: string,
|
|
670
|
+
value: SerovalNode,
|
|
671
|
+
): void {
|
|
672
|
+
const base = ctx.base;
|
|
673
|
+
const serialized = serialize(ctx, value);
|
|
674
|
+
const check = Number(key);
|
|
675
|
+
const isIdentifier =
|
|
676
|
+
// Test if key is a valid positive number or JS identifier
|
|
677
|
+
// so that we don't have to serialize the key and wrap with brackets
|
|
678
|
+
(check >= 0 &&
|
|
679
|
+
// It's also important to consider that if the key is
|
|
680
|
+
// indeed numeric, we need to make sure that when
|
|
681
|
+
// converted back into a string, it's still the same
|
|
682
|
+
// to the original key. This allows us to differentiate
|
|
683
|
+
// keys that has numeric formats but in a different
|
|
684
|
+
// format, which can cause unintentional key declaration
|
|
685
|
+
// Example: { 0x1: 1 } vs { '0x1': 1 }
|
|
686
|
+
check.toString() === key) ||
|
|
687
|
+
isValidIdentifier(key);
|
|
688
|
+
if (isIndexedValueInStack(base, value)) {
|
|
689
|
+
// Strict identifier check, make sure
|
|
690
|
+
// that it isn't numeric (except NaN)
|
|
691
|
+
if (isIdentifier && check !== check) {
|
|
692
|
+
createObjectAssign(ctx, source.i, key, serialized);
|
|
693
|
+
} else {
|
|
694
|
+
createArrayAssign(
|
|
695
|
+
ctx,
|
|
696
|
+
source.i,
|
|
697
|
+
isIdentifier ? key : '"' + key + '"',
|
|
698
|
+
serialized,
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
} else {
|
|
702
|
+
const parentAssignment = base.assignments;
|
|
703
|
+
base.assignments = mainAssignments;
|
|
704
|
+
if (isIdentifier && check !== check) {
|
|
705
|
+
createObjectAssign(ctx, source.i, key, serialized);
|
|
706
|
+
} else {
|
|
707
|
+
createArrayAssign(
|
|
708
|
+
ctx,
|
|
709
|
+
source.i,
|
|
710
|
+
isIdentifier ? key : '"' + key + '"',
|
|
711
|
+
serialized,
|
|
712
|
+
);
|
|
625
713
|
}
|
|
626
|
-
|
|
714
|
+
base.assignments = parentAssignment;
|
|
627
715
|
}
|
|
716
|
+
}
|
|
628
717
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
718
|
+
function serializeAssignment(
|
|
719
|
+
ctx: SerializerContext,
|
|
720
|
+
source: SerovalNodeWithProperties,
|
|
721
|
+
mainAssignments: Assignment[],
|
|
722
|
+
key: SerovalObjectRecordKey,
|
|
723
|
+
value: SerovalNode,
|
|
724
|
+
): void {
|
|
725
|
+
if (typeof key === 'string') {
|
|
726
|
+
serializeStringKeyAssignment(ctx, source, mainAssignments, key, value);
|
|
727
|
+
} else {
|
|
728
|
+
const base = ctx.base;
|
|
729
|
+
const parent = base.stack;
|
|
730
|
+
base.stack = [];
|
|
731
|
+
const serialized = serialize(ctx, value);
|
|
732
|
+
base.stack = parent;
|
|
733
|
+
const parentAssignment = base.assignments;
|
|
734
|
+
base.assignments = mainAssignments;
|
|
735
|
+
createArrayAssign(ctx, source.i, serialize(ctx, key), serialized);
|
|
736
|
+
base.assignments = parentAssignment;
|
|
632
737
|
}
|
|
738
|
+
}
|
|
633
739
|
|
|
634
|
-
|
|
635
|
-
|
|
740
|
+
function serializeAssignments(
|
|
741
|
+
ctx: SerializerContext,
|
|
742
|
+
source: SerovalNodeWithProperties,
|
|
743
|
+
node: SerovalObjectRecordNode,
|
|
744
|
+
): string | undefined {
|
|
745
|
+
const len = node.s;
|
|
746
|
+
if (len) {
|
|
747
|
+
const mainAssignments: Assignment[] = [];
|
|
748
|
+
const keys = node.k;
|
|
749
|
+
const values = node.v;
|
|
750
|
+
ctx.base.stack.push(source.i);
|
|
751
|
+
for (let i = 0; i < len; i++) {
|
|
752
|
+
serializeAssignment(ctx, source, mainAssignments, keys[i], values[i]);
|
|
753
|
+
}
|
|
754
|
+
ctx.base.stack.pop();
|
|
755
|
+
return resolveAssignments(mainAssignments);
|
|
636
756
|
}
|
|
757
|
+
return NIL;
|
|
758
|
+
}
|
|
637
759
|
|
|
638
|
-
|
|
639
|
-
|
|
760
|
+
function serializeDictionary(
|
|
761
|
+
ctx: SerializerContext,
|
|
762
|
+
node: SerovalNodeWithProperties,
|
|
763
|
+
init: string,
|
|
764
|
+
): string {
|
|
765
|
+
if (node.p) {
|
|
766
|
+
const base = ctx.base;
|
|
767
|
+
if (base.features & Feature.ObjectAssign) {
|
|
768
|
+
init = serializeWithObjectAssign(ctx, node, node.p, init);
|
|
769
|
+
} else {
|
|
770
|
+
markSerializerRef(base, node.i);
|
|
771
|
+
const assignments = serializeAssignments(ctx, node, node.p);
|
|
772
|
+
if (assignments) {
|
|
773
|
+
return (
|
|
774
|
+
'(' +
|
|
775
|
+
assignIndexedValue(ctx, node.i, init) +
|
|
776
|
+
',' +
|
|
777
|
+
assignments +
|
|
778
|
+
getRefParam(ctx, node.i) +
|
|
779
|
+
')'
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
640
783
|
}
|
|
784
|
+
return init;
|
|
785
|
+
}
|
|
641
786
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
787
|
+
function serializeNullConstructor(
|
|
788
|
+
ctx: SerializerContext,
|
|
789
|
+
node: SerovalNullConstructorNode,
|
|
790
|
+
): string {
|
|
791
|
+
pushObjectFlag(ctx, node.o, node.i);
|
|
792
|
+
return serializeDictionary(ctx, node, NULL_CONSTRUCTOR);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
function serializeDate(node: SerovalDateNode): string {
|
|
796
|
+
return 'new Date("' + node.s + '")';
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
function serializeRegExp(node: SerovalRegExpNode): string {
|
|
800
|
+
return '/' + node.c + '/' + node.m;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function serializeSetItem(
|
|
804
|
+
ctx: SerializerContext,
|
|
805
|
+
id: number,
|
|
806
|
+
item: SerovalNode,
|
|
807
|
+
): string {
|
|
808
|
+
const base = ctx.base;
|
|
809
|
+
if (isIndexedValueInStack(base, item)) {
|
|
810
|
+
markSerializerRef(base, id);
|
|
811
|
+
createAddAssignment(
|
|
812
|
+
ctx,
|
|
813
|
+
id,
|
|
814
|
+
getRefParam(ctx, (item as SerovalIndexedValueNode).i),
|
|
815
|
+
);
|
|
816
|
+
return '';
|
|
652
817
|
}
|
|
818
|
+
return serialize(ctx, item);
|
|
819
|
+
}
|
|
653
820
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
}
|
|
821
|
+
function serializeSet(ctx: SerializerContext, node: SerovalSetNode): string {
|
|
822
|
+
let serialized = SET_CONSTRUCTOR;
|
|
823
|
+
const size = node.l;
|
|
824
|
+
const id = node.i;
|
|
825
|
+
if (size) {
|
|
826
|
+
const items = node.a;
|
|
827
|
+
ctx.base.stack.push(id);
|
|
828
|
+
let result = serializeSetItem(ctx, id, items[0]);
|
|
829
|
+
for (let i = 1, item = result; i < size; i++) {
|
|
830
|
+
item = serializeSetItem(ctx, id, items[i]);
|
|
831
|
+
result += (item && result && ',') + item;
|
|
832
|
+
}
|
|
833
|
+
ctx.base.stack.pop();
|
|
834
|
+
if (result) {
|
|
835
|
+
serialized += '([' + result + '])';
|
|
670
836
|
}
|
|
671
|
-
return this.assignIndexedValue(id, serialized);
|
|
672
837
|
}
|
|
838
|
+
return serialized;
|
|
839
|
+
}
|
|
673
840
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
// Reset the stack
|
|
694
|
-
// This is required because the serialized
|
|
695
|
-
// value is no longer part of the expression
|
|
696
|
-
// tree and has been moved to the deferred
|
|
697
|
-
// assignment
|
|
698
|
-
if (
|
|
699
|
-
val.t !== SerovalNodeType.IndexedValue &&
|
|
700
|
-
val.i != null &&
|
|
701
|
-
this.isMarked(val.i)
|
|
702
|
-
) {
|
|
703
|
-
// We use a trick here using sequence (or comma) expressions
|
|
704
|
-
// basically we serialize the intended object in place WITHOUT
|
|
705
|
-
// actually returning it, this is by returning a placeholder
|
|
706
|
-
// value that we will remove sometime after.
|
|
707
|
-
const serialized =
|
|
708
|
-
'(' + this.serialize(val) + ',[' + sentinel + ',' + sentinel + '])';
|
|
709
|
-
this.createSetAssignment(id, keyRef, this.getRefParam(val.i));
|
|
710
|
-
this.createDeleteAssignment(id, sentinel);
|
|
711
|
-
return serialized;
|
|
712
|
-
}
|
|
713
|
-
const parent = this.stack;
|
|
714
|
-
this.stack = [];
|
|
715
|
-
this.createSetAssignment(id, keyRef, this.serialize(val));
|
|
716
|
-
this.stack = parent;
|
|
841
|
+
function serializeMapEntry(
|
|
842
|
+
ctx: SerializerContext,
|
|
843
|
+
id: number,
|
|
844
|
+
key: SerovalNode,
|
|
845
|
+
val: SerovalNode,
|
|
846
|
+
sentinel: string,
|
|
847
|
+
): string {
|
|
848
|
+
const base = ctx.base;
|
|
849
|
+
if (isIndexedValueInStack(base, key)) {
|
|
850
|
+
// Create reference for the map instance
|
|
851
|
+
const keyRef = getRefParam(ctx, (key as SerovalIndexedValueNode).i);
|
|
852
|
+
markSerializerRef(base, id);
|
|
853
|
+
// Check if value is a parent
|
|
854
|
+
if (isIndexedValueInStack(base, val)) {
|
|
855
|
+
const valueRef = getRefParam(ctx, (val as SerovalIndexedValueNode).i);
|
|
856
|
+
// Register an assignment since
|
|
857
|
+
// both key and value are a parent of this
|
|
858
|
+
// Map instance
|
|
859
|
+
createSetAssignment(ctx, id, keyRef, valueRef);
|
|
717
860
|
return '';
|
|
718
861
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
)
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
this.stack = parent;
|
|
739
|
-
return '';
|
|
862
|
+
// Reset the stack
|
|
863
|
+
// This is required because the serialized
|
|
864
|
+
// value is no longer part of the expression
|
|
865
|
+
// tree and has been moved to the deferred
|
|
866
|
+
// assignment
|
|
867
|
+
if (
|
|
868
|
+
val.t !== SerovalNodeType.IndexedValue &&
|
|
869
|
+
val.i != null &&
|
|
870
|
+
isSerializerRefMarked(base, val.i)
|
|
871
|
+
) {
|
|
872
|
+
// We use a trick here using sequence (or comma) expressions
|
|
873
|
+
// basically we serialize the intended object in place WITHOUT
|
|
874
|
+
// actually returning it, this is by returning a placeholder
|
|
875
|
+
// value that we will remove sometime after.
|
|
876
|
+
const serialized =
|
|
877
|
+
'(' + serialize(ctx, val) + ',[' + sentinel + ',' + sentinel + '])';
|
|
878
|
+
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
879
|
+
createDeleteAssignment(ctx, id, sentinel);
|
|
880
|
+
return serialized;
|
|
740
881
|
}
|
|
741
|
-
|
|
742
|
-
|
|
882
|
+
const parent = base.stack;
|
|
883
|
+
base.stack = [];
|
|
884
|
+
createSetAssignment(ctx, id, keyRef, serialize(ctx, val));
|
|
885
|
+
base.stack = parent;
|
|
886
|
+
return '';
|
|
743
887
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
result += (item && result && ',') + item;
|
|
759
|
-
}
|
|
760
|
-
this.stack.pop();
|
|
761
|
-
// Check if there are any values
|
|
762
|
-
// so that the empty Map constructor
|
|
763
|
-
// can be used instead
|
|
764
|
-
if (result) {
|
|
765
|
-
serialized += '([' + result + '])';
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
if (sentinel.t === SerovalNodeType.SpecialReference) {
|
|
769
|
-
this.markRef(sentinel.i);
|
|
770
|
-
serialized = '(' + this.serialize(sentinel) + ',' + serialized + ')';
|
|
888
|
+
if (isIndexedValueInStack(base, val)) {
|
|
889
|
+
// Create ref for the Map instance
|
|
890
|
+
const valueRef = getRefParam(ctx, (val as SerovalIndexedValueNode).i);
|
|
891
|
+
markSerializerRef(base, id);
|
|
892
|
+
if (
|
|
893
|
+
key.t !== SerovalNodeType.IndexedValue &&
|
|
894
|
+
key.i != null &&
|
|
895
|
+
isSerializerRefMarked(base, key.i)
|
|
896
|
+
) {
|
|
897
|
+
const serialized =
|
|
898
|
+
'(' + serialize(ctx, key) + ',[' + sentinel + ',' + sentinel + '])';
|
|
899
|
+
createSetAssignment(ctx, id, getRefParam(ctx, key.i), valueRef);
|
|
900
|
+
createDeleteAssignment(ctx, id, sentinel);
|
|
901
|
+
return serialized;
|
|
771
902
|
}
|
|
772
|
-
|
|
903
|
+
// Reset stack for the key serialization
|
|
904
|
+
const parent = base.stack;
|
|
905
|
+
base.stack = [];
|
|
906
|
+
createSetAssignment(ctx, id, serialize(ctx, key), valueRef);
|
|
907
|
+
base.stack = parent;
|
|
908
|
+
return '';
|
|
773
909
|
}
|
|
774
910
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
911
|
+
return '[' + serialize(ctx, key) + ',' + serialize(ctx, val) + ']';
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
function serializeMap(ctx: SerializerContext, node: SerovalMapNode): string {
|
|
915
|
+
let serialized = MAP_CONSTRUCTOR;
|
|
916
|
+
const size = node.e.s;
|
|
917
|
+
const id = node.i;
|
|
918
|
+
const sentinel = node.f;
|
|
919
|
+
const sentinelId = getRefParam(ctx, sentinel.i);
|
|
920
|
+
const base = ctx.base;
|
|
921
|
+
if (size) {
|
|
922
|
+
const keys = node.e.k;
|
|
923
|
+
const vals = node.e.v;
|
|
924
|
+
base.stack.push(id);
|
|
925
|
+
let result = serializeMapEntry(ctx, id, keys[0], vals[0], sentinelId);
|
|
926
|
+
for (let i = 1, item = result; i < size; i++) {
|
|
927
|
+
item = serializeMapEntry(ctx, id, keys[i], vals[i], sentinelId);
|
|
928
|
+
result += (item && result && ',') + item;
|
|
929
|
+
}
|
|
930
|
+
base.stack.pop();
|
|
931
|
+
// Check if there are any values
|
|
932
|
+
// so that the empty Map constructor
|
|
933
|
+
// can be used instead
|
|
934
|
+
if (result) {
|
|
935
|
+
serialized += '([' + result + '])';
|
|
785
936
|
}
|
|
786
|
-
return this.assignIndexedValue(node.i, result + ').buffer');
|
|
787
937
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
): string {
|
|
792
|
-
return this.assignIndexedValue(
|
|
793
|
-
node.i,
|
|
794
|
-
'new ' +
|
|
795
|
-
node.c +
|
|
796
|
-
'(' +
|
|
797
|
-
this.serialize(node.f) +
|
|
798
|
-
',' +
|
|
799
|
-
node.b +
|
|
800
|
-
',' +
|
|
801
|
-
node.l +
|
|
802
|
-
')',
|
|
803
|
-
);
|
|
938
|
+
if (sentinel.t === SerovalNodeType.SpecialReference) {
|
|
939
|
+
markSerializerRef(base, sentinel.i);
|
|
940
|
+
serialized = '(' + serialize(ctx, sentinel) + ',' + serialized + ')';
|
|
804
941
|
}
|
|
942
|
+
return serialized;
|
|
943
|
+
}
|
|
805
944
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
node.b +
|
|
813
|
-
',' +
|
|
814
|
-
node.l +
|
|
815
|
-
')',
|
|
816
|
-
);
|
|
817
|
-
}
|
|
945
|
+
function serializeArrayBuffer(
|
|
946
|
+
ctx: SerializerContext,
|
|
947
|
+
node: SerovalArrayBufferNode,
|
|
948
|
+
): string {
|
|
949
|
+
return getConstructor(ctx, node.f) + '(' + node.l + ',"' + node.s + '")';
|
|
950
|
+
}
|
|
818
951
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
952
|
+
function serializeTypedArray(
|
|
953
|
+
ctx: SerializerContext,
|
|
954
|
+
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
|
|
955
|
+
): string {
|
|
956
|
+
return (
|
|
957
|
+
'new ' +
|
|
958
|
+
node.c +
|
|
959
|
+
'(' +
|
|
960
|
+
serialize(ctx, node.f) +
|
|
961
|
+
',' +
|
|
962
|
+
node.b +
|
|
963
|
+
',' +
|
|
964
|
+
node.l +
|
|
965
|
+
')'
|
|
966
|
+
);
|
|
967
|
+
}
|
|
832
968
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
969
|
+
function serializeDataView(
|
|
970
|
+
ctx: SerializerContext,
|
|
971
|
+
node: SerovalDataViewNode,
|
|
972
|
+
): string {
|
|
973
|
+
return (
|
|
974
|
+
'new DataView(' + serialize(ctx, node.f) + ',' + node.b + ',' + node.l + ')'
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
function serializeAggregateError(
|
|
979
|
+
ctx: SerializerContext,
|
|
980
|
+
node: SerovalAggregateErrorNode,
|
|
981
|
+
): string {
|
|
982
|
+
const id = node.i;
|
|
983
|
+
// `AggregateError` might've been extended
|
|
984
|
+
// either through class or custom properties
|
|
985
|
+
// Make sure to assign extra properties
|
|
986
|
+
ctx.base.stack.push(id);
|
|
987
|
+
const serialized = serializeDictionary(
|
|
988
|
+
ctx,
|
|
989
|
+
node,
|
|
990
|
+
'new AggregateError([],"' + node.m + '")',
|
|
991
|
+
);
|
|
992
|
+
ctx.base.stack.pop();
|
|
993
|
+
return serialized;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
function serializeError(
|
|
997
|
+
ctx: SerializerContext,
|
|
998
|
+
node: SerovalErrorNode,
|
|
999
|
+
): string {
|
|
1000
|
+
return serializeDictionary(
|
|
1001
|
+
ctx,
|
|
1002
|
+
node,
|
|
1003
|
+
'new ' + ERROR_CONSTRUCTOR_STRING[node.s] + '("' + node.m + '")',
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
function serializePromise(
|
|
1008
|
+
ctx: SerializerContext,
|
|
1009
|
+
node: SerovalPromiseNode,
|
|
1010
|
+
): string {
|
|
1011
|
+
let serialized: string;
|
|
1012
|
+
// Check if resolved value is a parent expression
|
|
1013
|
+
const fulfilled = node.f;
|
|
1014
|
+
const id = node.i;
|
|
1015
|
+
const promiseConstructor = node.s ? PROMISE_RESOLVE : PROMISE_REJECT;
|
|
1016
|
+
const base = ctx.base;
|
|
1017
|
+
if (isIndexedValueInStack(base, fulfilled)) {
|
|
1018
|
+
// A Promise trick, reference the value
|
|
1019
|
+
// inside the `then` expression so that
|
|
1020
|
+
// the Promise evaluates after the parent
|
|
1021
|
+
// has initialized
|
|
1022
|
+
const ref = getRefParam(ctx, (fulfilled as SerovalIndexedValueNode).i);
|
|
1023
|
+
serialized =
|
|
1024
|
+
promiseConstructor +
|
|
1025
|
+
(node.s
|
|
1026
|
+
? '().then(' + createFunction([], ref) + ')'
|
|
1027
|
+
: '().catch(' + createEffectfulFunction([], 'throw ' + ref) + ')');
|
|
1028
|
+
} else {
|
|
1029
|
+
base.stack.push(id);
|
|
1030
|
+
const result = serialize(ctx, fulfilled);
|
|
1031
|
+
base.stack.pop();
|
|
1032
|
+
// just inline the value/reference here
|
|
1033
|
+
serialized = promiseConstructor + '(' + result + ')';
|
|
838
1034
|
}
|
|
1035
|
+
return serialized;
|
|
1036
|
+
}
|
|
839
1037
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
// just inline the value/reference here
|
|
864
|
-
serialized = promiseConstructor + '(' + result + ')';
|
|
865
|
-
}
|
|
866
|
-
return this.assignIndexedValue(id, serialized);
|
|
1038
|
+
function serializeBoxed(
|
|
1039
|
+
ctx: SerializerContext,
|
|
1040
|
+
node: SerovalBoxedNode,
|
|
1041
|
+
): string {
|
|
1042
|
+
return 'Object(' + serialize(ctx, node.f) + ')';
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
function getConstructor(
|
|
1046
|
+
ctx: SerializerContext,
|
|
1047
|
+
node: SerovalNodeWithID,
|
|
1048
|
+
): string {
|
|
1049
|
+
const current = serialize(ctx, node);
|
|
1050
|
+
return node.t === SerovalNodeType.IndexedValue
|
|
1051
|
+
? current
|
|
1052
|
+
: '(' + current + ')';
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
function serializePromiseConstructor(
|
|
1056
|
+
ctx: SerializerContext,
|
|
1057
|
+
node: SerovalPromiseConstructorNode,
|
|
1058
|
+
): string {
|
|
1059
|
+
if (ctx.mode === SerovalMode.Vanilla) {
|
|
1060
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
867
1061
|
}
|
|
1062
|
+
const resolver = assignIndexedValue(
|
|
1063
|
+
ctx,
|
|
1064
|
+
node.s,
|
|
1065
|
+
getConstructor(ctx, node.f) + '()',
|
|
1066
|
+
);
|
|
1067
|
+
return '(' + resolver + ').p';
|
|
1068
|
+
}
|
|
868
1069
|
|
|
869
|
-
|
|
870
|
-
|
|
1070
|
+
function serializePromiseResolve(
|
|
1071
|
+
ctx: SerializerContext,
|
|
1072
|
+
node: SerovalPromiseResolveNode,
|
|
1073
|
+
): string {
|
|
1074
|
+
if (ctx.mode === SerovalMode.Vanilla) {
|
|
1075
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
871
1076
|
}
|
|
1077
|
+
return (
|
|
1078
|
+
getConstructor(ctx, node.a[0]) +
|
|
1079
|
+
'(' +
|
|
1080
|
+
getRefParam(ctx, node.i) +
|
|
1081
|
+
',' +
|
|
1082
|
+
serialize(ctx, node.a[1]) +
|
|
1083
|
+
')'
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
872
1086
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1087
|
+
function serializePromiseReject(
|
|
1088
|
+
ctx: SerializerContext,
|
|
1089
|
+
node: SerovalPromiseRejectNode,
|
|
1090
|
+
): string {
|
|
1091
|
+
if (ctx.mode === SerovalMode.Vanilla) {
|
|
1092
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
878
1093
|
}
|
|
1094
|
+
return (
|
|
1095
|
+
getConstructor(ctx, node.a[0]) +
|
|
1096
|
+
'(' +
|
|
1097
|
+
getRefParam(ctx, node.i) +
|
|
1098
|
+
',' +
|
|
1099
|
+
serialize(ctx, node.a[1]) +
|
|
1100
|
+
')'
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
879
1103
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
);
|
|
1104
|
+
function serializePlugin(
|
|
1105
|
+
ctx: SerializerContext,
|
|
1106
|
+
node: SerovalPluginNode,
|
|
1107
|
+
): string {
|
|
1108
|
+
const currentPlugins = ctx.base.plugins;
|
|
1109
|
+
if (currentPlugins) {
|
|
1110
|
+
for (let i = 0, len = currentPlugins.length; i < len; i++) {
|
|
1111
|
+
const plugin = currentPlugins[i];
|
|
1112
|
+
if (plugin.tag === node.c) {
|
|
1113
|
+
if (ctx.child == null) {
|
|
1114
|
+
ctx.child = new SerializePluginContext(ctx);
|
|
892
1115
|
}
|
|
1116
|
+
return plugin.serialize(node.s, ctx.child, {
|
|
1117
|
+
id: node.i,
|
|
1118
|
+
});
|
|
893
1119
|
}
|
|
894
1120
|
}
|
|
895
|
-
throw new SerovalMissingPluginError(node.c);
|
|
896
1121
|
}
|
|
1122
|
+
throw new SerovalMissingPluginError(node.c);
|
|
1123
|
+
}
|
|
897
1124
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1125
|
+
function serializeIteratorFactory(
|
|
1126
|
+
ctx: SerializerContext,
|
|
1127
|
+
node: SerovalIteratorFactoryNode,
|
|
1128
|
+
): string {
|
|
1129
|
+
let result = '';
|
|
1130
|
+
let initialized = false;
|
|
1131
|
+
if (node.f.t !== SerovalNodeType.IndexedValue) {
|
|
1132
|
+
markSerializerRef(ctx.base, node.f.i);
|
|
1133
|
+
result = '(' + serialize(ctx, node.f) + ',';
|
|
1134
|
+
initialized = true;
|
|
901
1135
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
node
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
node.i
|
|
909
|
-
|
|
910
|
-
|
|
1136
|
+
result += assignIndexedValue(
|
|
1137
|
+
ctx,
|
|
1138
|
+
node.i,
|
|
1139
|
+
'(' +
|
|
1140
|
+
SERIALIZED_ITERATOR_CONSTRUCTOR +
|
|
1141
|
+
')(' +
|
|
1142
|
+
getRefParam(ctx, node.f.i) +
|
|
1143
|
+
')',
|
|
1144
|
+
);
|
|
1145
|
+
if (initialized) {
|
|
1146
|
+
result += ')';
|
|
911
1147
|
}
|
|
1148
|
+
return result;
|
|
1149
|
+
}
|
|
912
1150
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
this.serialize(node.a[1]) +
|
|
920
|
-
')'
|
|
921
|
-
);
|
|
922
|
-
}
|
|
1151
|
+
function serializeIteratorFactoryInstance(
|
|
1152
|
+
ctx: SerializerContext,
|
|
1153
|
+
node: SerovalIteratorFactoryInstanceNode,
|
|
1154
|
+
): string {
|
|
1155
|
+
return getConstructor(ctx, node.a[0]) + '(' + serialize(ctx, node.a[1]) + ')';
|
|
1156
|
+
}
|
|
923
1157
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
')'
|
|
932
|
-
);
|
|
933
|
-
}
|
|
1158
|
+
function serializeAsyncIteratorFactory(
|
|
1159
|
+
ctx: SerializerContext,
|
|
1160
|
+
node: SerovalAsyncIteratorFactoryNode,
|
|
1161
|
+
): string {
|
|
1162
|
+
const promise = node.a[0];
|
|
1163
|
+
const symbol = node.a[1];
|
|
1164
|
+
const base = ctx.base;
|
|
934
1165
|
|
|
935
|
-
|
|
936
|
-
node: SerovalSpecialReferenceNode,
|
|
937
|
-
): string {
|
|
938
|
-
return this.assignIndexedValue(
|
|
939
|
-
node.i,
|
|
940
|
-
serializeSpecialReferenceValue(this.features, node.s),
|
|
941
|
-
);
|
|
942
|
-
}
|
|
1166
|
+
let result = '';
|
|
943
1167
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
this.createFunction(
|
|
955
|
-
['s'],
|
|
956
|
-
this.createFunction(
|
|
957
|
-
['i', 'c', 'd', 't'],
|
|
958
|
-
'(i=0,t={[' +
|
|
959
|
-
this.getRefParam(node.f.i) +
|
|
960
|
-
']:' +
|
|
961
|
-
this.createFunction([], 't') +
|
|
962
|
-
',next:' +
|
|
963
|
-
this.createEffectfulFunction(
|
|
964
|
-
[],
|
|
965
|
-
'if(i>s.d)return{done:!0,value:void 0};if(d=s.v[c=i++],c===s.t)throw d;return{done:c===s.d,value:d}',
|
|
966
|
-
) +
|
|
967
|
-
'})',
|
|
968
|
-
),
|
|
969
|
-
),
|
|
970
|
-
);
|
|
971
|
-
if (initialized) {
|
|
972
|
-
result += ')';
|
|
973
|
-
}
|
|
974
|
-
return result;
|
|
1168
|
+
if (promise.t !== SerovalNodeType.IndexedValue) {
|
|
1169
|
+
markSerializerRef(base, promise.i);
|
|
1170
|
+
result += '(' + serialize(ctx, promise);
|
|
1171
|
+
}
|
|
1172
|
+
if (symbol.t !== SerovalNodeType.IndexedValue) {
|
|
1173
|
+
markSerializerRef(base, symbol.i);
|
|
1174
|
+
result += (result ? ',' : '(') + serialize(ctx, symbol);
|
|
1175
|
+
}
|
|
1176
|
+
if (result) {
|
|
1177
|
+
result += ',';
|
|
975
1178
|
}
|
|
976
1179
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1180
|
+
const iterator = assignIndexedValue(
|
|
1181
|
+
ctx,
|
|
1182
|
+
node.i,
|
|
1183
|
+
'(' +
|
|
1184
|
+
SERIALIZED_ASYNC_ITERATOR_CONSTRUCTOR +
|
|
1185
|
+
')(' +
|
|
1186
|
+
getRefParam(ctx, symbol.i) +
|
|
1187
|
+
',' +
|
|
1188
|
+
getRefParam(ctx, promise.i) +
|
|
1189
|
+
')',
|
|
1190
|
+
);
|
|
1191
|
+
|
|
1192
|
+
if (result) {
|
|
1193
|
+
return result + iterator + ')';
|
|
983
1194
|
}
|
|
984
1195
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
): string {
|
|
988
|
-
const promise = node.a[0];
|
|
989
|
-
const symbol = node.a[1];
|
|
1196
|
+
return iterator;
|
|
1197
|
+
}
|
|
990
1198
|
|
|
991
|
-
|
|
1199
|
+
function serializeAsyncIteratorFactoryInstance(
|
|
1200
|
+
ctx: SerializerContext,
|
|
1201
|
+
node: SerovalAsyncIteratorFactoryInstanceNode,
|
|
1202
|
+
): string {
|
|
1203
|
+
return getConstructor(ctx, node.a[0]) + '(' + serialize(ctx, node.a[1]) + ')';
|
|
1204
|
+
}
|
|
992
1205
|
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1206
|
+
function serializeStreamConstructor(
|
|
1207
|
+
ctx: SerializerContext,
|
|
1208
|
+
node: SerovalStreamConstructorNode,
|
|
1209
|
+
): string {
|
|
1210
|
+
const result = assignIndexedValue(
|
|
1211
|
+
ctx,
|
|
1212
|
+
node.i,
|
|
1213
|
+
getConstructor(ctx, node.f) + '()',
|
|
1214
|
+
);
|
|
1215
|
+
const len = node.a.length;
|
|
1216
|
+
if (len) {
|
|
1217
|
+
let values = serialize(ctx, node.a[0]);
|
|
1218
|
+
for (let i = 1; i < len; i++) {
|
|
1219
|
+
values += ',' + serialize(ctx, node.a[i]);
|
|
1003
1220
|
}
|
|
1221
|
+
return '(' + result + ',' + values + ',' + getRefParam(ctx, node.i) + ')';
|
|
1222
|
+
}
|
|
1223
|
+
return result;
|
|
1224
|
+
}
|
|
1004
1225
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
/**
|
|
1012
|
-
* b = resolved values
|
|
1013
|
-
* c = b size
|
|
1014
|
-
* p = pending promises
|
|
1015
|
-
* d = index where the resolved value stops
|
|
1016
|
-
* e = if the last value is a throw
|
|
1017
|
-
* t = placeholder variable
|
|
1018
|
-
* f = finalize
|
|
1019
|
-
*/
|
|
1020
|
-
'(b=[],c=0,p=[],d=-1,e=!1,f=' +
|
|
1021
|
-
this.createEffectfulFunction(
|
|
1022
|
-
['i', 'l'],
|
|
1023
|
-
'for(i=0,l=p.length;i<l;i++)p[i].s({done:!0,value:void 0})',
|
|
1024
|
-
) +
|
|
1025
|
-
',s.on({next:' +
|
|
1026
|
-
this.createEffectfulFunction(
|
|
1027
|
-
['v', 't'],
|
|
1028
|
-
'if(t=p.shift())t.s({done:!1,value:v});b.push(v)',
|
|
1029
|
-
) +
|
|
1030
|
-
',throw:' +
|
|
1031
|
-
this.createEffectfulFunction(
|
|
1032
|
-
['v', 't'],
|
|
1033
|
-
'if(t=p.shift())t.f(v);f(),d=b.length,e=!0,b.push(v)',
|
|
1034
|
-
) +
|
|
1035
|
-
',return:' +
|
|
1036
|
-
this.createEffectfulFunction(
|
|
1037
|
-
['v', 't'],
|
|
1038
|
-
'if(t=p.shift())t.s({done:!0,value:v});f(),d=b.length,b.push(v)',
|
|
1039
|
-
) +
|
|
1040
|
-
'}),t={[' +
|
|
1041
|
-
this.getRefParam(symbol.i) +
|
|
1042
|
-
']:' +
|
|
1043
|
-
this.createFunction([], 't.p') +
|
|
1044
|
-
',next:' +
|
|
1045
|
-
this.createEffectfulFunction(
|
|
1046
|
-
['i', 't', 'v'],
|
|
1047
|
-
'if(d===-1){return((i=c++)>=b.length)?(' +
|
|
1048
|
-
this.getRefParam(promise.i) +
|
|
1049
|
-
'(t={p:0,s:0,f:0}),p.push(t),t.p):{done:!1,value:b[i]}}if(c>d)return{done:!0,value:void 0};if(v=b[i=c++],i!==d)return{done:!1,value:v};if(e)throw v;return{done:!0,value:v}',
|
|
1050
|
-
) +
|
|
1051
|
-
'})',
|
|
1052
|
-
),
|
|
1053
|
-
),
|
|
1054
|
-
);
|
|
1226
|
+
function serializeStreamNext(
|
|
1227
|
+
ctx: SerializerContext,
|
|
1228
|
+
node: SerovalStreamNextNode,
|
|
1229
|
+
): string {
|
|
1230
|
+
return getRefParam(ctx, node.i) + '.next(' + serialize(ctx, node.f) + ')';
|
|
1231
|
+
}
|
|
1055
1232
|
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1233
|
+
function serializeStreamThrow(
|
|
1234
|
+
ctx: SerializerContext,
|
|
1235
|
+
node: SerovalStreamThrowNode,
|
|
1236
|
+
): string {
|
|
1237
|
+
return getRefParam(ctx, node.i) + '.throw(' + serialize(ctx, node.f) + ')';
|
|
1238
|
+
}
|
|
1059
1239
|
|
|
1060
|
-
|
|
1061
|
-
|
|
1240
|
+
function serializeStreamReturn(
|
|
1241
|
+
ctx: SerializerContext,
|
|
1242
|
+
node: SerovalStreamReturnNode,
|
|
1243
|
+
): string {
|
|
1244
|
+
return getRefParam(ctx, node.i) + '.return(' + serialize(ctx, node.f) + ')';
|
|
1245
|
+
}
|
|
1062
1246
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1247
|
+
function serializeAssignable(
|
|
1248
|
+
ctx: SerializerContext,
|
|
1249
|
+
node: SerovalNode,
|
|
1250
|
+
): string {
|
|
1251
|
+
switch (node.t) {
|
|
1252
|
+
case SerovalNodeType.WKSymbol:
|
|
1253
|
+
return SYMBOL_STRING[node.s];
|
|
1254
|
+
case SerovalNodeType.Reference:
|
|
1255
|
+
return serializeReference(node);
|
|
1256
|
+
case SerovalNodeType.Array:
|
|
1257
|
+
return serializeArray(ctx, node);
|
|
1258
|
+
case SerovalNodeType.Object:
|
|
1259
|
+
return serializeObject(ctx, node);
|
|
1260
|
+
case SerovalNodeType.NullConstructor:
|
|
1261
|
+
return serializeNullConstructor(ctx, node);
|
|
1262
|
+
case SerovalNodeType.Date:
|
|
1263
|
+
return serializeDate(node);
|
|
1264
|
+
case SerovalNodeType.RegExp:
|
|
1265
|
+
return serializeRegExp(node);
|
|
1266
|
+
case SerovalNodeType.Set:
|
|
1267
|
+
return serializeSet(ctx, node);
|
|
1268
|
+
case SerovalNodeType.Map:
|
|
1269
|
+
return serializeMap(ctx, node);
|
|
1270
|
+
case SerovalNodeType.ArrayBuffer:
|
|
1271
|
+
return serializeArrayBuffer(ctx, node);
|
|
1272
|
+
case SerovalNodeType.BigIntTypedArray:
|
|
1273
|
+
case SerovalNodeType.TypedArray:
|
|
1274
|
+
return serializeTypedArray(ctx, node);
|
|
1275
|
+
case SerovalNodeType.DataView:
|
|
1276
|
+
return serializeDataView(ctx, node);
|
|
1277
|
+
case SerovalNodeType.AggregateError:
|
|
1278
|
+
return serializeAggregateError(ctx, node);
|
|
1279
|
+
case SerovalNodeType.Error:
|
|
1280
|
+
return serializeError(ctx, node);
|
|
1281
|
+
case SerovalNodeType.Promise:
|
|
1282
|
+
return serializePromise(ctx, node);
|
|
1283
|
+
case SerovalNodeType.Boxed:
|
|
1284
|
+
return serializeBoxed(ctx, node);
|
|
1285
|
+
case SerovalNodeType.PromiseConstructor:
|
|
1286
|
+
return serializePromiseConstructor(ctx, node);
|
|
1287
|
+
case SerovalNodeType.Plugin:
|
|
1288
|
+
return serializePlugin(ctx, node);
|
|
1289
|
+
case SerovalNodeType.SpecialReference:
|
|
1290
|
+
return SPECIAL_REF_STRING[node.s];
|
|
1291
|
+
default:
|
|
1292
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
1069
1293
|
}
|
|
1294
|
+
}
|
|
1070
1295
|
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
return
|
|
1085
|
-
|
|
1086
|
-
|
|
1296
|
+
function serialize(ctx: SerializerContext, node: SerovalNode): string {
|
|
1297
|
+
switch (node.t) {
|
|
1298
|
+
case SerovalNodeType.Constant:
|
|
1299
|
+
return CONSTANT_STRING[node.s];
|
|
1300
|
+
case SerovalNodeType.Number:
|
|
1301
|
+
return '' + node.s;
|
|
1302
|
+
case SerovalNodeType.String:
|
|
1303
|
+
return '"' + node.s + '"';
|
|
1304
|
+
case SerovalNodeType.BigInt:
|
|
1305
|
+
return node.s + 'n';
|
|
1306
|
+
case SerovalNodeType.IndexedValue:
|
|
1307
|
+
return getRefParam(ctx, node.i);
|
|
1308
|
+
case SerovalNodeType.PromiseSuccess:
|
|
1309
|
+
return serializePromiseResolve(ctx, node);
|
|
1310
|
+
case SerovalNodeType.PromiseFailure:
|
|
1311
|
+
return serializePromiseReject(ctx, node);
|
|
1312
|
+
case SerovalNodeType.IteratorFactory:
|
|
1313
|
+
return serializeIteratorFactory(ctx, node);
|
|
1314
|
+
case SerovalNodeType.IteratorFactoryInstance:
|
|
1315
|
+
return serializeIteratorFactoryInstance(ctx, node);
|
|
1316
|
+
case SerovalNodeType.AsyncIteratorFactory:
|
|
1317
|
+
return serializeAsyncIteratorFactory(ctx, node);
|
|
1318
|
+
case SerovalNodeType.AsyncIteratorFactoryInstance:
|
|
1319
|
+
return serializeAsyncIteratorFactoryInstance(ctx, node);
|
|
1320
|
+
case SerovalNodeType.StreamConstructor:
|
|
1321
|
+
return serializeStreamConstructor(ctx, node);
|
|
1322
|
+
case SerovalNodeType.StreamNext:
|
|
1323
|
+
return serializeStreamNext(ctx, node);
|
|
1324
|
+
case SerovalNodeType.StreamThrow:
|
|
1325
|
+
return serializeStreamThrow(ctx, node);
|
|
1326
|
+
case SerovalNodeType.StreamReturn:
|
|
1327
|
+
return serializeStreamReturn(ctx, node);
|
|
1328
|
+
default:
|
|
1329
|
+
return assignIndexedValue(ctx, node.i, serializeAssignable(ctx, node));
|
|
1087
1330
|
}
|
|
1331
|
+
}
|
|
1088
1332
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1333
|
+
export function serializeRoot(
|
|
1334
|
+
ctx: SerializerContext,
|
|
1335
|
+
node: SerovalNode,
|
|
1336
|
+
): string {
|
|
1337
|
+
try {
|
|
1338
|
+
return serialize(ctx, node);
|
|
1339
|
+
} catch (error) {
|
|
1340
|
+
throw error instanceof SerovalSerializationError
|
|
1341
|
+
? error
|
|
1342
|
+
: new SerovalSerializationError(error);
|
|
1091
1343
|
}
|
|
1344
|
+
}
|
|
1092
1345
|
|
|
1093
|
-
|
|
1094
|
-
|
|
1346
|
+
export function serializeTopVanilla(
|
|
1347
|
+
ctx: VanillaSerializerContext,
|
|
1348
|
+
tree: SerovalNode,
|
|
1349
|
+
): string {
|
|
1350
|
+
const result = serialize(ctx, tree);
|
|
1351
|
+
// Shared references detected
|
|
1352
|
+
if (tree.i != null && ctx.state.vars.length) {
|
|
1353
|
+
const patches = resolvePatches(ctx.base);
|
|
1354
|
+
let body = result;
|
|
1355
|
+
if (patches) {
|
|
1356
|
+
// Get (or create) a ref from the source
|
|
1357
|
+
const index = getRefParam(ctx, tree.i);
|
|
1358
|
+
body = result + ',' + patches + index;
|
|
1359
|
+
if (!result.startsWith(index + '=')) {
|
|
1360
|
+
body = index + '=' + body;
|
|
1361
|
+
}
|
|
1362
|
+
body = '(' + body + ')';
|
|
1363
|
+
}
|
|
1364
|
+
return '(' + createFunction(ctx.state.vars, body) + ')()';
|
|
1095
1365
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
return this.getRefParam(node.i) + '.return(' + this.serialize(node.f) + ')';
|
|
1366
|
+
if (tree.t === SerovalNodeType.Object) {
|
|
1367
|
+
return '(' + result + ')';
|
|
1099
1368
|
}
|
|
1369
|
+
return result;
|
|
1370
|
+
}
|
|
1100
1371
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
case SerovalNodeType.Set:
|
|
1127
|
-
return this.serializeSet(node);
|
|
1128
|
-
case SerovalNodeType.Map:
|
|
1129
|
-
return this.serializeMap(node);
|
|
1130
|
-
case SerovalNodeType.ArrayBuffer:
|
|
1131
|
-
return this.serializeArrayBuffer(node);
|
|
1132
|
-
case SerovalNodeType.BigIntTypedArray:
|
|
1133
|
-
case SerovalNodeType.TypedArray:
|
|
1134
|
-
return this.serializeTypedArray(node);
|
|
1135
|
-
case SerovalNodeType.DataView:
|
|
1136
|
-
return this.serializeDataView(node);
|
|
1137
|
-
case SerovalNodeType.AggregateError:
|
|
1138
|
-
return this.serializeAggregateError(node);
|
|
1139
|
-
case SerovalNodeType.Error:
|
|
1140
|
-
return this.serializeError(node);
|
|
1141
|
-
case SerovalNodeType.Promise:
|
|
1142
|
-
return this.serializePromise(node);
|
|
1143
|
-
case SerovalNodeType.WKSymbol:
|
|
1144
|
-
return this.serializeWellKnownSymbol(node);
|
|
1145
|
-
case SerovalNodeType.Boxed:
|
|
1146
|
-
return this.serializeBoxed(node);
|
|
1147
|
-
case SerovalNodeType.PromiseConstructor:
|
|
1148
|
-
return this.serializePromiseConstructor(node);
|
|
1149
|
-
case SerovalNodeType.PromiseSuccess:
|
|
1150
|
-
return this.serializePromiseResolve(node);
|
|
1151
|
-
case SerovalNodeType.PromiseFailure:
|
|
1152
|
-
return this.serializePromiseReject(node);
|
|
1153
|
-
case SerovalNodeType.Plugin:
|
|
1154
|
-
return this.serializePlugin(node);
|
|
1155
|
-
case SerovalNodeType.SpecialReference:
|
|
1156
|
-
return this.serializeSpecialReference(node);
|
|
1157
|
-
case SerovalNodeType.IteratorFactory:
|
|
1158
|
-
return this.serializeIteratorFactory(node);
|
|
1159
|
-
case SerovalNodeType.IteratorFactoryInstance:
|
|
1160
|
-
return this.serializeIteratorFactoryInstance(node);
|
|
1161
|
-
case SerovalNodeType.AsyncIteratorFactory:
|
|
1162
|
-
return this.serializeAsyncIteratorFactory(node);
|
|
1163
|
-
case SerovalNodeType.AsyncIteratorFactoryInstance:
|
|
1164
|
-
return this.serializeAsyncIteratorFactoryInstance(node);
|
|
1165
|
-
case SerovalNodeType.StreamConstructor:
|
|
1166
|
-
return this.serializeStreamConstructor(node);
|
|
1167
|
-
case SerovalNodeType.StreamNext:
|
|
1168
|
-
return this.serializeStreamNext(node);
|
|
1169
|
-
case SerovalNodeType.StreamThrow:
|
|
1170
|
-
return this.serializeStreamThrow(node);
|
|
1171
|
-
case SerovalNodeType.StreamReturn:
|
|
1172
|
-
return this.serializeStreamReturn(node);
|
|
1173
|
-
default:
|
|
1174
|
-
throw new SerovalUnsupportedNodeError(node);
|
|
1175
|
-
}
|
|
1176
|
-
} catch (error) {
|
|
1177
|
-
throw new SerovalSerializationError(error);
|
|
1372
|
+
export function serializeTopCross(
|
|
1373
|
+
ctx: CrossSerializerContext,
|
|
1374
|
+
tree: SerovalNode,
|
|
1375
|
+
): string {
|
|
1376
|
+
// Get the serialized result
|
|
1377
|
+
const result = serialize(ctx, tree);
|
|
1378
|
+
// If the node is a non-reference, return
|
|
1379
|
+
// the result immediately
|
|
1380
|
+
const id = tree.i;
|
|
1381
|
+
if (id == null) {
|
|
1382
|
+
return result;
|
|
1383
|
+
}
|
|
1384
|
+
// Get the patches
|
|
1385
|
+
const patches = resolvePatches(ctx.base);
|
|
1386
|
+
// Get the variable that represents the root
|
|
1387
|
+
const ref = getRefParam(ctx, id);
|
|
1388
|
+
const scopeId = ctx.state.scopeId;
|
|
1389
|
+
// Parameters needed for scoping
|
|
1390
|
+
const params = scopeId == null ? '' : GLOBAL_CONTEXT_REFERENCES;
|
|
1391
|
+
// If there are patches, append it after the result
|
|
1392
|
+
const body = patches ? '(' + result + ',' + patches + ref + ')' : result;
|
|
1393
|
+
// If there are no params, there's no need to generate a function
|
|
1394
|
+
if (params === '') {
|
|
1395
|
+
if (tree.t === SerovalNodeType.Object && !patches) {
|
|
1396
|
+
return '(' + body + ')';
|
|
1178
1397
|
}
|
|
1398
|
+
return body;
|
|
1179
1399
|
}
|
|
1400
|
+
// Get the arguments for the IIFE
|
|
1401
|
+
const args =
|
|
1402
|
+
scopeId == null
|
|
1403
|
+
? '()'
|
|
1404
|
+
: '(' +
|
|
1405
|
+
GLOBAL_CONTEXT_REFERENCES +
|
|
1406
|
+
'["' +
|
|
1407
|
+
serializeString(scopeId) +
|
|
1408
|
+
'"])';
|
|
1409
|
+
// Create the IIFE
|
|
1410
|
+
return '(' + createFunction([params], body) + ')' + args;
|
|
1180
1411
|
}
|