json-as 1.1.10 → 1.1.12

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.
@@ -1,12 +1,13 @@
1
- import { ClassDeclaration, FieldDeclaration, IdentifierExpression, Parser, Source, NodeKind, CommonFlags, ImportStatement, Node, Tokenizer, SourceKind, NamedTypeNode, Range, FEATURE_SIMD, FunctionExpression, MethodDeclaration, Statement, Program, Feature, CallExpression, PropertyAccessExpression } from "assemblyscript/dist/assemblyscript.js";
1
+ import { ClassDeclaration, FieldDeclaration, IdentifierExpression, Parser, Source, NodeKind, CommonFlags, ImportStatement, Node, SourceKind, NamedTypeNode, Range, FunctionExpression, MethodDeclaration, Program, Feature } from "assemblyscript/dist/assemblyscript.js";
2
2
  import { Transform } from "assemblyscript/dist/transform.js";
3
3
  import { Visitor } from "./visitor.js";
4
- import { cloneNode, isStdlib, removeExtension, replaceRef, SimpleParser, toString } from "./util.js";
4
+ import { isStdlib, removeExtension, SimpleParser, toString } from "./util.js";
5
5
  import * as path from "path";
6
6
  import { fileURLToPath } from "url";
7
- import { Property, PropertyFlags, Schema } from "./types.js";
8
- import { getClass, getClasses, getImportedClass } from "./linker.js";
7
+ import { Property, PropertyFlags, Schema, Src } from "./types.js";
8
+ import { getClass, getImportedClass } from "./linkers/classes.js";
9
9
  import { existsSync, writeFileSync } from "fs";
10
+ import { CustomTransform } from "./linkers/custom.js";
10
11
 
11
12
  let indent = " ";
12
13
 
@@ -25,37 +26,6 @@ const DEBUG = rawValue === "true"
25
26
 
26
27
  const STRICT = process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "true";
27
28
 
28
- class CustomTransform extends Visitor {
29
- static SN: CustomTransform = new CustomTransform();
30
-
31
- private modify: boolean = false;
32
- visitCallExpression(node: CallExpression) {
33
- super.visit(node.args, node);
34
- if (node.expression.kind != NodeKind.PropertyAccess || (node.expression as PropertyAccessExpression).property.text != "stringify") return;
35
- if ((node.expression as PropertyAccessExpression).expression.kind != NodeKind.Identifier || ((node.expression as PropertyAccessExpression).expression as IdentifierExpression).text != "JSON") return;
36
-
37
- if (this.modify) {
38
- (node.expression as PropertyAccessExpression).expression = Node.createPropertyAccessExpression(Node.createIdentifierExpression("JSON", node.expression.range), Node.createIdentifierExpression("internal", node.expression.range), node.expression.range);
39
- }
40
- this.modify = true;
41
-
42
- // console.log(toString(node));
43
- // console.log(SimpleParser.parseStatement("JSON.internal.stringify").expression.expression)
44
- }
45
- static visit(node: Node | Node[], ref: Node | null = null): void {
46
- if (!node) return;
47
- CustomTransform.SN.modify = true;
48
- CustomTransform.SN.visit(node, ref);
49
- CustomTransform.SN.modify = false;
50
- }
51
- static hasCall(node: Node | Node[]): boolean {
52
- if (!node) return;
53
- CustomTransform.SN.modify = false;
54
- CustomTransform.SN.visit(node);
55
- return CustomTransform.SN.modify;
56
- }
57
- }
58
-
59
29
  class JSONTransform extends Visitor {
60
30
  static SN: JSONTransform = new JSONTransform();
61
31
 
@@ -64,14 +34,24 @@ class JSONTransform extends Visitor {
64
34
  public parser!: Parser;
65
35
  public schemas: Map<string, Schema[]> = new Map<string, Schema[]>();
66
36
  public schema!: Schema;
67
- public sources = new Set<Source>();
37
+ public src!: Src;
38
+ public sources: Map<string, Src> = new Map<string, Src>();
68
39
  public imports: ImportStatement[] = [];
69
40
 
70
- public topStatements: Statement[] = [];
71
41
  public simdStatements: string[] = [];
72
42
 
73
43
  private visitedClasses: Set<string> = new Set<string>();
74
44
 
45
+ visitClassDeclarationRef(node: ClassDeclaration): void {
46
+ if (
47
+ !node.decorators?.length ||
48
+ !node.decorators.some((decorator) => {
49
+ const name = (<IdentifierExpression>decorator.name).text;
50
+ return name === "json" || name === "serializable";
51
+ })
52
+ ) throw new Error("Class " + node.name.text + " is missing an @json or @serializable decorator in " + node.range.source.internalPath);
53
+ this.visitClassDeclaration(node);
54
+ }
75
55
  visitClassDeclaration(node: ClassDeclaration): void {
76
56
  if (!node.decorators?.length) return;
77
57
 
@@ -80,11 +60,16 @@ class JSONTransform extends Visitor {
80
60
  const name = (<IdentifierExpression>decorator.name).text;
81
61
  return name === "json" || name === "serializable";
82
62
  })
83
- )
84
- return;
63
+ ) return;
64
+
65
+ const source = node.range.source;
66
+ if (!this.sources.has(source.internalPath)) {
67
+ this.src = new Src(source);
68
+ this.sources.set(source.internalPath, this.src);
69
+ } else this.src = this.sources.get(source.internalPath);
85
70
 
