seroval 0.12.4 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -15
- package/dist/cjs/development/index.cjs +1432 -959
- package/dist/cjs/development/index.cjs.map +3 -3
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +1432 -959
- package/dist/esm/development/index.mjs.map +3 -3
- package/dist/esm/production/index.mjs +3 -3
- 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 +3 -3
- 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 +89 -14
- 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,14 +1,13 @@
|
|
|
1
|
-
import { Feature } from '
|
|
1
|
+
import { Feature } from '../compat';
|
|
2
2
|
import {
|
|
3
3
|
CONSTANT_STRING,
|
|
4
4
|
ERROR_CONSTRUCTOR_STRING,
|
|
5
5
|
SYMBOL_STRING,
|
|
6
6
|
SerovalNodeType,
|
|
7
7
|
SerovalObjectFlags,
|
|
8
|
-
} from '
|
|
9
|
-
import { REFERENCES_KEY } from '
|
|
10
|
-
import type { Plugin, PluginAccessOptions, SerovalMode } from '
|
|
11
|
-
import { isValidIdentifier } from './shared';
|
|
8
|
+
} from '../constants';
|
|
9
|
+
import { REFERENCES_KEY } from '../keys';
|
|
10
|
+
import type { Plugin, PluginAccessOptions, SerovalMode } from '../plugin';
|
|
12
11
|
import type {
|
|
13
12
|
SerovalArrayNode,
|
|
14
13
|
SerovalIndexedValueNode,
|
|
@@ -50,10 +49,15 @@ import type {
|
|
|
50
49
|
SerovalReadableStreamEnqueueNode,
|
|
51
50
|
SerovalReadableStreamErrorNode,
|
|
52
51
|
SerovalReadableStreamCloseNode,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
SerovalMapSentinelNode,
|
|
53
|
+
SerovalIteratorFactoryInstanceNode,
|
|
54
|
+
SerovalIteratorFactoryNode,
|
|
55
|
+
SerovalAsyncIteratorFactoryInstanceNode,
|
|
56
|
+
SerovalAsyncIteratorFactoryNode,
|
|
57
|
+
SerovalReadableStreamNode,
|
|
58
|
+
SerovalReadableStreamFactoryNode,
|
|
59
|
+
} from '../types';
|
|
60
|
+
import { isValidIdentifier } from '../utils/is-valid-identifier';
|
|
57
61
|
|
|
58
62
|
interface IndexAssignment {
|
|
59
63
|
t: 'index';
|
|
@@ -180,16 +184,6 @@ const MAP_CONSTRUCTOR = 'new Map';
|
|
|
180
184
|
const PROMISE_RESOLVE = 'Promise.resolve';
|
|
181
185
|
const PROMISE_REJECT = 'Promise.reject';
|
|
182
186
|
|
|
183
|
-
const SYMBOL_ITERATOR = 'Symbol.iterator';
|
|
184
|
-
|
|
185
|
-
const enum SpecialReference {
|
|
186
|
-
Sentinel = 0,
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const SPECIAL_REFERENCE_VALUE: Record<SpecialReference, string> = {
|
|
190
|
-
[SpecialReference.Sentinel]: '[]',
|
|
191
|
-
};
|
|
192
|
-
|
|
193
187
|
const OBJECT_FLAG_CONSTRUCTOR: Record<SerovalObjectFlags, string | undefined> = {
|
|
194
188
|
[SerovalObjectFlags.Frozen]: 'Object.freeze',
|
|
195
189
|
[SerovalObjectFlags.Sealed]: 'Object.seal',
|
|
@@ -197,6 +191,13 @@ const OBJECT_FLAG_CONSTRUCTOR: Record<SerovalObjectFlags, string | undefined> =
|
|
|
197
191
|
[SerovalObjectFlags.None]: undefined,
|
|
198
192
|
};
|
|
199
193
|
|
|
194
|
+
type SerovalNodeWithProperties =
|
|
195
|
+
| SerovalObjectNode
|
|
196
|
+
| SerovalNullConstructorNode
|
|
197
|
+
| SerovalAggregateErrorNode
|
|
198
|
+
| SerovalErrorNode
|
|
199
|
+
| SerovalHeadersNode;
|
|
200
|
+
|
|
200
201
|
export interface BaseSerializerContextOptions extends PluginAccessOptions {
|
|
201
202
|
features: number;
|
|
202
203
|
markedRefs: number[] | Set<number>;
|
|
@@ -242,6 +243,32 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
242
243
|
|
|
243
244
|
abstract readonly mode: SerovalMode;
|
|
244
245
|
|
|
246
|
+
protected createFunction(
|
|
247
|
+
parameters: string[],
|
|
248
|
+
body: string,
|
|
249
|
+
): string {
|
|
250
|
+
if (this.features & Feature.ArrowFunction) {
|
|
251
|
+
const joined = parameters.length === 1
|
|
252
|
+
? parameters[0]
|
|
253
|
+
: '(' + parameters.join(',') + ')';
|
|
254
|
+
return joined + '=>' + body;
|
|
255
|
+
}
|
|
256
|
+
return 'function(' + parameters.join(',') + '){return ' + body + '}';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
protected createEffectfulFunction(
|
|
260
|
+
parameters: string[],
|
|
261
|
+
body: string,
|
|
262
|
+
): string {
|
|
263
|
+
if (this.features & Feature.ArrowFunction) {
|
|
264
|
+
const joined = parameters.length === 1
|
|
265
|
+
? parameters[0]
|
|
266
|
+
: '(' + parameters.join(',') + ')';
|
|
267
|
+
return joined + '=>{' + body + '}';
|
|
268
|
+
}
|
|
269
|
+
return 'function(' + parameters.join(',') + '){' + body + '}';
|
|
270
|
+
}
|
|
271
|
+
|
|
245
272
|
/**
|
|
246
273
|
* A tiny function that tells if a reference
|
|
247
274
|
* is to be accessed. This is a requirement for
|
|
@@ -263,21 +290,6 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
263
290
|
*/
|
|
264
291
|
abstract getRefParam(id: number | string): string;
|
|
265
292
|
|
|
266
|
-
private specials = new Set<SpecialReference>();
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Generates special references that isn't provided by the user
|
|
270
|
-
* but by the script.
|
|
271
|
-
*/
|
|
272
|
-
protected getSpecialReference(ref: SpecialReference): string {
|
|
273
|
-
const param = this.getRefParam('_' + ref);
|
|
274
|
-
if (this.specials.has(ref)) {
|
|
275
|
-
return param;
|
|
276
|
-
}
|
|
277
|
-
this.specials.add(ref);
|
|
278
|
-
return param + '=' + SPECIAL_REFERENCE_VALUE[ref];
|
|
279
|
-
}
|
|
280
|
-
|
|
281
293
|
protected pushObjectFlag(flag: SerovalObjectFlags, id: number): void {
|
|
282
294
|
if (flag !== SerovalObjectFlags.None) {
|
|
283
295
|
this.markRef(id);
|
|
@@ -406,30 +418,6 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
406
418
|
return this.assignIndexedValue(node.i, REFERENCES_KEY + '.get("' + node.s + '")');
|
|
407
419
|
}
|
|
408
420
|
|
|
409
|
-
protected getIterableAccess(): string {
|
|
410
|
-
return this.features & Feature.ArrayPrototypeValues
|
|
411
|
-
? '.values()'
|
|
412
|
-
: '[' + SYMBOL_ITERATOR + ']()';
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
protected serializeIterable(
|
|
416
|
-
node: SerovalNode,
|
|
417
|
-
): string {
|
|
418
|
-
const key = '[' + SYMBOL_ITERATOR + ']';
|
|
419
|
-
const parent = this.stack;
|
|
420
|
-
this.stack = [];
|
|
421
|
-
let serialized = this.serialize(node) + this.getIterableAccess();
|
|
422
|
-
this.stack = parent;
|
|
423
|
-
if (this.features & Feature.ArrowFunction) {
|
|
424
|
-
serialized = ':()=>' + serialized;
|
|
425
|
-
} else if (this.features & Feature.MethodShorthand) {
|
|
426
|
-
serialized = '(){return ' + serialized + '}';
|
|
427
|
-
} else {
|
|
428
|
-
serialized = ':function(){return ' + serialized + '}';
|
|
429
|
-
}
|
|
430
|
-
return key + serialized;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
421
|
protected serializeArrayItem(
|
|
434
422
|
id: number,
|
|
435
423
|
item: SerovalNode | undefined,
|
|
@@ -473,50 +461,43 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
473
461
|
}
|
|
474
462
|
|
|
475
463
|
protected serializeProperty(
|
|
476
|
-
|
|
464
|
+
source: SerovalNodeWithProperties,
|
|
477
465
|
key: SerovalObjectRecordKey,
|
|
478
466
|
val: SerovalNode,
|
|
479
467
|
): string {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
const refParam = this.getRefParam((val as SerovalIndexedValueNode).i);
|
|
494
|
-
this.markRef(id);
|
|
495
|
-
// eslint-disable-next-line no-self-compare
|
|
496
|
-
if (isIdentifier && check !== check) {
|
|
497
|
-
this.createObjectAssign(id, key, refParam);
|
|
498
|
-
} else {
|
|
499
|
-
this.createArrayAssign(id, isIdentifier ? key : ('"' + key + '"'), refParam);
|
|
500
|
-
}
|
|
501
|
-
return '';
|
|
468
|
+
if (typeof key === 'string') {
|
|
469
|
+
const check = Number(key);
|
|
470
|
+
// Test if key is a valid number or JS identifier
|
|
471
|
+
// so that we don't have to serialize the key and wrap with brackets
|
|
472
|
+
const isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
473
|
+
if (this.isIndexedValueInStack(val)) {
|
|
474
|
+
const refParam = this.getRefParam((val as SerovalIndexedValueNode).i);
|
|
475
|
+
this.markRef(source.i);
|
|
476
|
+
// eslint-disable-next-line no-self-compare
|
|
477
|
+
if (isIdentifier && check !== check) {
|
|
478
|
+
this.createObjectAssign(source.i, key, refParam);
|
|
479
|
+
} else {
|
|
480
|
+
this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), refParam);
|
|
502
481
|
}
|
|
503
|
-
return
|
|
482
|
+
return '';
|
|
504
483
|
}
|
|
484
|
+
return (isIdentifier ? key : ('"' + key + '"')) + ':' + this.serialize(val);
|
|
505
485
|
}
|
|
486
|
+
return '[' + this.serialize(key) + ']:' + this.serialize(val);
|
|
506
487
|
}
|
|
507
488
|
|
|
508
489
|
protected serializeProperties(
|
|
509
|
-
|
|
510
|
-
|
|
490
|
+
source: SerovalNodeWithProperties,
|
|
491
|
+
record: SerovalObjectRecordNode,
|
|
511
492
|
): string {
|
|
512
|
-
const len =
|
|
493
|
+
const len = record.s;
|
|
513
494
|
if (len) {
|
|
514
|
-
this.stack.push(
|
|
515
|
-
const keys =
|
|
516
|
-
const values =
|
|
517
|
-
let result = this.serializeProperty(
|
|
495
|
+
this.stack.push(source.i);
|
|
496
|
+
const keys = record.k;
|
|
497
|
+
const values = record.v;
|
|
498
|
+
let result = this.serializeProperty(source, keys[0], values[0]);
|
|
518
499
|
for (let i = 1, item = result; i < len; i++) {
|
|
519
|
-
item = this.serializeProperty(
|
|
500
|
+
item = this.serializeProperty(source, keys[i], values[i]);
|
|
520
501
|
result += (item && result && ',') + item;
|
|
521
502
|
}
|
|
522
503
|
this.stack.pop();
|
|
@@ -529,15 +510,15 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
529
510
|
node: SerovalObjectNode,
|
|
530
511
|
): string {
|
|
531
512
|
this.pushObjectFlag(node.o, node.i);
|
|
532
|
-
return this.assignIndexedValue(node.i, this.serializeProperties(node
|
|
513
|
+
return this.assignIndexedValue(node.i, this.serializeProperties(node, node.p));
|
|
533
514
|
}
|
|
534
515
|
|
|
535
516
|
protected serializeWithObjectAssign(
|
|
517
|
+
source: SerovalNodeWithProperties,
|
|
536
518
|
value: SerovalObjectRecordNode,
|
|
537
|
-
id: number,
|
|
538
519
|
serialized: string,
|
|
539
520
|
): string {
|
|
540
|
-
const fields = this.serializeProperties(
|
|
521
|
+
const fields = this.serializeProperties(source, value);
|
|
541
522
|
if (fields !== '{}') {
|
|
542
523
|
return 'Object.assign(' + serialized + ',' + fields + ')';
|
|
543
524
|
}
|
|
@@ -545,68 +526,62 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
545
526
|
}
|
|
546
527
|
|
|
547
528
|
protected serializeAssignment(
|
|
548
|
-
|
|
529
|
+
source: SerovalNodeWithProperties,
|
|
549
530
|
mainAssignments: Assignment[],
|
|
550
531
|
key: SerovalObjectRecordKey,
|
|
551
532
|
value: SerovalNode,
|
|
552
533
|
): void {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
534
|
+
if (typeof key === 'string') {
|
|
535
|
+
const serialized = this.serialize(value);
|
|
536
|
+
const check = Number(key);
|
|
537
|
+
// Test if key is a valid number or JS identifier
|
|
538
|
+
// so that we don't have to serialize the key and wrap with brackets
|
|
539
|
+
const isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
540
|
+
if (this.isIndexedValueInStack(value)) {
|
|
541
|
+
// eslint-disable-next-line no-self-compare
|
|
542
|
+
if (isIdentifier && check !== check) {
|
|
543
|
+
this.createObjectAssign(source.i, key, serialized);
|
|
544
|
+
} else {
|
|
545
|
+
this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), serialized);
|
|
546
|
+
}
|
|
547
|
+
} else {
|
|
559
548
|
const parentAssignment = this.assignments;
|
|
560
549
|
this.assignments = mainAssignments;
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
this.getSpecialReference(SpecialReference.Sentinel),
|
|
564
|
-
this.features & Feature.ArrowFunction
|
|
565
|
-
? '()=>' + serialized
|
|
566
|
-
: 'function(){return ' + serialized + '}',
|
|
567
|
-
);
|
|
568
|
-
this.assignments = parentAssignment;
|
|
569
|
-
}
|
|
570
|
-
break;
|
|
571
|
-
default: {
|
|
572
|
-
const serialized = this.serialize(value);
|
|
573
|
-
const check = Number(key);
|
|
574
|
-
// Test if key is a valid number or JS identifier
|
|
575
|
-
// so that we don't have to serialize the key and wrap with brackets
|
|
576
|
-
const isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
577
|
-
if (this.isIndexedValueInStack(value)) {
|
|
578
|
-
// eslint-disable-next-line no-self-compare
|
|
579
|
-
if (isIdentifier && check !== check) {
|
|
580
|
-
this.createObjectAssign(sourceID, key, serialized);
|
|
581
|
-
} else {
|
|
582
|
-
this.createArrayAssign(sourceID, isIdentifier ? key : ('"' + key + '"'), serialized);
|
|
583
|
-
}
|
|
550
|
+
if (isIdentifier) {
|
|
551
|
+
this.createObjectAssign(source.i, key, serialized);
|
|
584
552
|
} else {
|
|
585
|
-
|
|
586
|
-
this.assignments = mainAssignments;
|
|
587
|
-
if (isIdentifier) {
|
|
588
|
-
this.createObjectAssign(sourceID, key, serialized);
|
|
589
|
-
} else {
|
|
590
|
-
this.createArrayAssign(sourceID, isIdentifier ? key : ('"' + key + '"'), serialized);
|
|
591
|
-
}
|
|
592
|
-
this.assignments = parentAssignment;
|
|
553
|
+
this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), serialized);
|
|
593
554
|
}
|
|
555
|
+
this.assignments = parentAssignment;
|
|
594
556
|
}
|
|
557
|
+
} else {
|
|
558
|
+
const parent = this.stack;
|
|
559
|
+
this.stack = [];
|
|
560
|
+
const serialized = this.serialize(value);
|
|
561
|
+
this.stack = parent;
|
|
562
|
+
const parentAssignment = this.assignments;
|
|
563
|
+
this.assignments = mainAssignments;
|
|
564
|
+
this.createArrayAssign(
|
|
565
|
+
source.i,
|
|
566
|
+
this.serialize(key),
|
|
567
|
+
serialized,
|
|
568
|
+
);
|
|
569
|
+
this.assignments = parentAssignment;
|
|
595
570
|
}
|
|
596
571
|
}
|
|
597
572
|
|
|
598
573
|
protected serializeAssignments(
|
|
599
|
-
|
|
574
|
+
source: SerovalNodeWithProperties,
|
|
600
575
|
node: SerovalObjectRecordNode,
|
|
601
576
|
): string | undefined {
|
|
602
577
|
const len = node.s;
|
|
603
578
|
if (len) {
|
|
604
|
-
this.stack.push(
|
|
579
|
+
this.stack.push(source.i);
|
|
605
580
|
const mainAssignments: Assignment[] = [];
|
|
606
581
|
const keys = node.k;
|
|
607
582
|
const values = node.v;
|
|
608
583
|
for (let i = 0; i < len; i++) {
|
|
609
|
-
this.serializeAssignment(
|
|
584
|
+
this.serializeAssignment(source, mainAssignments, keys[i], values[i]);
|
|
610
585
|
}
|
|
611
586
|
this.stack.pop();
|
|
612
587
|
return resolveAssignments(mainAssignments);
|
|
@@ -615,29 +590,28 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
615
590
|
}
|
|
616
591
|
|
|
617
592
|
protected serializeDictionary(
|
|
618
|
-
|
|
619
|
-
p: SerovalObjectRecordNode | undefined,
|
|
593
|
+
node: SerovalNodeWithProperties,
|
|
620
594
|
init: string,
|
|
621
595
|
): string {
|
|
622
|
-
if (p) {
|
|
596
|
+
if (node.p) {
|
|
623
597
|
if (this.features & Feature.ObjectAssign) {
|
|
624
|
-
init = this.serializeWithObjectAssign(
|
|
598
|
+
init = this.serializeWithObjectAssign(node, node.p, init);
|
|
625
599
|
} else {
|
|
626
|
-
this.markRef(i);
|
|
627
|
-
const assignments = this.serializeAssignments(
|
|
600
|
+
this.markRef(node.i);
|
|
601
|
+
const assignments = this.serializeAssignments(node, node.p);
|
|
628
602
|
if (assignments) {
|
|
629
|
-
return '(' + this.assignIndexedValue(i, init) + ',' + assignments + this.getRefParam(i) + ')';
|
|
603
|
+
return '(' + this.assignIndexedValue(node.i, init) + ',' + assignments + this.getRefParam(node.i) + ')';
|
|
630
604
|
}
|
|
631
605
|
}
|
|
632
606
|
}
|
|
633
|
-
return this.assignIndexedValue(i, init);
|
|
607
|
+
return this.assignIndexedValue(node.i, init);
|
|
634
608
|
}
|
|
635
609
|
|
|
636
610
|
protected serializeNullConstructor(
|
|
637
611
|
node: SerovalNullConstructorNode,
|
|
638
612
|
): string {
|
|
639
613
|
this.pushObjectFlag(node.o, node.i);
|
|
640
|
-
return this.serializeDictionary(node
|
|
614
|
+
return this.serializeDictionary(node, NULL_CONSTRUCTOR);
|
|
641
615
|
}
|
|
642
616
|
|
|
643
617
|
protected serializeDate(
|
|
@@ -690,6 +664,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
690
664
|
id: number,
|
|
691
665
|
key: SerovalNode,
|
|
692
666
|
val: SerovalNode,
|
|
667
|
+
sentinel: string,
|
|
693
668
|
): string {
|
|
694
669
|
if (this.isIndexedValueInStack(key)) {
|
|
695
670
|
// Create reference for the map instance
|
|
@@ -714,9 +689,9 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
714
689
|
// basically we serialize the intended object in place WITHOUT
|
|
715
690
|
// actually returning it, this is by returning a placeholder
|
|
716
691
|
// value that we will remove sometime after.
|
|
717
|
-
const serialized = '(' + this.serialize(val) + ',[' +
|
|
692
|
+
const serialized = '(' + this.serialize(val) + ',[' + sentinel + ',' + sentinel + '])';
|
|
718
693
|
this.createSetAssignment(id, keyRef, this.getRefParam(val.i));
|
|
719
|
-
this.createDeleteAssignment(id,
|
|
694
|
+
this.createDeleteAssignment(id, sentinel);
|
|
720
695
|
return serialized;
|
|
721
696
|
}
|
|
722
697
|
const parent = this.stack;
|
|
@@ -730,9 +705,9 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
730
705
|
const valueRef = this.getRefParam((val as SerovalIndexedValueNode).i);
|
|
731
706
|
this.markRef(id);
|
|
732
707
|
if (key.t !== SerovalNodeType.IndexedValue && key.i != null && this.isMarked(key.i)) {
|
|
733
|
-
const serialized = '(' + this.serialize(key) + ',[' +
|
|
708
|
+
const serialized = '(' + this.serialize(key) + ',[' + sentinel + ',' + sentinel + '])';
|
|
734
709
|
this.createSetAssignment(id, this.getRefParam(key.i), valueRef);
|
|
735
|
-
this.createDeleteAssignment(id,
|
|
710
|
+
this.createDeleteAssignment(id, sentinel);
|
|
736
711
|
return serialized;
|
|
737
712
|
}
|
|
738
713
|
// Reset stack for the key serialization
|
|
@@ -752,13 +727,15 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
752
727
|
let serialized = MAP_CONSTRUCTOR;
|
|
753
728
|
const size = node.e.s;
|
|
754
729
|
const id = node.i;
|
|
730
|
+
const sentinel = node.f;
|
|
731
|
+
const sentinelID = this.getRefParam(sentinel.i);
|
|
755
732
|
if (size) {
|
|
756
733
|
const keys = node.e.k;
|
|
757
734
|
const vals = node.e.v;
|
|
758
735
|
this.stack.push(id);
|
|
759
|
-
let result = this.serializeMapEntry(id, keys[0], vals[0]);
|
|
736
|
+
let result = this.serializeMapEntry(id, keys[0], vals[0], sentinelID);
|
|
760
737
|
for (let i = 1, item = result; i < size; i++) {
|
|
761
|
-
item = this.serializeMapEntry(id, keys[i], vals[i]);
|
|
738
|
+
item = this.serializeMapEntry(id, keys[i], vals[i], sentinelID);
|
|
762
739
|
result += (item && result && ',') + item;
|
|
763
740
|
}
|
|
764
741
|
this.stack.pop();
|
|
@@ -769,6 +746,10 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
769
746
|
serialized += '([' + result + '])';
|
|
770
747
|
}
|
|
771
748
|
}
|
|
749
|
+
if (sentinel.t === SerovalNodeType.MapSentinel) {
|
|
750
|
+
this.markRef(sentinel.i);
|
|
751
|
+
serialized = '(' + this.serialize(sentinel) + ',' + serialized + ')';
|
|
752
|
+
}
|
|
772
753
|
return this.assignIndexedValue(id, serialized);
|
|
773
754
|
}
|
|
774
755
|
|
|
@@ -817,13 +798,13 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
817
798
|
// `AggregateError` might've been extended
|
|
818
799
|
// either through class or custom properties
|
|
819
800
|
// Make sure to assign extra properties
|
|
820
|
-
return this.serializeDictionary(
|
|
801
|
+
return this.serializeDictionary(node, serialized);
|
|
821
802
|
}
|
|
822
803
|
|
|
823
804
|
protected serializeError(
|
|
824
805
|
node: SerovalErrorNode,
|
|
825
806
|
): string {
|
|
826
|
-
return this.serializeDictionary(node
|
|
807
|
+
return this.serializeDictionary(node, 'new ' + ERROR_CONSTRUCTOR_STRING[node.s] + '("' + node.m + '")');
|
|
827
808
|
}
|
|
828
809
|
|
|
829
810
|
protected serializePromise(
|
|
@@ -840,17 +821,11 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
840
821
|
// the Promise evaluates after the parent
|
|
841
822
|
// has initialized
|
|
842
823
|
const ref = this.getRefParam((fulfilled as SerovalIndexedValueNode).i);
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
}
|
|
849
|
-
} else if (node.s) {
|
|
850
|
-
serialized = constructor + '().then(function(){return ' + ref + '})';
|
|
851
|
-
} else {
|
|
852
|
-
serialized = constructor + '().catch(function(){throw ' + ref + '})';
|
|
853
|
-
}
|
|
824
|
+
serialized = constructor + (
|
|
825
|
+
node.s
|
|
826
|
+
? '().then(' + this.createFunction([], ref) + ')'
|
|
827
|
+
: '().catch(' + this.createEffectfulFunction([], 'throw ' + ref) + ')'
|
|
828
|
+
);
|
|
854
829
|
} else {
|
|
855
830
|
this.stack.push(id);
|
|
856
831
|
const result = this.serialize(fulfilled);
|
|
@@ -905,7 +880,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
905
880
|
): string {
|
|
906
881
|
return this.assignIndexedValue(
|
|
907
882
|
node.i,
|
|
908
|
-
'new Headers(' + this.serializeProperties(node
|
|
883
|
+
'new Headers(' + this.serializeProperties(node, node.e) + ')',
|
|
909
884
|
);
|
|
910
885
|
}
|
|
911
886
|
|
|
@@ -999,9 +974,12 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
999
974
|
for (let i = 0, len = currentPlugins.length; i < len; i++) {
|
|
1000
975
|
const plugin = currentPlugins[i];
|
|
1001
976
|
if (plugin.tag === node.c) {
|
|
1002
|
-
return
|
|
1003
|
-
|
|
1004
|
-
|
|
977
|
+
return this.assignIndexedValue(
|
|
978
|
+
node.i,
|
|
979
|
+
plugin.serialize(node.s, this, {
|
|
980
|
+
id: node.i,
|
|
981
|
+
}),
|
|
982
|
+
);
|
|
1005
983
|
}
|
|
1006
984
|
}
|
|
1007
985
|
}
|
|
@@ -1036,6 +1014,89 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
1036
1014
|
node: SerovalReadableStreamCloseNode,
|
|
1037
1015
|
): string;
|
|
1038
1016
|
|
|
1017
|
+
protected serializeMapSentinel(node: SerovalMapSentinelNode): string {
|
|
1018
|
+
return this.assignIndexedValue(
|
|
1019
|
+
node.i,
|
|
1020
|
+
'[]',
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
protected serializeIteratorFactory(node: SerovalIteratorFactoryNode): string {
|
|
1025
|
+
return this.assignIndexedValue(
|
|
1026
|
+
node.i,
|
|
1027
|
+
this.createFunction(
|
|
1028
|
+
['s'],
|
|
1029
|
+
this.createFunction(
|
|
1030
|
+
['i', 'c', 'd', 't'],
|
|
1031
|
+
'(i=0,t={[' + this.serialize(node.f) + ']:' + this.createFunction([], 't') + ','
|
|
1032
|
+
+ 'next:' + this.createEffectfulFunction([], 'if(i>s.d)return{done:!0,value:void 0};c=i++,d=s.v[c];if(c===s.t)throw d;return{done:c===s.d,value:d}') + '})',
|
|
1033
|
+
),
|
|
1034
|
+
),
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
protected serializeIteratorFactoryInstance(
|
|
1039
|
+
node: SerovalIteratorFactoryInstanceNode,
|
|
1040
|
+
): string {
|
|
1041
|
+
return '(' + this.serialize(node.a[0]) + ')(' + this.serialize(node.a[1]) + ')';
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
protected serializeAsyncIteratorFactory(node: SerovalAsyncIteratorFactoryNode): string {
|
|
1045
|
+
return this.assignIndexedValue(
|
|
1046
|
+
node.i,
|
|
1047
|
+
this.createFunction(
|
|
1048
|
+
['s'],
|
|
1049
|
+
this.createFunction(
|
|
1050
|
+
['i', 't'],
|
|
1051
|
+
'(i=0,t={[' + this.serialize(node.f) + ']:' + this.createFunction([], 't') + ','
|
|
1052
|
+
+ 'next:' + this.createFunction(
|
|
1053
|
+
[],
|
|
1054
|
+
'Promise.resolve().then(' + this.createEffectfulFunction(
|
|
1055
|
+
['c', 'd'],
|
|
1056
|
+
'if(i>s.d)return{done:!0,value:void 0};c=i++,d=s.v[c];if(c===s.t)throw d;return{done:c===s.d,value:d}',
|
|
1057
|
+
) + ')',
|
|
1058
|
+
) + '})',
|
|
1059
|
+
),
|
|
1060
|
+
),
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
protected serializeAsyncIteratorFactoryInstance(
|
|
1065
|
+
node: SerovalAsyncIteratorFactoryInstanceNode,
|
|
1066
|
+
): string {
|
|
1067
|
+
return '(' + this.serialize(node.a[0]) + ')(' + this.serialize(node.a[1]) + ')';
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
protected serializeReadableStream(
|
|
1071
|
+
node: SerovalReadableStreamNode,
|
|
1072
|
+
): string {
|
|
1073
|
+
this.stack.push(node.i);
|
|
1074
|
+
const result = '(' + this.serialize(node.a[0]) + ')(' + this.serialize(node.a[1]) + ')';
|
|
1075
|
+
this.stack.pop();
|
|
1076
|
+
return this.assignIndexedValue(
|
|
1077
|
+
node.i,
|
|
1078
|
+
result,
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
protected serializeReadableStreamFactory(
|
|
1083
|
+
node: SerovalReadableStreamFactoryNode,
|
|
1084
|
+
): string {
|
|
1085
|
+
return this.assignIndexedValue(
|
|
1086
|
+
node.i,
|
|
1087
|
+
this.createFunction(
|
|
1088
|
+
['s'],
|
|
1089
|
+
'new ReadableStream({start:' + this.createFunction(
|
|
1090
|
+
['c'],
|
|
1091
|
+
'Promise.resolve().then(' + this.createEffectfulFunction(
|
|
1092
|
+
['i', 'v'],
|
|
1093
|
+
'for(i=0;i<s.d;i++)c.enqueue(s.v[i]);(s.t===-1)?c.close():c.error(s.v[i])',
|
|
1094
|
+
) + ')',
|
|
1095
|
+
) + '})',
|
|
1096
|
+
),
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1039
1100
|
serialize(node: SerovalNode): string {
|
|
1040
1101
|
switch (node.t) {
|
|
1041
1102
|
case SerovalNodeType.Constant:
|
|
@@ -1119,6 +1180,20 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
|
|
|
1119
1180
|
return this.serializeDOMException(node);
|
|
1120
1181
|
case SerovalNodeType.Plugin:
|
|
1121
1182
|
return this.serializePlugin(node);
|
|
1183
|
+
case SerovalNodeType.MapSentinel:
|
|
1184
|
+
return this.serializeMapSentinel(node);
|
|
1185
|
+
case SerovalNodeType.IteratorFactory:
|
|
1186
|
+
return this.serializeIteratorFactory(node);
|
|
1187
|
+
case SerovalNodeType.IteratorFactoryInstance:
|
|
1188
|
+
return this.serializeIteratorFactoryInstance(node);
|
|
1189
|
+
case SerovalNodeType.AsyncIteratorFactory:
|
|
1190
|
+
return this.serializeAsyncIteratorFactory(node);
|
|
1191
|
+
case SerovalNodeType.AsyncIteratorFactoryInstance:
|
|
1192
|
+
return this.serializeAsyncIteratorFactoryInstance(node);
|
|
1193
|
+
case SerovalNodeType.ReadableStream:
|
|
1194
|
+
return this.serializeReadableStream(node);
|
|
1195
|
+
case SerovalNodeType.ReadableStreamFactory:
|
|
1196
|
+
return this.serializeReadableStreamFactory(node);
|
|
1122
1197
|
default:
|
|
1123
1198
|
throw new Error('invariant');
|
|
1124
1199
|
}
|
package/src/core/cross/async.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import BaseAsyncParserContext from '../
|
|
2
|
-
import type { CrossParserContextOptions } from './
|
|
1
|
+
import BaseAsyncParserContext from '../context/parser/async';
|
|
2
|
+
import type { CrossParserContextOptions } from './parser';
|
|
3
3
|
import type { SerovalMode } from '../plugin';
|
|
4
4
|
|
|
5
5
|
export type CrossAsyncParserContextOptions = CrossParserContextOptions
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import BaseDeserializerContext from '../context/deserializer';
|
|
2
|
+
import type { BaseDeserializerOptions } from '../context/deserializer';
|
|
3
|
+
import type { SerovalMode } from '../plugin';
|
|
4
|
+
|
|
5
|
+
export type CrossDeserializerContextOptions = BaseDeserializerOptions;
|
|
6
|
+
|
|
7
|
+
export default class CrossDeserializerContext extends BaseDeserializerContext {
|
|
8
|
+
readonly mode: SerovalMode = 'cross';
|
|
9
|
+
|
|
10
|
+
assignIndexedValue<T>(
|
|
11
|
+
index: number,
|
|
12
|
+
value: T,
|
|
13
|
+
): T {
|
|
14
|
+
if (!this.refs.has(index)) {
|
|
15
|
+
this.refs.set(index, value);
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
}
|