json-as 0.5.67 → 0.6.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 +2 -1
- package/assembly/src/json.ts +110 -14
- package/assembly/test.ts +5 -4
- package/package.json +4 -5
- package/transform/lib/index.js +29 -3
- package/transform/package.json +1 -1
- package/transform/src/index.ts +45 -11
package/README.md
CHANGED
|
@@ -59,7 +59,8 @@ const player: Player = {
|
|
|
59
59
|
isVerified: true
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
const stringified = JSON.stringify<Player>(player);
|
|
62
|
+
const stringified = JSON.stringify<Player>(player, true);
|
|
63
|
+
// You can toggle on setting default values with the 2nd parameter
|
|
63
64
|
// Alternative: use JSON.serializeTo(player, out);
|
|
64
65
|
|
|
65
66
|
const parsed = JSON.parse<Player>(stringified);
|
package/assembly/src/json.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StringSink } from "as-string-sink/assembly";
|
|
2
2
|
import { isSpace } from "util/string";
|
|
3
|
+
import { E_INVALIDDATE } from "util/error";
|
|
3
4
|
import {
|
|
4
5
|
backSlashCode,
|
|
5
6
|
commaCode,
|
|
@@ -192,7 +193,7 @@ export namespace JSON {
|
|
|
192
193
|
*/
|
|
193
194
|
|
|
194
195
|
// @ts-ignore: Decorator
|
|
195
|
-
@inline export function parse<T>(data: string): T {
|
|
196
|
+
@inline export function parse<T>(data: string, initializeDefaultValues: boolean = false): T {
|
|
196
197
|
let type: T;
|
|
197
198
|
if (isString<T>()) {
|
|
198
199
|
// @ts-ignore
|
|
@@ -211,10 +212,10 @@ export namespace JSON {
|
|
|
211
212
|
return null;
|
|
212
213
|
// @ts-ignore
|
|
213
214
|
} else if (isDefined(type.__JSON_Set_Key)) {
|
|
214
|
-
return parseObject<T>(data.trimStart());
|
|
215
|
+
return parseObject<T>(data.trimStart(), initializeDefaultValues);
|
|
215
216
|
} else if (idof<nonnull<T>>() == idof<Date>()) {
|
|
216
217
|
// @ts-ignore
|
|
217
|
-
return
|
|
218
|
+
return parseDate(data);
|
|
218
219
|
} else {
|
|
219
220
|
// @ts-ignore
|
|
220
221
|
throw new Error(
|
|
@@ -225,7 +226,7 @@ export namespace JSON {
|
|
|
225
226
|
}
|
|
226
227
|
|
|
227
228
|
// @ts-ignore: Decorator
|
|
228
|
-
@global @inline function __parseObjectValue<T>(data: string): T {
|
|
229
|
+
@global @inline function __parseObjectValue<T>(data: string, initializeDefaultValues: boolean): T {
|
|
229
230
|
let type: T;
|
|
230
231
|
if (isString<T>()) {
|
|
231
232
|
// @ts-ignore
|
|
@@ -288,10 +289,10 @@ export namespace JSON {
|
|
|
288
289
|
return null;
|
|
289
290
|
// @ts-ignore
|
|
290
291
|
} else if (isDefined(type.__JSON_Set_Key)) {
|
|
291
|
-
return parseObject<T>(data.trimStart());
|
|
292
|
+
return parseObject<T>(data.trimStart(), initializeDefaultValues);
|
|
292
293
|
} else if (idof<nonnull<T>>() == idof<Date>()) {
|
|
293
294
|
// @ts-ignore
|
|
294
|
-
return
|
|
295
|
+
return parseDate(data);
|
|
295
296
|
} else {
|
|
296
297
|
// @ts-ignore
|
|
297
298
|
throw new Error(
|
|
@@ -435,10 +436,13 @@ export namespace JSON {
|
|
|
435
436
|
}
|
|
436
437
|
|
|
437
438
|
// @ts-ignore: Decorator
|
|
438
|
-
@inline function parseObject<T>(data: string): T {
|
|
439
|
+
@inline function parseObject<T>(data: string, initializeDefaultValues: boolean): T {
|
|
439
440
|
let schema: nonnull<T> = changetype<nonnull<T>>(
|
|
440
441
|
__new(offsetof<nonnull<T>>(), idof<nonnull<T>>())
|
|
441
442
|
);
|
|
443
|
+
// @ts-ignore
|
|
444
|
+
if (initializeDefaultValues) schema.__JSON_Initialize();
|
|
445
|
+
|
|
442
446
|
let key = Virtual.createEmpty<string>();
|
|
443
447
|
let isKey = false;
|
|
444
448
|
let depth = 0;
|
|
@@ -459,7 +463,7 @@ export namespace JSON {
|
|
|
459
463
|
if (depth === 0) {
|
|
460
464
|
++arrayValueIndex;
|
|
461
465
|
// @ts-ignore
|
|
462
|
-
schema.__JSON_Set_Key<Virtual<string>>(key, data, outerLoopIndex, arrayValueIndex);
|
|
466
|
+
schema.__JSON_Set_Key<Virtual<string>>(key, data, outerLoopIndex, arrayValueIndex, initializeDefaultValues);
|
|
463
467
|
outerLoopIndex = arrayValueIndex;
|
|
464
468
|
isKey = false;
|
|
465
469
|
break;
|
|
@@ -480,7 +484,7 @@ export namespace JSON {
|
|
|
480
484
|
if (depth === 0) {
|
|
481
485
|
++objectValueIndex;
|
|
482
486
|
// @ts-ignore
|
|
483
|
-
schema.__JSON_Set_Key<Virtual<string>>(key, data, outerLoopIndex, objectValueIndex);
|
|
487
|
+
schema.__JSON_Set_Key<Virtual<string>>(key, data, outerLoopIndex, objectValueIndex, initializeDefaultValues);
|
|
484
488
|
outerLoopIndex = objectValueIndex;
|
|
485
489
|
isKey = false;
|
|
486
490
|
break;
|
|
@@ -506,7 +510,7 @@ export namespace JSON {
|
|
|
506
510
|
isKey = true;
|
|
507
511
|
} else {
|
|
508
512
|
// @ts-ignore
|
|
509
|
-
schema.__JSON_Set_Key<Virtual<string>>(key, data, outerLoopIndex, stringValueIndex);
|
|
513
|
+
schema.__JSON_Set_Key<Virtual<string>>(key, data, outerLoopIndex, stringValueIndex, initializeDefaultValues);
|
|
510
514
|
isKey = false;
|
|
511
515
|
}
|
|
512
516
|
outerLoopIndex = ++stringValueIndex;
|
|
@@ -517,7 +521,7 @@ export namespace JSON {
|
|
|
517
521
|
}
|
|
518
522
|
} else if (char == nCode) {
|
|
519
523
|
// @ts-ignore
|
|
520
|
-
schema.__JSON_Set_Key<Virtual<string>>(key, nullWord, 0, 4);
|
|
524
|
+
schema.__JSON_Set_Key<Virtual<string>>(key, nullWord, 0, 4, initializeDefaultValues);
|
|
521
525
|
isKey = false;
|
|
522
526
|
} else if (
|
|
523
527
|
char === tCode &&
|
|
@@ -526,7 +530,7 @@ export namespace JSON {
|
|
|
526
530
|
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
527
531
|
) {
|
|
528
532
|
// @ts-ignore
|
|
529
|
-
schema.__JSON_Set_Key<Virtual<string>>(key, trueWord, 0, 4);
|
|
533
|
+
schema.__JSON_Set_Key<Virtual<string>>(key, trueWord, 0, 4, initializeDefaultValues);
|
|
530
534
|
isKey = false;
|
|
531
535
|
} else if (
|
|
532
536
|
char === fCode &&
|
|
@@ -536,7 +540,7 @@ export namespace JSON {
|
|
|
536
540
|
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
537
541
|
) {
|
|
538
542
|
// @ts-ignore
|
|
539
|
-
schema.__JSON_Set_Key<Virtual<string>>(key, falseWord, 0, 5);
|
|
543
|
+
schema.__JSON_Set_Key<Virtual<string>>(key, falseWord, 0, 5, initializeDefaultValues);
|
|
540
544
|
isKey = false;
|
|
541
545
|
} else if ((char >= 48 && char <= 57) || char === 45) {
|
|
542
546
|
let numberValueIndex = ++outerLoopIndex;
|
|
@@ -544,7 +548,7 @@ export namespace JSON {
|
|
|
544
548
|
const char = unsafeCharCodeAt(data, numberValueIndex);
|
|
545
549
|
if (char === commaCode || char === rightBraceCode || isSpace(char)) {
|
|
546
550
|
// @ts-ignore
|
|
547
|
-
schema.__JSON_Set_Key<Virtual<string>>(key, data, outerLoopIndex - 1, numberValueIndex);
|
|
551
|
+
schema.__JSON_Set_Key<Virtual<string>>(key, data, outerLoopIndex - 1, numberValueIndex, initializeDefaultValues);
|
|
548
552
|
outerLoopIndex = numberValueIndex;
|
|
549
553
|
isKey = false;
|
|
550
554
|
break;
|
|
@@ -711,3 +715,95 @@ export namespace JSON {
|
|
|
711
715
|
}
|
|
712
716
|
return result;
|
|
713
717
|
}
|
|
718
|
+
|
|
719
|
+
// @ts-ignore: decorator
|
|
720
|
+
@inline const
|
|
721
|
+
MILLIS_PER_DAY = 1000 * 60 * 60 * 24,
|
|
722
|
+
MILLIS_PER_HOUR = 1000 * 60 * 60,
|
|
723
|
+
MILLIS_PER_MINUTE = 1000 * 60,
|
|
724
|
+
MILLIS_PER_SECOND = 1000,
|
|
725
|
+
|
|
726
|
+
YEARS_PER_EPOCH = 400,
|
|
727
|
+
DAYS_PER_EPOCH = 146097,
|
|
728
|
+
EPOCH_OFFSET = 719468, // Jan 1, 1970
|
|
729
|
+
MILLIS_LIMIT = 8640000000000000;
|
|
730
|
+
|
|
731
|
+
function parseDate(dateTimeString: string): Date {
|
|
732
|
+
if (!dateTimeString.length) throw new RangeError(E_INVALIDDATE);
|
|
733
|
+
var
|
|
734
|
+
hour: i32 = 0,
|
|
735
|
+
min: i32 = 0,
|
|
736
|
+
sec: i32 = 0,
|
|
737
|
+
ms: i32 = 0;
|
|
738
|
+
|
|
739
|
+
let dateString = dateTimeString;
|
|
740
|
+
let posT = dateTimeString.indexOf("T");
|
|
741
|
+
if (~posT) {
|
|
742
|
+
// includes a time component
|
|
743
|
+
let timeString: string;
|
|
744
|
+
dateString = dateTimeString.substring(0, posT);
|
|
745
|
+
timeString = dateTimeString.substring(posT + 1);
|
|
746
|
+
// parse the HH-MM-SS component
|
|
747
|
+
let timeParts = timeString.split(":");
|
|
748
|
+
let len = timeParts.length;
|
|
749
|
+
if (len <= 1) throw new RangeError(E_INVALIDDATE);
|
|
750
|
+
|
|
751
|
+
hour = i32.parse(timeParts[0]);
|
|
752
|
+
min = i32.parse(timeParts[1]);
|
|
753
|
+
if (len >= 3) {
|
|
754
|
+
let secAndMs = timeParts[2];
|
|
755
|
+
let posDot = secAndMs.indexOf(".");
|
|
756
|
+
if (~posDot) {
|
|
757
|
+
// includes milliseconds
|
|
758
|
+
sec = i32.parse(secAndMs.substring(0, posDot));
|
|
759
|
+
ms = i32.parse(secAndMs.substring(posDot + 1));
|
|
760
|
+
} else {
|
|
761
|
+
sec = i32.parse(secAndMs);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
// parse the YYYY-MM-DD component
|
|
766
|
+
let parts = dateString.split("-");
|
|
767
|
+
let year = i32.parse(parts[0]);
|
|
768
|
+
let month = 1, day = 1;
|
|
769
|
+
let len = parts.length;
|
|
770
|
+
if (len >= 2) {
|
|
771
|
+
month = i32.parse(parts[1]);
|
|
772
|
+
if (len >= 3) {
|
|
773
|
+
day = i32.parse(parts[2]);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
return new Date(epochMillis(year, month, day, hour, min, sec, ms));
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
function epochMillis(
|
|
780
|
+
year: i32,
|
|
781
|
+
month: i32,
|
|
782
|
+
day: i32,
|
|
783
|
+
hour: i32,
|
|
784
|
+
minute: i32,
|
|
785
|
+
second: i32,
|
|
786
|
+
milliseconds: i32
|
|
787
|
+
): i64 {
|
|
788
|
+
return (
|
|
789
|
+
daysSinceEpoch(year, month, day) * MILLIS_PER_DAY +
|
|
790
|
+
hour * MILLIS_PER_HOUR +
|
|
791
|
+
minute * MILLIS_PER_MINUTE +
|
|
792
|
+
second * MILLIS_PER_SECOND +
|
|
793
|
+
milliseconds
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function daysSinceEpoch(y: i32, m: i32, d: i32): i64 {
|
|
798
|
+
y -= i32(m <= 2);
|
|
799
|
+
let era = <u32>floorDiv(y, YEARS_PER_EPOCH);
|
|
800
|
+
let yoe = <u32>y - era * YEARS_PER_EPOCH; // [0, 399]
|
|
801
|
+
let doy = <u32>(153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365]
|
|
802
|
+
let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
|
|
803
|
+
return <i64><i32>(era * 146097 + doe - EPOCH_OFFSET);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// @ts-ignore: decorator
|
|
807
|
+
@inline function floorDiv<T extends number>(a: T, b: T): T {
|
|
808
|
+
return (a - (a < 0 ? b - 1 : 0)) / b as T;
|
|
809
|
+
}
|
package/assembly/test.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { JSON } from "./src/json";
|
|
2
|
+
|
|
2
3
|
// @ts-ignore
|
|
3
4
|
@json
|
|
4
5
|
class Vec3 {
|
|
@@ -12,7 +13,7 @@ class Vec3 {
|
|
|
12
13
|
class Player {
|
|
13
14
|
firstName: string;
|
|
14
15
|
lastName: string;
|
|
15
|
-
lastActive:
|
|
16
|
+
lastActive: Date;
|
|
16
17
|
age: i32;
|
|
17
18
|
pos: Vec3 | null;
|
|
18
19
|
isVerified: boolean;
|
|
@@ -23,7 +24,7 @@ const vec = new Vec3();
|
|
|
23
24
|
const player: Player = {
|
|
24
25
|
firstName: "Emmet",
|
|
25
26
|
lastName: "West",
|
|
26
|
-
lastActive:
|
|
27
|
+
lastActive: new Date(0),
|
|
27
28
|
age: 23,
|
|
28
29
|
pos: {
|
|
29
30
|
x: 3.4,
|
|
@@ -39,11 +40,11 @@ JSON.stringifyTo(vec, out);
|
|
|
39
40
|
|
|
40
41
|
console.log("Original: " + out);
|
|
41
42
|
//console.log("Revised: " + vec.__JSON_Deserialize('{"x":3,"y":1,"z":8}').__JSON_Serialize());
|
|
42
|
-
console.log("Implemented: " + JSON.stringify(JSON.parse<Vec3>('{}')));
|
|
43
|
+
console.log("Implemented: " + JSON.stringify(JSON.parse<Vec3>('{}', true)));
|
|
43
44
|
|
|
44
45
|
console.log("Original: " + JSON.stringify(player));
|
|
45
46
|
//console.log("Revised: " + vec.__JSON_Deserialize('{"x":3,"y":1,"z":8}').__JSON_Serialize());
|
|
46
|
-
console.log("Implemented: " + JSON.stringify(JSON.parse<Player>('{"firstName":"Emmet","lastName":"West","lastActive":
|
|
47
|
+
console.log("Implemented: " + JSON.stringify(JSON.parse<Player>('{"firstName":"Emmet","lastName":"West","lastActive":2023-11-16T04:06:35.108285303Z,"age":23,"pos":{"x":3.4,"y":1.2,"z":8.3},"isVerified":true}')));
|
|
47
48
|
/*
|
|
48
49
|
// 9,325,755
|
|
49
50
|
bench("Stringify Object (Vec3)", () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-as",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "JSON encoder/decoder for AssemblyScript",
|
|
5
5
|
"types": "assembly/index.ts",
|
|
6
6
|
"author": "Jairus Tanaka",
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"test:aspect": "asp",
|
|
18
18
|
"bench:astral": "astral --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior never --runtime stub",
|
|
19
|
-
"build:test": "asc assembly/test.ts -o build/test.wasm --transform ./transform
|
|
20
|
-
"build:test:debug": "asc assembly/test.ts -o build/test.wasm --transform ./transform --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json --optimizeLevel 0 --shrinkLevel 0 --noAssert --uncheckedBehavior always --runtime stub",
|
|
19
|
+
"build:test": "asc assembly/test.ts -o build/test.wasm --transform ./transform --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json --optimizeLevel 0 --shrinkLevel 0 --noAssert --uncheckedBehavior always --runtime stub",
|
|
21
20
|
"build:bench": "asc bench/benchmark.ts -o bench/benchmark.wasm --transform ./transform --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior always --runtime stub",
|
|
22
21
|
"bench:wasmtime": "wasmtime ./bench/benchmark.wasm",
|
|
23
22
|
"bench:wavm": "wavm run ./bench/benchmark.wasm",
|
|
@@ -33,12 +32,12 @@
|
|
|
33
32
|
"@as-tral/cli": "^2.0.1",
|
|
34
33
|
"@assemblyscript/wasi-shim": "^0.1.0",
|
|
35
34
|
"as-bench": "^0.0.0-alpha",
|
|
36
|
-
"assemblyscript": "^0.27.
|
|
35
|
+
"assemblyscript": "^0.27.18",
|
|
37
36
|
"assemblyscript-prettier": "^3.0.1",
|
|
38
37
|
"benchmark": "^2.1.4",
|
|
39
38
|
"kati": "^0.6.2",
|
|
40
39
|
"microtime": "^3.1.1",
|
|
41
|
-
"prettier": "^3.0
|
|
40
|
+
"prettier": "^3.1.0",
|
|
42
41
|
"tinybench": "^2.5.1",
|
|
43
42
|
"typescript": "^5.2.2",
|
|
44
43
|
"visitor-as": "^0.11.4"
|
package/transform/lib/index.js
CHANGED
|
@@ -10,6 +10,7 @@ class SchemaData {
|
|
|
10
10
|
this.parent = "";
|
|
11
11
|
this.encodeStmts = [];
|
|
12
12
|
this.setDataStmts = [];
|
|
13
|
+
this.initializeStmts = [];
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
class AsJSONTransform extends BaseVisitor {
|
|
@@ -49,6 +50,7 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
49
50
|
node: node,
|
|
50
51
|
encodeStmts: [],
|
|
51
52
|
setDataStmts: [],
|
|
53
|
+
initializeStmts: []
|
|
52
54
|
};
|
|
53
55
|
if (this.currentClass.parent.length > 0) {
|
|
54
56
|
const parentSchema = this.schemasList.find((v) => v.name == this.currentClass.parent);
|
|
@@ -100,6 +102,9 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
100
102
|
return;
|
|
101
103
|
}
|
|
102
104
|
`);
|
|
105
|
+
if (member.initializer) {
|
|
106
|
+
this.currentClass.initializeStmts.push(`this.${name} = ${toString(member.initializer)}`);
|
|
107
|
+
}
|
|
103
108
|
}
|
|
104
109
|
else // @ts-ignore
|
|
105
110
|
if ([
|
|
@@ -109,19 +114,25 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
109
114
|
this.currentClass.encodeStmts.push(`"${name}":\${this.${name}.toString()},`);
|
|
110
115
|
// @ts-ignore
|
|
111
116
|
this.currentClass.setDataStmts.push(`if (key.equals("${name}")) {
|
|
112
|
-
this.${name} = __parseObjectValue<${type}>(data.slice(val_start, val_end));
|
|
117
|
+
this.${name} = __parseObjectValue<${type}>(data.slice(val_start, val_end), initializeDefaultValues);
|
|
113
118
|
return;
|
|
114
119
|
}
|
|
115
120
|
`);
|
|
121
|
+
if (member.initializer) {
|
|
122
|
+
this.currentClass.initializeStmts.push(`this.${name} = ${toString(member.initializer)}`);
|
|
123
|
+
}
|
|
116
124
|
}
|
|
117
125
|
else {
|
|
118
126
|
this.currentClass.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
|
|
119
127
|
// @ts-ignore
|
|
120
128
|
this.currentClass.setDataStmts.push(`if (key.equals("${name}")) {
|
|
121
|
-
this.${name} = __parseObjectValue<${type}>(val_start ? data.slice(val_start, val_end) : data);
|
|
129
|
+
this.${name} = __parseObjectValue<${type}>(val_start ? data.slice(val_start, val_end) : data, initializeDefaultValues);
|
|
122
130
|
return;
|
|
123
131
|
}
|
|
124
132
|
`);
|
|
133
|
+
if (member.initializer) {
|
|
134
|
+
this.currentClass.initializeStmts.push(`this.${name} = ${toString(member.initializer)}`);
|
|
135
|
+
}
|
|
125
136
|
}
|
|
126
137
|
}
|
|
127
138
|
}
|
|
@@ -146,16 +157,31 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
146
157
|
// Odd behavior here... When pairing this transform with asyncify, having @inline on __JSON_Set_Key<T> with a generic will cause it to freeze.
|
|
147
158
|
// Binaryen cannot predict and add/mangle code when it is genericed.
|
|
148
159
|
const setKeyFunc = `
|
|
149
|
-
__JSON_Set_Key<T>(key: T, data: string, val_start: i32, val_end: i32): void {
|
|
160
|
+
__JSON_Set_Key<T>(key: T, data: string, val_start: i32, val_end: i32, initializeDefaultValues: boolean): void {
|
|
150
161
|
${
|
|
151
162
|
// @ts-ignore
|
|
152
163
|
this.currentClass.setDataStmts.join("")}
|
|
153
164
|
}
|
|
154
165
|
`;
|
|
166
|
+
let initializeFunc = "";
|
|
167
|
+
if (this.currentClass.initializeStmts.length > 0) {
|
|
168
|
+
initializeFunc = `
|
|
169
|
+
@inline __JSON_Initialize(): void {
|
|
170
|
+
${this.currentClass.initializeStmts.join(";\n")};
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
initializeFunc = `
|
|
176
|
+
@inline __JSON_Initialize(): void {}
|
|
177
|
+
`;
|
|
178
|
+
}
|
|
155
179
|
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
|
|
156
180
|
node.members.push(serializeMethod);
|
|
157
181
|
const setDataMethod = SimpleParser.parseClassMember(setKeyFunc, node);
|
|
158
182
|
node.members.push(setDataMethod);
|
|
183
|
+
const initializeMethod = SimpleParser.parseClassMember(initializeFunc, node);
|
|
184
|
+
node.members.push(initializeMethod);
|
|
159
185
|
this.schemasList.push(this.currentClass);
|
|
160
186
|
//console.log(toString(node));
|
|
161
187
|
}
|
package/transform/package.json
CHANGED
package/transform/src/index.ts
CHANGED
|
@@ -17,7 +17,9 @@ class SchemaData {
|
|
|
17
17
|
public node!: ClassDeclaration;
|
|
18
18
|
public encodeStmts: string[] = [];
|
|
19
19
|
public setDataStmts: string[] = [];
|
|
20
|
+
public initializeStmts: string[] = [];
|
|
20
21
|
}
|
|
22
|
+
|
|
21
23
|
class AsJSONTransform extends BaseVisitor {
|
|
22
24
|
public schemasList: SchemaData[] = [];
|
|
23
25
|
public currentClass!: SchemaData;
|
|
@@ -53,6 +55,7 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
53
55
|
node: node,
|
|
54
56
|
encodeStmts: [],
|
|
55
57
|
setDataStmts: [],
|
|
58
|
+
initializeStmts: []
|
|
56
59
|
};
|
|
57
60
|
|
|
58
61
|
if (this.currentClass.parent.length > 0) {
|
|
@@ -118,6 +121,11 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
118
121
|
}
|
|
119
122
|
`
|
|
120
123
|
);
|
|
124
|
+
if (member.initializer) {
|
|
125
|
+
this.currentClass.initializeStmts.push(
|
|
126
|
+
`this.${name} = ${toString(member.initializer)}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
121
129
|
} else // @ts-ignore
|
|
122
130
|
if (
|
|
123
131
|
[
|
|
@@ -131,24 +139,34 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
131
139
|
// @ts-ignore
|
|
132
140
|
this.currentClass.setDataStmts.push(
|
|
133
141
|
`if (key.equals("${name}")) {
|
|
134
|
-
this.${name} = __parseObjectValue<${type}>(data.slice(val_start, val_end));
|
|
142
|
+
this.${name} = __parseObjectValue<${type}>(data.slice(val_start, val_end), initializeDefaultValues);
|
|
135
143
|
return;
|
|
136
144
|
}
|
|
137
145
|
`
|
|
138
146
|
);
|
|
147
|
+
if (member.initializer) {
|
|
148
|
+
this.currentClass.initializeStmts.push(
|
|
149
|
+
`this.${name} = ${toString(member.initializer)}`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
139
152
|
} else {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
this.${name} = __parseObjectValue<${type}>(val_start ? data.slice(val_start, val_end) : data);
|
|
153
|
+
this.currentClass.encodeStmts.push(
|
|
154
|
+
`"${name}":\${JSON.stringify<${type}>(this.${name})},`
|
|
155
|
+
);
|
|
156
|
+
// @ts-ignore
|
|
157
|
+
this.currentClass.setDataStmts.push(
|
|
158
|
+
`if (key.equals("${name}")) {
|
|
159
|
+
this.${name} = __parseObjectValue<${type}>(val_start ? data.slice(val_start, val_end) : data, initializeDefaultValues);
|
|
147
160
|
return;
|
|
148
161
|
}
|
|
149
162
|
`
|
|
150
|
-
|
|
151
|
-
|
|
163
|
+
);
|
|
164
|
+
if (member.initializer) {
|
|
165
|
+
this.currentClass.initializeStmts.push(
|
|
166
|
+
`this.${name} = ${toString(member.initializer)}`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
152
170
|
}
|
|
153
171
|
}
|
|
154
172
|
|
|
@@ -177,7 +195,7 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
177
195
|
// Odd behavior here... When pairing this transform with asyncify, having @inline on __JSON_Set_Key<T> with a generic will cause it to freeze.
|
|
178
196
|
// Binaryen cannot predict and add/mangle code when it is genericed.
|
|
179
197
|
const setKeyFunc = `
|
|
180
|
-
__JSON_Set_Key<T>(key: T, data: string, val_start: i32, val_end: i32): void {
|
|
198
|
+
__JSON_Set_Key<T>(key: T, data: string, val_start: i32, val_end: i32, initializeDefaultValues: boolean): void {
|
|
181
199
|
${
|
|
182
200
|
// @ts-ignore
|
|
183
201
|
this.currentClass.setDataStmts.join("")
|
|
@@ -185,12 +203,28 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
185
203
|
}
|
|
186
204
|
`;
|
|
187
205
|
|
|
206
|
+
let initializeFunc = "";
|
|
207
|
+
|
|
208
|
+
if (this.currentClass.initializeStmts.length > 0) {
|
|
209
|
+
initializeFunc = `
|
|
210
|
+
@inline __JSON_Initialize(): void {
|
|
211
|
+
${this.currentClass.initializeStmts.join(";\n")};
|
|
212
|
+
}
|
|
213
|
+
`;
|
|
214
|
+
} else {
|
|
215
|
+
initializeFunc = `
|
|
216
|
+
@inline __JSON_Initialize(): void {}
|
|
217
|
+
`;
|
|
218
|
+
}
|
|
188
219
|
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
|
|
189
220
|
node.members.push(serializeMethod);
|
|
190
221
|
|
|
191
222
|
const setDataMethod = SimpleParser.parseClassMember(setKeyFunc, node);
|
|
192
223
|
node.members.push(setDataMethod);
|
|
193
224
|
|
|
225
|
+
const initializeMethod = SimpleParser.parseClassMember(initializeFunc, node);
|
|
226
|
+
node.members.push(initializeMethod);
|
|
227
|
+
|
|
194
228
|
this.schemasList.push(this.currentClass);
|
|
195
229
|
//console.log(toString(node));
|
|
196
230
|
}
|