86
- if (this.visitedClasses.has(node.range.source.internalPath + node.name.text)) return;
87
- if (!this.schemas.has(node.range.source.internalPath)) this.schemas.set(node.range.source.internalPath, []);
71
+ if (this.visitedClasses.has(source.internalPath + node.name.text)) return;
72
+ if (!this.schemas.has(source.internalPath)) this.schemas.set(source.internalPath, []);
88
73
 
89
74
  const members: FieldDeclaration[] = [...(node.members.filter((v) => v.kind === NodeKind.FieldDeclaration && v.flags !== CommonFlags.Static && v.flags !== CommonFlags.Private && v.flags !== CommonFlags.Protected && !v.decorators?.some((decorator) => (<IdentifierExpression>decorator.name).text === "omit")) as FieldDeclaration[])];
90
75
  const serializers: MethodDeclaration[] = [...node.members.filter((v) => v.kind === NodeKind.MethodDeclaration && v.decorators && v.decorators.some((e) => (<IdentifierExpression>e.name).text.toLowerCase() === "serializer"))] as MethodDeclaration[];
@@ -99,27 +84,37 @@ class JSONTransform extends Visitor {
99
84
  if (!schema.parent) {
100
85
  const depSearch = schema.deps.find((v) => v.name == extendsName);
101
86
  if (depSearch) {
102
- if (DEBUG > 0) console.log("Found " + extendsName + " in dependencies of " + node.range.source.internalPath);
103
- schema.deps.push(depSearch);
104
- schema.parent = depSearch
87
+ if (DEBUG > 0) console.log("Found " + extendsName + " in dependencies of " + source.internalPath);
88
+ if (!schema.deps.some(v => v.name == depSearch.name)) schema.deps.push(depSearch);
89
+ schema.parent = depSearch;
105
90
  } else {
106
- const internalSearch = getClass(extendsName, node.range.source);
91
+ const internalSearch = getClass(extendsName, source);
107
92
  if (internalSearch) {
108
- if (DEBUG > 0) console.log("Found " + extendsName + " internally from " + node.range.source.internalPath);
109
- this.visitClassDeclaration(internalSearch);
110
- schema.deps.push(this.schema);
111
- this.schemas.get(node.range.source.internalPath).push(this.schema);
112
- schema.parent = this.schema;
113
- this.schema = schema;
93
+ if (DEBUG > 0) console.log("Found " + extendsName + " internally from " + source.internalPath);
94
+ if (!this.visitedClasses.has(internalSearch.range.source.internalPath + internalSearch.name.text)) {
95
+ this.visitClassDeclarationRef(internalSearch);
96
+ this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
97
+ this.visitClassDeclaration(node);
98
+ return;
99
+ }
100
+ const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find(s => s.name == internalSearch.name.text);
101
+ if (!schem) throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
102
+ schema.deps.push(schem);
103
+ schema.parent = schem;
114
104
  } else {
115
- const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
105
+ const externalSearch = getImportedClass(extendsName, source, this.parser);
116
106
  if (externalSearch) {
117
- if (DEBUG > 0) console.log("Found " + externalSearch.name.text + " externally from " + node.range.source.internalPath);
118
- this.visitClassDeclaration(externalSearch);
119
- schema.deps.push(this.schema);
120
- this.schemas.get(node.range.source.internalPath).push(this.schema);
121
- schema.parent = this.schema;
122
- this.schema = schema;
107
+ if (DEBUG > 0) console.log("Found " + externalSearch.name.text + " externally from " + source.internalPath);
108
+ if (!this.visitedClasses.has(externalSearch.range.source.internalPath + externalSearch.name.text)) {
109
+ this.visitClassDeclarationRef(externalSearch);
110
+ this.schemas.get(externalSearch.range.source.internalPath).push(this.schema);
111
+ this.visitClassDeclaration(node);
112
+ return;
113
+ }
114
+ const schem = this.schemas.get(externalSearch.range.source.internalPath)?.find(s => s.name == externalSearch.name.text);
115
+ if (!schem) throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSearch.range.source.internalPath);
116
+ schema.deps.push(schem);
117
+ schema.parent = schem;
123
118
  }
124
119
  }
125
120
  }
@@ -136,6 +131,7 @@ class JSONTransform extends Visitor {
136
131
 
137
132
  const getUnknownTypes = (type: string, types: string[] = []): string[] => {
138
133
  type = stripNull(type);
134
+ type = this.src.aliases.find(v => stripNull(v.name) == type)?.getBaseType() || type;
139
135
  if (type.startsWith("Array<")) {
140
136
  return getUnknownTypes(type.slice(6, -1));
141
137
  } else if (type.startsWith("Map<")) {
@@ -161,33 +157,43 @@ class JSONTransform extends Visitor {
161
157
  for (const unknownType of unknown) {
162
158
  const depSearch = schema.deps.find((v) => v.name == unknownType);
163
159
  if (depSearch) {
164
- if (DEBUG > 0) console.log("Found " + unknownType + " in dependencies of " + node.range.source.internalPath);
165
- schema.deps.push(depSearch);
166
- continue;
167
- }
168
- const internalSearch = getClass(unknownType, node.range.source);
169
- if (internalSearch) {
170
- if (DEBUG > 0) console.log("Found " + unknownType + " internally from " + node.range.source.internalPath);
171
- this.visitClassDeclaration(internalSearch);
172
- this.schemas.get(node.range.source.internalPath).push(this.schema);
173
- schema.deps.push(this.schema);
174
- this.schema = schema;
160
+ if (DEBUG > 0) console.log("Found " + unknownType + " in dependencies of " + source.internalPath);
161
+ if (!schema.deps.some(v => v.name == depSearch.name)) schema.deps.push(depSearch);
175
162
  } else {
176
- const externalSearch = getImportedClass(unknownType, node.range.source, this.parser);
177
- if (externalSearch) {
178
- if (DEBUG > 0) console.log("Found " + externalSearch.name.text + " externally from " + node.range.source.internalPath);
179
- this.visitClassDeclaration(externalSearch);
180
- this.schemas.get(node.range.source.internalPath).push(this.schema);
181
- schema.deps.push(this.schema);
182
- this.schema = schema;
163
+ const internalSearch = getClass(unknownType, source);
164
+ if (internalSearch) {
165
+ if (DEBUG > 0) console.log("Found " + unknownType + " internally from " + source.internalPath);
166
+ if (!this.visitedClasses.has(internalSearch.range.source.internalPath + internalSearch.name.text)) {
167
+ this.visitClassDeclarationRef(internalSearch);
168
+ this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
169
+ this.visitClassDeclaration(node);
170
+ return;
171
+ }
172
+ const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find(s => s.name == internalSearch.name.text);
173
+ if (!schem) throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
174
+ schema.deps.push(schem);
175
+ } else {
176
+ const externalSearch = getImportedClass(unknownType, source, this.parser);
177
+ if (externalSearch) {
178
+ if (DEBUG > 0) console.log("Found " + externalSearch.name.text + " externally from " + source.internalPath);
179
+ if (!this.visitedClasses.has(externalSearch.range.source.internalPath + externalSearch.name.text)) {
180
+ this.visitClassDeclarationRef(externalSearch);
181
+ this.schemas.get(externalSearch.range.source.internalPath).push(this.schema);
182
+ this.visitClassDeclaration(node);
183
+ return;
184
+ }
185
+ const schem = this.schemas.get(externalSearch.range.source.internalPath)?.find(s => s.name == externalSearch.name.text);
186
+ if (!schem) throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSearch.range.source.internalPath);
187
+ schema.deps.push(schem);
188
+ }
183
189
  }
184
190
  }
185
191
  }
186
192
  }
187
193
 
188
- this.schemas.get(node.range.source.internalPath).push(schema);
194
+ this.schemas.get(source.internalPath).push(schema);
189
195
  this.schema = schema;
190
- this.visitedClasses.add(node.range.source.internalPath + node.name.text);
196
+ this.visitedClasses.add(source.internalPath + node.name.text);
191
197
 
192
198
  let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
193
199
  let INITIALIZE = "@inline __INITIALIZE(): this {\n";
@@ -195,7 +201,7 @@ class JSONTransform extends Visitor {
195
201
  let DESERIALIZE_CUSTOM = "";
196
202
  let SERIALIZE_CUSTOM = "";
197
203
 
198
- if (DEBUG > 0) console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath + (this.schema.deps.length ? " with dependencies:\n " + this.schema.deps.map((v) => v.name).join("\n ") : ""));
204
+ if (DEBUG > 0) console.log("Created schema: " + this.schema.name + " in file " + source.normalizedPath + (this.schema.deps.length ? " with dependencies:\n " + this.schema.deps.map((v) => v.name).join("\n ") : ""));
199
205
 
200
206
  if (serializers.length > 1) throwError("Multiple serializers detected for class " + node.name.text + " but schemas can only have one serializer!", serializers[1].range);
201
207
  if (deserializers.length > 1) throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
@@ -248,7 +254,9 @@ class JSONTransform extends Visitor {
248
254
 
249
255
  for (const member of members) {
250
256
  if (!member.type) throwError("Fields must be strongly typed", node.range);
251
- const type = toString(member.type!);
257
+ let type = toString(member.type!);
258
+ type = this.src.aliases.find(v => stripNull(v.name) == stripNull(type))?.getBaseType() || type;
259
+
252
260
  const name = member.name;
253
261
  const value = member.initializer ? toString(member.initializer!) : null;
254
262
 
@@ -418,16 +426,27 @@ class JSONTransform extends Visitor {
418
426
  };
419
427
 
420
428
  for (const member of this.schema.members) {
421
- if (member.type.endsWith(" | null")) sortedMembers.null.push(member);
422
- if (isString(member.type) || member.type == "JSON.Raw") sortedMembers.string.push(member);
423
- else if (isBoolean(member.type) || member.type.startsWith("JSON.Box<bool")) sortedMembers.boolean.push(member);
424
- else if (isPrimitive(member.type) || member.type.startsWith("JSON.Box<")) sortedMembers.number.push(member);
425
- else if (isArray(member.type)) sortedMembers.array.push(member);
426
- else sortedMembers.object.push(member);
429
+ const type = stripNull(member.type);
430
+ if (node.isGeneric && node.typeParameters.some((p) => stripNull(p.name.text) == type)) {
431
+ member.generic = true;
432
+ sortedMembers.string.push(member);
433
+ sortedMembers.number.push(member);
434
+ sortedMembers.object.push(member);
435
+ sortedMembers.array.push(member);
436
+ sortedMembers.boolean.push(member);
437
+ sortedMembers.null.push(member);
438
+ } else {
439
+ if (member.node.type.isNullable) sortedMembers.null.push(member);
440
+ if (isString(type) || type == "JSON.Raw") sortedMembers.string.push(member);
441
+ else if (isBoolean(type) || type.startsWith("JSON.Box<bool")) sortedMembers.boolean.push(member);
442
+ else if (isPrimitive(type) || type.startsWith("JSON.Box<")) sortedMembers.number.push(member);
443
+ else if (isArray(type)) sortedMembers.array.push(member);
444
+ else if (isStruct(type, source)) sortedMembers.object.push(member);
445
+ else throw new Error("Could not determine type " + type + " for member " + member.name + " in class " + this.schema.name);
446
+ }
427
447
  }
428
448
 
429
449
  indent = "";
430
- let shouldGroup = false;
431
450
 
432
451
  DESERIALIZE += indent + " let keyStart: usize = 0;\n";
433
452
  DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
@@ -599,22 +618,22 @@ class JSONTransform extends Visitor {
599
618
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
600
619
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
601
620
  DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
602
- if (DEBUG > 1)DESERIALIZE += " console.log(\"Value (string, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart + 2));";
621
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (string, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart + 2));";
603
622
  generateGroups(sortedMembers.string, (group) => {
604
623
  generateConsts(group);
605
624
  const first = group[0];
606
625
  const fName = first.alias || first.name;
607
- DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
626
+ DESERIALIZE += indent + " if (" + (first.generic ? "isString<" + first.type + ">() && " : "") + getComparision(fName) + ") { // " + fName + "\n";
608
627
  DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
609
628
  DESERIALIZE += indent + " srcStart += 4;\n";
610
629
  DESERIALIZE += indent + " keyStart = 0;\n";
611
630
  DESERIALIZE += indent + " break;\n";
612
631
  DESERIALIZE += indent + " }";
613
632
 
614
- for (let i = 1; i <group.length; i++) {
633
+ for (let i = 1; i < group.length; i++) {
615
634
  const mem = group[i];
616
635
  const memName = mem.alias || mem.name;
617
- DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
636
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isString<" + mem.type + ">() && " : "") + getComparision(memName) + ") { // " + memName + "\n";
618
637
  DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
619
638
  DESERIALIZE += indent + " srcStart += 4;\n";
620
639
  DESERIALIZE += indent + " keyStart = 0;\n";
@@ -655,7 +674,7 @@ class JSONTransform extends Visitor {
655
674
  generateConsts(group);
656
675
  const first = group[0];
657
676
  const fName = first.alias || first.name;
658
- DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
677
+ DESERIALIZE += indent + " if (" + (first.generic ? "(isInteger<" + first.type + ">() || isFloat<" + first.type + ">()) && " : "") + getComparision(fName) + ") { // " + fName + "\n";
659
678
  DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
660
679
  DESERIALIZE += indent + " srcStart += 2;\n";
661
680
  DESERIALIZE += indent + " keyStart = 0;\n";
@@ -665,7 +684,7 @@ class JSONTransform extends Visitor {
665
684
  for (let i = 1; i < group.length; i++) {
666
685
  const mem = group[i];
667
686
  const memName = mem.alias || mem.name;
668
- DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
687
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "(isInteger<" + mem.type + ">() || isFloat<" + mem.type + ">()) && " : "") + getComparision(memName) + ") { // " + memName + "\n";
669
688
  DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
670
689
  DESERIALIZE += indent + " srcStart += 2;\n";
671
690
  DESERIALIZE += indent + " keyStart = 0;\n";
@@ -712,7 +731,7 @@ class JSONTransform extends Visitor {
712
731
  generateConsts(group);
713
732
  const first = group[0];
714
733
  const fName = first.alias || first.name;
715
- DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
734
+ DESERIALIZE += indent + " if (" + (first.generic ? "isDefined(out.__DESERIALIZE) &&" : "") + getComparision(fName) + ") { // " + fName + "\n";
716
735
  DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
717
736
  DESERIALIZE += indent + " keyStart = 0;\n";
718
737
  DESERIALIZE += indent + " break;\n";
@@ -721,7 +740,7 @@ class JSONTransform extends Visitor {
721
740
  for (let i = 1; i < group.length; i++) {
722
741
  const mem = group[i];
723
742
  const memName = mem.alias || mem.name;
724
- DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
743
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isDefined(out.__DESERIALIZE) &&" : "") + getComparision(memName) + ") { // " + memName + "\n";
725
744
  DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
726
745
  DESERIALIZE += indent + " keyStart = 0;\n";
727
746
  DESERIALIZE += indent + " break;\n";
@@ -768,7 +787,7 @@ class JSONTransform extends Visitor {
768
787
  generateConsts(group);
769
788
  const first = group[0];
770
789
  const fName = first.alias || first.name;
771
- DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
790
+ DESERIALIZE += indent + " if (" + (first.generic ? "isArray<" + first.type + ">() && " : "") + getComparision(fName) + ") { // " + fName + "\n";
772
791
  DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
773
792
  DESERIALIZE += indent + " keyStart = 0;\n";
774
793
  DESERIALIZE += indent + " break;\n";
@@ -777,7 +796,7 @@ class JSONTransform extends Visitor {
777
796
  for (let i = 1; i < group.length; i++) {
778
797
  const mem = group[i];
779
798
  const memName = mem.alias || mem.name;
780
- DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
799
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isArray" + mem.type + ">() && " : "") + getComparision(memName) + ") { // " + memName + "\n";
781
800
  DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
782
801
  DESERIALIZE += indent + " keyStart = 0;\n";
783
802
  DESERIALIZE += indent + " break;\n";
@@ -813,39 +832,39 @@ class JSONTransform extends Visitor {
813
832
  DESERIALIZE += " srcStart += 8;\n";
814
833
  if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
815
834
  generateGroups(sortedMembers.boolean, (group) => {
816
- generateConsts(group);
835
+ generateConsts(group);
817
836
  const first = group[0];
818
- const fName =first.alias || first.name;
819
- DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
820
- DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
837
+ const fName = first.alias || first.name;
838
+ DESERIALIZE += indent + " if (" + (first.generic ? "isBoolean<" + first.type + ">() && " : "") + getComparision(fName) + ") { // " + fName + "\n";
839
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
840
+ DESERIALIZE += indent + " srcStart += 2;\n";
841
+ DESERIALIZE += indent + " keyStart = 0;\n";
842
+ DESERIALIZE += indent + " break;\n";
843
+ DESERIALIZE += indent + " }";
844
+
845
+ for (let i = 1; i < group.length; i++) {
846
+ const mem = group[i];
847
+ const memName = mem.alias || mem.name;
848
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isBoolean<" + mem.type + ">() && " : "") + getComparision(memName) + ") { // " + memName + "\n";
849
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
821
850
  DESERIALIZE += indent + " srcStart += 2;\n";
822
851
  DESERIALIZE += indent + " keyStart = 0;\n";
823
852
  DESERIALIZE += indent + " break;\n";
824
853
  DESERIALIZE += indent + " }";
854
+ }
825
855
 
826
- for (let i = 1; i < group.length; i++) {
827
- const mem = group[i];
828
- const memName = mem.alias || mem.name;
829
- DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
830
- DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
831
- DESERIALIZE += indent + " srcStart += 2;\n";
832
- DESERIALIZE += indent + " keyStart = 0;\n";
833
- DESERIALIZE += indent + " break;\n";
834
- DESERIALIZE += indent + " }";
835
- }
836
-
837
- if (STRICT) {
838
- DESERIALIZE += " else {\n";
839
- DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
840
- DESERIALIZE += indent + " }\n";
841
- } else {
842
- DESERIALIZE += " else { \n";
843
- DESERIALIZE += indent + " srcStart += 2;\n";
844
- DESERIALIZE += indent + " keyStart = 0;\n";
845
- DESERIALIZE += indent + " break;\n";
846
- DESERIALIZE += indent + " }\n";
847
- }
848
- },
856
+ if (STRICT) {
857
+ DESERIALIZE += " else {\n";
858
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
859
+ DESERIALIZE += indent + " }\n";
860
+ } else {
861
+ DESERIALIZE += " else { \n";
862
+ DESERIALIZE += indent + " srcStart += 2;\n";
863
+ DESERIALIZE += indent + " keyStart = 0;\n";
864
+ DESERIALIZE += indent + " break;\n";
865
+ DESERIALIZE += indent + " }\n";
866
+ }
867
+ },
849
868
  "boolean",
850
869
  );
851
870
 
@@ -863,41 +882,41 @@ class JSONTransform extends Visitor {
863
882
  DESERIALIZE += " if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
864
883
  DESERIALIZE += " srcStart += 10;\n";
865
884
  if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 10));";
866
- generateGroups( sortedMembers.boolean, (group) => {
867
- generateConsts(group);
885
+ generateGroups(sortedMembers.boolean, (group) => {
886
+ generateConsts(group);
868
887
 
869
- const first = group[0];
870
- const fName = first.alias || first.name;
871
- DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
872
- DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
888
+ const first = group[0];
889
+ const fName = first.alias || first.name;
890
+ DESERIALIZE += indent + " if (" + (first.generic ? "isBoolean<" + first.type + ">() && " : "") + getComparision(fName) + ") { // " + fName + "\n";
891
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
892
+ DESERIALIZE += indent + " srcStart += 2;\n";
893
+ DESERIALIZE += indent + " keyStart = 0;\n";
894
+ DESERIALIZE += indent + " break;\n";
895
+ DESERIALIZE += indent + " }";
896
+
897
+ for (let i = 1; i < group.length; i++) {
898
+ const mem = group[i];
899
+ const memName = mem.alias || mem.name;
900
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isBoolean<" + mem.type + ">() && " : "") + getComparision(memName) + ") { // " + memName + "\n";
901
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
873
902
  DESERIALIZE += indent + " srcStart += 2;\n";
874
903
  DESERIALIZE += indent + " keyStart = 0;\n";
875
904
  DESERIALIZE += indent + " break;\n";
876
905
  DESERIALIZE += indent + " }";
906
+ }
877
907
 
878
- for (let i = 1; i < group.length; i++) {
879
- const mem = group[i];
880
- const memName = mem.alias || mem.name;
881
- DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
882
- DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
883
- DESERIALIZE += indent + " srcStart += 2;\n";
884
- DESERIALIZE += indent + " keyStart = 0;\n";
885
- DESERIALIZE += indent + " break;\n";
886
- DESERIALIZE += indent + " }";
887
- }
888
-
889
- if (STRICT) {
890
- DESERIALIZE += " else {\n";
891
- DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
892
- DESERIALIZE += indent + " }\n";
893
- } else {
894
- DESERIALIZE += " else { \n";
895
- DESERIALIZE += indent + " srcStart += 2;\n";
896
- DESERIALIZE += indent + " keyStart = 0;\n";
897
- DESERIALIZE += indent + " break;\n";
898
- DESERIALIZE += indent + " }\n";
899
- }
900
- },
908
+ if (STRICT) {
909
+ DESERIALIZE += " else {\n";
910
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
911
+ DESERIALIZE += indent + " }\n";
912
+ } else {
913
+ DESERIALIZE += " else { \n";
914
+ DESERIALIZE += indent + " srcStart += 2;\n";
915
+ DESERIALIZE += indent + " keyStart = 0;\n";
916
+ DESERIALIZE += indent + " break;\n";
917
+ DESERIALIZE += indent + " }\n";
918
+ }
919
+ },
901
920
  "boolean",
902
921
  );
903
922
 
@@ -920,37 +939,37 @@ class JSONTransform extends Visitor {
920
939
  generateConsts(group);
921
940
 
922
941
  const first = group[0];
923
- const fName = first.alias || first.name;
924
- DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
925
- DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
942
+ const fName = first.alias || first.name;
943
+ DESERIALIZE += indent + " if (" + (first.generic ? "isNullable<" + first.type + ">() && " : "") + getComparision(fName) + ") { // " + fName + "\n";
944
+ DESERIALIZE += indent + " store<usize>(changetype<usize>(out), 0, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
945
+ DESERIALIZE += indent + " srcStart += 2;\n";
946
+ DESERIALIZE += indent + " keyStart = 0;\n";
947
+ DESERIALIZE += indent + " break;\n";
948
+ DESERIALIZE += indent + " }";
949
+
950
+ for (let i = 1; i < group.length; i++) {
951
+ const mem = group[i];
952
+ const memName = mem.alias || mem.name;
953
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isNullable<" + mem.type + ">() && " : "") + getComparision(memName) + ") { // " + memName + "\n";
954
+ DESERIALIZE += indent + " store<usize>(changetype<usize>(out), 0, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
926
955
  DESERIALIZE += indent + " srcStart += 2;\n";
927
956
  DESERIALIZE += indent + " keyStart = 0;\n";
928
957
  DESERIALIZE += indent + " break;\n";
929
958
  DESERIALIZE += indent + " }";
959
+ }
930
960
 
931
- for (let i = 1; i < group.length; i++) {
932
- const mem = group[i];
933
- const memName = mem.alias || mem.name;
934
- DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
935
- DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
936
- DESERIALIZE += indent + " srcStart += 2;\n";
937
- DESERIALIZE += indent + " keyStart = 0;\n";
938
- DESERIALIZE += indent + " break;\n";
939
- DESERIALIZE += indent + " }";
940
- }
941
-
942
- if (STRICT) {
943
- DESERIALIZE += " else {\n";
944
- DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
945
- DESERIALIZE += indent + " }\n";
946
- } else {
947
- DESERIALIZE += " else { \n";
948
- DESERIALIZE += indent + " srcStart += 2;\n";
949
- DESERIALIZE += indent + " keyStart = 0;\n";
950
- DESERIALIZE += indent + " break;\n";
951
- DESERIALIZE += indent + " }\n";
952
- }
953
- },
961
+ if (STRICT) {
962
+ DESERIALIZE += " else {\n";
963
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
964
+ DESERIALIZE += indent + " }\n";
965
+ } else {
966
+ DESERIALIZE += " else { \n";
967
+ DESERIALIZE += indent + " srcStart += 2;\n";
968
+ DESERIALIZE += indent + " keyStart = 0;\n";
969
+ DESERIALIZE += indent + " break;\n";
970
+ DESERIALIZE += indent + " }\n";
971
+ }
972
+ },
954
973
  "null",
955
974
  );
956
975
 
@@ -1074,7 +1093,7 @@ class JSONTransform extends Visitor {
1074
1093
  )
1075
1094
  ? path.join(pkgPath, fromPath.slice(5))
1076
1095
  : fromPath
1077
- : path.join(baseDir, fromPath);
1096
+ : path.join(this.baseCWD, fromPath);
1078
1097
 
1079
1098
  const bsImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "bs" || d.name.text == "bs"));
1080
1099
  const jsonImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "JSON" || d.name.text == "JSON"));
@@ -1237,10 +1256,6 @@ export default class Transformer extends Transform {
1237
1256
  transformer.currentSource = source;
1238
1257
  transformer.visit(source);
1239
1258
 
1240
- if (transformer.topStatements.length) {
1241
- source.statements.unshift(...transformer.topStatements);
1242
- transformer.topStatements = [];
1243
- }
1244
1259
  if (transformer.simdStatements.length) {
1245
1260
  for (const simd of transformer.simdStatements) source.statements.unshift(SimpleParser.parseTopLevelStatement(simd));
1246
1261
  }