json-as 1.1.9 → 1.1.10

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,15 +1,28 @@
1
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";
2
2
  import { Transform } from "assemblyscript/dist/transform.js";
3
3
  import { Visitor } from "./visitor.js";
4
- import { cloneNode, isStdlib, replaceRef, SimpleParser, toString } from "./util.js";
4
+ import { cloneNode, isStdlib, removeExtension, replaceRef, SimpleParser, toString } from "./util.js";
5
5
  import * as path from "path";
6
6
  import { fileURLToPath } from "url";
7
7
  import { Property, PropertyFlags, Schema } from "./types.js";
8
- import { getClasses, getImportedClass } from "./linker.js";
8
+ import { getClass, getClasses, getImportedClass } from "./linker.js";
9
+ import { existsSync, writeFileSync } from "fs";
9
10
 
10
11
  let indent = " ";
11
12
 
12
- const DEBUG = process.env["JSON_DEBUG"];
13
+ let id = 0;
14
+
15
+ const WRITE = process.env["JSON_WRITE"];
16
+ const rawValue = process.env["JSON_DEBUG"];
17
+
18
+ const DEBUG = rawValue === "true"
19
+ ? 1
20
+ : rawValue === "false" || rawValue === ""
21
+ ? 0
22
+ : isNaN(Number(rawValue))
23
+ ? 0
24
+ : Number(rawValue);
25
+
13
26
  const STRICT = process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "true";
14
27
 
15
28
  class CustomTransform extends Visitor {
@@ -47,9 +60,9 @@ class JSONTransform extends Visitor {
47
60
  static SN: JSONTransform = new JSONTransform();
48
61
 
49
62
  public program!: Program;
50
- public baseDir!: string;
63
+ public baseCWD!: string;
51
64
  public parser!: Parser;
52
- public schemas: Schema[] = [];
65
+ public schemas: Map<string, Schema[]> = new Map<string, Schema[]>();
53
66
  public schema!: Schema;
54
67
  public sources = new Set<Source>();
55
68
  public imports: ImportStatement[] = [];
@@ -57,6 +70,8 @@ class JSONTransform extends Visitor {
57
70
  public topStatements: Statement[] = [];
58
71
  public simdStatements: string[] = [];
59
72
 
73
+ private visitedClasses: Set<string> = new Set<string>();
74
+
60
75
  visitClassDeclaration(node: ClassDeclaration): void {
61
76
  if (!node.decorators?.length) return;
62
77
 
@@ -68,11 +83,111 @@ class JSONTransform extends Visitor {
68
83
  )
69
84
  return;
70
85
 
71
- this.schema = new Schema();
72
- this.schema.node = node;
73
- this.schema.name = node.name.text;
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, []);
88
+
89
+ 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
+ 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[];
91
+ const deserializers: MethodDeclaration[] = [...node.members.filter((v) => v.kind === NodeKind.MethodDeclaration && v.decorators && v.decorators.some((e) => (<IdentifierExpression>e.name).text.toLowerCase() === "deserializer"))] as MethodDeclaration[];
92
+
93
+ const schema = new Schema();
94
+ schema.node = node;
95
+ schema.name = node.name.text;
96
+
97
+ if (node.extendsType) {
98
+ const extendsName = node.extendsType?.name.identifier.text;
99
+ if (!schema.parent) {
100
+ const depSearch = schema.deps.find((v) => v.name == extendsName);
101
+ 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
105
+ } else {
106
+ const internalSearch = getClass(extendsName, node.range.source);
107
+ 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;
114
+ } else {
115
+ const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
116
+ 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;
123
+ }
124
+ }
125
+ }
126
+ }
127
+ if (schema.parent?.members) {
128
+ for (let i = schema.parent.members.length - 1; i >= 0; i--) {
129
+ const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
130
+ if (!replace) {
131
+ members.unshift(schema.parent?.members[i]!.node);
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ const getUnknownTypes = (type: string, types: string[] = []): string[] => {
138
+ type = stripNull(type);
139
+ if (type.startsWith("Array<")) {
140
+ return getUnknownTypes(type.slice(6, -1));
141
+ } else if (type.startsWith("Map<")) {
142
+ const parts = type.slice(4, -1).split(",");
143
+ return getUnknownTypes(parts[0]) || getUnknownTypes(parts[1]);
144
+ } else if (isString(type) || isPrimitive(type)) {
145
+ return types;
146
+ } else if (["JSON.Box", "JSON.Obj", "JSON.Value", "JSON.Raw"].includes(type)) {
147
+ return types;
148
+ } else if (node.isGeneric && node.typeParameters.some((p) => p.name.text == type)) {
149
+ return types;
150
+ } else if (type == node.name.text) {
151
+ return types;
152
+ }
153
+ types.push(type);
154
+ return types;
155
+ }
156
+
157
+ for (const member of members) {
158
+ const type = toString(member.type);
159
+ const unknown = getUnknownTypes(type);
160
+
161
+ for (const unknownType of unknown) {
162
+ const depSearch = schema.deps.find((v) => v.name == unknownType);
163
+ 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;
175
+ } 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;
183
+ }
184
+ }
185
+ }
186
+ }
74
187
 
75
- this.schemas.push(this.schema);
188
+ this.schemas.get(node.range.source.internalPath).push(schema);
189
+ this.schema = schema;
190
+ this.visitedClasses.add(node.range.source.internalPath + node.name.text);
76
191
 
77
192
  let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
78
193
  let INITIALIZE = "@inline __INITIALIZE(): this {\n";
@@ -80,11 +195,7 @@ class JSONTransform extends Visitor {
80
195
  let DESERIALIZE_CUSTOM = "";
81
196
  let SERIALIZE_CUSTOM = "";
82
197
 
83
- if (DEBUG) console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath);
84
-
85
- 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[])];
86
- 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[];
87
- const deserializers: MethodDeclaration[] = [...node.members.filter((v) => v.kind === NodeKind.MethodDeclaration && v.decorators && v.decorators.some((e) => (<IdentifierExpression>e.name).text.toLowerCase() === "deserializer"))] as MethodDeclaration[];
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 ") : ""));
88
199
 
89
200
  if (serializers.length > 1) throwError("Multiple serializers detected for class " + node.name.text + " but schemas can only have one serializer!", serializers[1].range);
90
201
  if (deserializers.length > 1) throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
@@ -130,43 +241,11 @@ class JSONTransform extends Visitor {
130
241
  DESERIALIZE_CUSTOM += " }\n";
131
242
  }
132
243
 
133
- if (node.extendsType) {
134
- const extendsName = node.extendsType?.name.identifier.text;
135
- this.schema.parent = this.schemas.find((v) => v.name == extendsName) as Schema | null;
136
- if (!this.schema.parent) {
137
- const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
138
- if (internalSearch) {
139
- if (DEBUG) console.log("Found " + extendsName + " internally");
140
- this.visitClassDeclaration(internalSearch);
141
- this.visitClassDeclaration(node);
142
- return;
143
- }
144
-
145
- const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
146
- if (externalSearch) {
147
- if (DEBUG) console.log("Found " + extendsName + " externally");
148
- this.visitClassDeclaration(externalSearch);
149
- this.visitClassDeclaration(node);
150
- return;
151
- }
152
- }
153
- if (this.schema.parent?.members) {
154
- for (let i = this.schema.parent.members.length - 1; i >= 0; i--) {
155
- const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name);
156
- if (!replace) {
157
- members.unshift(this.schema.parent?.members[i]!.node);
158
- }
159
- }
160
- }
161
- }
162
-
163
244
  if (!members.length) {
164
245
  this.generateEmptyMethods(node);
165
246
  return;
166
247
  }
167
248
 
168
- this.addRequiredImports(node.range.source);
169
-
170
249
  for (const member of members) {
171
250
  if (!member.type) throwError("Fields must be strongly typed", node.range);
172
251
  const type = toString(member.type!);
@@ -234,22 +313,6 @@ class JSONTransform extends Visitor {
234
313
  SERIALIZE += indent + "bs.offset += 2;\n";
235
314
  }
236
315
 
237
- for (const member of this.schema.members) {
238
- if (isStruct(member.type)) {
239
- const schema = this.schemas.find((v) => v.name == stripNull(member.type));
240
- if (!schema) continue;
241
-
242
- if (!this.schema.deps.includes(schema)) {
243
- this.schema.deps.push(schema);
244
- this.schema.byteSize += schema.byteSize;
245
- }
246
-
247
- // if (schema.custom) {
248
- // member.flags.set(PropertyFlags.Custom, null);
249
- // }
250
- }
251
- }
252
-
253
316
  let isPure = this.schema.static;
254
317
  let isRegular = isPure;
255
318
  let isFirst = true;
@@ -263,7 +326,7 @@ class JSONTransform extends Visitor {
263
326
 
264
327
  if (member.value) {
265
328
  INITIALIZE += ` this.${member.name} = ${member.value};\n`;
266
- } else if (this.schemas.find((v) => nonNullType == v.name)) {
329
+ } else if (this.getSchema(nonNullType)) {
267
330
  INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`;
268
331
  } else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
269
332
  INITIALIZE += ` this.${member.name} = [];\n`;
@@ -366,7 +429,6 @@ class JSONTransform extends Visitor {
366
429
  indent = "";
367
430
  let shouldGroup = false;
368
431
 
369
- // DESERIALIZE += indent + " console.log(\"data: \" + JSON.Util.ptrToStr(srcStart,srcEnd))\n";
370
432
  DESERIALIZE += indent + " let keyStart: usize = 0;\n";
371
433
  DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
372
434
  DESERIALIZE += indent + " let isKey = false;\n";
@@ -388,6 +450,7 @@ class JSONTransform extends Visitor {
388
450
  DESERIALIZE += indent + " if (isKey) {\n";
389
451
  DESERIALIZE += indent + " keyStart = lastIndex;\n";
390
452
  DESERIALIZE += indent + " keyEnd = srcStart;\n";
453
+ if (DEBUG > 1) DESERIALIZE += indent + " console.log(\"Key: \" + JSON.Util.ptrToStr(keyStart, keyEnd));\n";
391
454
  DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
392
455
  DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
393
456
  DESERIALIZE += indent + " isKey = false;\n";
@@ -471,10 +534,14 @@ class JSONTransform extends Visitor {
471
534
  if (STRICT) {
472
535
  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';
473
536
  } else {
474
- if (type == "string") DESERIALIZE += indent + " srcStart += 4;\n";
475
- else DESERIALIZE += indent + " srcStart += 2;\n";
537
+ if (type == "string") {
538
+ DESERIALIZE += indent + " srcStart += 4;\n";
539
+ } else if (type == "boolean" || type == "null" || type == "number") {
540
+ DESERIALIZE += indent + " srcStart += 2;\n";
541
+ }
542
+
476
543
  DESERIALIZE += indent + " keyStart = 0;\n";
477
- if (type != "boolean" && type != "null") DESERIALIZE += indent + " break;\n";
544
+ if (type == "string" || type == "object" || type == "array" || type == "number") DESERIALIZE += indent + " break;\n";
478
545
  }
479
546
  } else {
480
547
  const groups = groupMembers(members);
@@ -491,17 +558,21 @@ class JSONTransform extends Visitor {
491
558
  if (STRICT) {
492
559
  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';
493
560
  } else {
494
- if (type == "string") DESERIALIZE += indent + " srcStart += 4;\n";
495
- else DESERIALIZE += indent + " srcStart += 2;\n";
561
+ if (type == "string") {
562
+ DESERIALIZE += indent + " srcStart += 4;\n";
563
+ } else if (type == "boolean" || type == "null" || type == "number") {
564
+ DESERIALIZE += indent + " srcStart += 2;\n";
565
+ }
496
566
  DESERIALIZE += indent + " keyStart = 0;\n";
567
+ if (type == "string" || type == "object" || type == "array" || type == "number") DESERIALIZE += indent + " break;\n";
497
568
  }
498
569
  DESERIALIZE += " }\n";
499
570
  DESERIALIZE += " }\n";
500
- if (!members[0].node.type.isNullable && !isBoolean(members[0].type)) DESERIALIZE += " break;\n";
571
+ if (type != "null" && type != "boolean") DESERIALIZE += " break;\n";
501
572
  }
502
573
  };
503
574
 
504
- const generateComparisions = (members: Property[]) => {
575
+ const generateConsts = (members: Property[]): void => {
505
576
  if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
506
577
  DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
507
578
  }
@@ -517,42 +588,7 @@ class JSONTransform extends Visitor {
517
588
  if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
518
589
  DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
519
590
  }
520
-
521
- const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
522
- const firstMemberName = members[0].alias || members[0].name;
523
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
524
- DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart" + (isString(members[0].type) ? " + 2" : "") + "), offsetof<this>(" + JSON.stringify(members[0].name) + "));\n";
525
- if (isString(members[0].type)) DESERIALIZE += indent + " srcStart += 4;\n";
526
- else if (!complex) DESERIALIZE += indent + " srcStart += 2;\n";
527
- DESERIALIZE += indent + " keyStart = 0;\n";
528
- DESERIALIZE += indent + " break;\n";
529
- DESERIALIZE += indent + " }";
530
-
531
- for (let i = 1; i < members.length; i++) {
532
- const member = members[i];
533
- const memberName = member.alias || member.name;
534
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
535
- DESERIALIZE += indent + " store<" + member.type + ">(changetype<usize>(out), JSON.__deserialize<" + member.type + ">(lastIndex, srcStart" + (isString(member.type) ? " + 2" : "") + "), offsetof<this>(" + JSON.stringify(member.name) + "));\n";
536
- if (isString(member.type)) DESERIALIZE += indent + " srcStart += 4;\n";
537
- else if (!complex) DESERIALIZE += indent + " srcStart += 2;\n";
538
- DESERIALIZE += indent + " keyStart = 0;\n";
539
- DESERIALIZE += indent + " break;\n";
540
- DESERIALIZE += indent + " }";
541
- }
542
-
543
- if (STRICT) {
544
- DESERIALIZE += " else {\n";
545
- 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';
546
- DESERIALIZE += indent + " }\n";
547
- } else {
548
- DESERIALIZE += " else {\n";
549
- if (isString(members[0].type)) DESERIALIZE += indent + " srcStart += 4;\n";
550
- else if (!complex) DESERIALIZE += indent + " srcStart += 2;\n";
551
- DESERIALIZE += indent + " keyStart = 0;\n";
552
- DESERIALIZE += indent + " break;\n";
553
- DESERIALIZE += indent + " }\n";
554
- }
555
- };
591
+ }
556
592
 
557
593
  let mbElse = " ";
558
594
  if (!STRICT || sortedMembers.string.length) {
@@ -563,8 +599,41 @@ class JSONTransform extends Visitor {
563
599
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
564
600
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
565
601
  DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
566
- // DESERIALIZE += " console.log(JSON.Util.ptrToStr(keyStart,keyEnd) + \" = \" + load<u16>(keyStart).toString() + \" val \" + JSON.Util.ptrToStr(lastIndex, srcStart));\n";
567
- generateGroups(sortedMembers.string, generateComparisions, "string");
602
+ if (DEBUG > 1)DESERIALIZE += " console.log(\"Value (string, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart + 2));";
603
+ generateGroups(sortedMembers.string, (group) => {
604
+ generateConsts(group);
605
+ const first = group[0];
606
+ const fName = first.alias || first.name;
607
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
608
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
609
+ DESERIALIZE += indent + " srcStart += 4;\n";
610
+ DESERIALIZE += indent + " keyStart = 0;\n";
611
+ DESERIALIZE += indent + " break;\n";
612
+ DESERIALIZE += indent + " }";
613
+
614
+ for (let i = 1; i <group.length; i++) {
615
+ const mem = group[i];
616
+ const memName = mem.alias || mem.name;
617
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
618
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
619
+ DESERIALIZE += indent + " srcStart += 4;\n";
620
+ DESERIALIZE += indent + " keyStart = 0;\n";
621
+ DESERIALIZE += indent + " break;\n";
622
+ DESERIALIZE += indent + " }";
623
+ }
624
+
625
+ if (STRICT) {
626
+ DESERIALIZE += " else {\n";
627
+ 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';
628
+ DESERIALIZE += indent + " }\n";
629
+ } else {
630
+ DESERIALIZE += " else {\n";
631
+ DESERIALIZE += indent + " srcStart += 4;\n";
632
+ DESERIALIZE += indent + " keyStart = 0;\n";
633
+ DESERIALIZE += indent + " break;\n";
634
+ DESERIALIZE += indent + " }\n";
635
+ }
636
+ }, "string");
568
637
  DESERIALIZE += " }\n"; // Close break char check
569
638
  DESERIALIZE += " srcStart += 2;\n";
570
639
  DESERIALIZE += " }\n"; // Close char scan loop
@@ -579,9 +648,43 @@ class JSONTransform extends Visitor {
579
648
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
580
649
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
581
650
  DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
651
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (number, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
582
652
  // DESERIALIZE += " console.log(JSON.Util.ptrToStr(keyStart,keyEnd) + \" = \" + load<u16>(keyStart).toString() + \" val \" + JSON.Util.ptrToStr(lastIndex, srcStart));\n";
583
653
 
584
- generateGroups(sortedMembers.number, generateComparisions, "number");
654
+ generateGroups(sortedMembers.number, (group) => {
655
+ generateConsts(group);
656
+ const first = group[0];
657
+ const fName = first.alias || first.name;
658
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
659
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
660
+ DESERIALIZE += indent + " srcStart += 2;\n";
661
+ DESERIALIZE += indent + " keyStart = 0;\n";
662
+ DESERIALIZE += indent + " break;\n";
663
+ DESERIALIZE += indent + " }";
664
+
665
+ for (let i = 1; i < group.length; i++) {
666
+ const mem = group[i];
667
+ const memName = mem.alias || mem.name;
668
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
669
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
670
+ DESERIALIZE += indent + " srcStart += 2;\n";
671
+ DESERIALIZE += indent + " keyStart = 0;\n";
672
+ DESERIALIZE += indent + " break;\n";
673
+ DESERIALIZE += indent + " }";
674
+ }
675
+
676
+ if (STRICT) {
677
+ DESERIALIZE += " else {\n";
678
+ 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';
679
+ DESERIALIZE += indent + " }\n";
680
+ } else {
681
+ DESERIALIZE += " else {\n";
682
+ DESERIALIZE += indent + " srcStart += 2;\n";
683
+ DESERIALIZE += indent + " keyStart = 0;\n";
684
+ DESERIALIZE += indent + " break;\n";
685
+ DESERIALIZE += indent + " }\n";
686
+ }
687
+ }, "number");
585
688
  DESERIALIZE += " }\n"; // Close break char check
586
689
  DESERIALIZE += " srcStart += 2;\n";
587
690
  DESERIALIZE += " }\n"; // Close char scan loop
@@ -602,9 +705,40 @@ class JSONTransform extends Visitor {
602
705
  DESERIALIZE += " } else if (code == 125) {\n";
603
706
  DESERIALIZE += " if (--depth == 0) {\n";
604
707
  DESERIALIZE += " srcStart += 2;\n";
708
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (object, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
605
709
 
606
710
  indent = " ";
607
- generateGroups(sortedMembers.object, generateComparisions, "object");
711
+ generateGroups(sortedMembers.object, (group) => {
712
+ generateConsts(group);
713
+ const first = group[0];
714
+ const fName = first.alias || first.name;
715
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
716
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
717
+ DESERIALIZE += indent + " keyStart = 0;\n";
718
+ DESERIALIZE += indent + " break;\n";
719
+ DESERIALIZE += indent + " }";
720
+
721
+ for (let i = 1; i < group.length; i++) {
722
+ const mem = group[i];
723
+ const memName = mem.alias || mem.name;
724
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
725
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
726
+ DESERIALIZE += indent + " keyStart = 0;\n";
727
+ DESERIALIZE += indent + " break;\n";
728
+ DESERIALIZE += indent + " }";
729
+ }
730
+
731
+ if (STRICT) {
732
+ DESERIALIZE += " else {\n";
733
+ 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';
734
+ DESERIALIZE += indent + " }\n";
735
+ } else {
736
+ DESERIALIZE += " else {\n";
737
+ DESERIALIZE += indent + " keyStart = 0;\n";
738
+ DESERIALIZE += indent + " break;\n";
739
+ DESERIALIZE += indent + " }\n";
740
+ }
741
+ }, "object");
608
742
  indent = "";
609
743
 
610
744
  DESERIALIZE += " }\n"; // Close break char check
@@ -627,10 +761,40 @@ class JSONTransform extends Visitor {
627
761
  DESERIALIZE += " } else if (code == 93) {\n";
628
762
  DESERIALIZE += " if (--depth == 0) {\n";
629
763
  DESERIALIZE += " srcStart += 2;\n";
630
- // DESERIALIZE += " console.log(ptrToStr(keyStart,keyEnd) + \" = \" + (load<u64>(keyStart) & 0x0000FFFFFFFFFFFF) .toString());\n";
764
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (object, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
631
765
 
632
766
  indent = " ";
633
- generateGroups(sortedMembers.array, generateComparisions, "array");
767
+ generateGroups(sortedMembers.array, (group) => {
768
+ generateConsts(group);
769
+ const first = group[0];
770
+ const fName = first.alias || first.name;
771
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
772
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
773
+ DESERIALIZE += indent + " keyStart = 0;\n";
774
+ DESERIALIZE += indent + " break;\n";
775
+ DESERIALIZE += indent + " }";
776
+
777
+ for (let i = 1; i < group.length; i++) {
778
+ const mem = group[i];
779
+ const memName = mem.alias || mem.name;
780
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
781
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
782
+ DESERIALIZE += indent + " keyStart = 0;\n";
783
+ DESERIALIZE += indent + " break;\n";
784
+ DESERIALIZE += indent + " }";
785
+ }
786
+
787
+ if (STRICT) {
788
+ DESERIALIZE += " else {\n";
789
+ 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';
790
+ DESERIALIZE += indent + " }\n";
791
+ } else {
792
+ DESERIALIZE += " else {\n";
793
+ DESERIALIZE += indent + " keyStart = 0;\n";
794
+ DESERIALIZE += indent + " break;\n";
795
+ DESERIALIZE += indent + " }\n";
796
+ }
797
+ }, "array");
634
798
  indent = "";
635
799
 
636
800
  DESERIALIZE += " }\n"; // Close break char check
@@ -647,38 +811,23 @@ class JSONTransform extends Visitor {
647
811
 
648
812
  DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
649
813
  DESERIALIZE += " srcStart += 8;\n";
650
- generateGroups(
651
- sortedMembers.boolean,
652
- (group) => {
653
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
654
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
655
- }
656
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
657
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
658
- }
659
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
660
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
661
- }
662
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
663
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
664
- }
665
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
666
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
667
- }
668
-
669
- const firstMemberName = group[0].alias || group[0].name;
670
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
671
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
814
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
815
+ generateGroups(sortedMembers.boolean, (group) => {
816
+ generateConsts(group);
817
+ 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";
672
821
  DESERIALIZE += indent + " srcStart += 2;\n";
673
822
  DESERIALIZE += indent + " keyStart = 0;\n";
674
823
  DESERIALIZE += indent + " break;\n";
675
824
  DESERIALIZE += indent + " }";
676
825
 
677
826
  for (let i = 1; i < group.length; i++) {
678
- const member = group[i];
679
- const memberName = member.alias || member.name;
680
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
681
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
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";
682
831
  DESERIALIZE += indent + " srcStart += 2;\n";
683
832
  DESERIALIZE += indent + " keyStart = 0;\n";
684
833
  DESERIALIZE += indent + " break;\n";
@@ -713,38 +862,24 @@ class JSONTransform extends Visitor {
713
862
 
714
863
  DESERIALIZE += " if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
715
864
  DESERIALIZE += " srcStart += 10;\n";
716
- generateGroups(
717
- sortedMembers.boolean,
718
- (group) => {
719
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
720
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
721
- }
722
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
723
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
724
- }
725
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
726
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
727
- }
728
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
729
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
730
- }
731
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
732
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
733
- }
734
-
735
- const firstMemberName = group[0].alias || group[0].name;
736
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
737
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
865
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 10));";
866
+ generateGroups( sortedMembers.boolean, (group) => {
867
+ generateConsts(group);
868
+
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";
738
873
  DESERIALIZE += indent + " srcStart += 2;\n";
739
874
  DESERIALIZE += indent + " keyStart = 0;\n";
740
875
  DESERIALIZE += indent + " break;\n";
741
876
  DESERIALIZE += indent + " }";
742
877
 
743
878
  for (let i = 1; i < group.length; i++) {
744
- const member = group[i];
745
- const memberName = member.alias || member.name;
746
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
747
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
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";
748
883
  DESERIALIZE += indent + " srcStart += 2;\n";
749
884
  DESERIALIZE += indent + " keyStart = 0;\n";
750
885
  DESERIALIZE += indent + " break;\n";
@@ -780,38 +915,24 @@ class JSONTransform extends Visitor {
780
915
 
781
916
  DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
782
917
  DESERIALIZE += " srcStart += 8;\n";
783
- generateGroups(
784
- sortedMembers.null,
785
- (group) => {
786
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
787
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
788
- }
789
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
790
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
791
- }
792
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
793
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
794
- }
795
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
796
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
797
- }
798
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
799
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
800
- }
801
-
802
- const firstMemberName = group[0].alias || group[0].name;
803
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
804
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
918
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (null, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
919
+ generateGroups(sortedMembers.null, (group) => {
920
+ generateConsts(group);
921
+
922
+ 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";
805
926
  DESERIALIZE += indent + " srcStart += 2;\n";
806
927
  DESERIALIZE += indent + " keyStart = 0;\n";
807
928
  DESERIALIZE += indent + " break;\n";
808
929
  DESERIALIZE += indent + " }";
809
930
 
810
931
  for (let i = 1; i < group.length; i++) {
811
- const member = group[i];
812
- const memberName = member.alias || member.name;
813
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
814
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
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";
815
936
  DESERIALIZE += indent + " srcStart += 2;\n";
816
937
  DESERIALIZE += indent + " keyStart = 0;\n";
817
938
  DESERIALIZE += indent + " break;\n";
@@ -865,7 +986,7 @@ class JSONTransform extends Visitor {
865
986
  // if (DESERIALIZE_CUSTOM) {
866
987
  // DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): usize {\n if (isDefined(this.__DESERIALIZE_CUSTOM) return changetype<usize>(this." + deserializers[0].name + "(changetype<switch (<u32>keyEnd - <u32>keyStart) {\n"
867
988
  // }
868
- if (DEBUG) {
989
+ if (DEBUG > 0) {
869
990
  console.log(SERIALIZE_CUSTOM || SERIALIZE);
870
991
  console.log(INITIALIZE);
871
992
  console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
@@ -880,12 +1001,16 @@ class JSONTransform extends Visitor {
880
1001
  if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD);
881
1002
  super.visitClassDeclaration(node);
882
1003
  }
1004
+ getSchema(name: string): Schema | null {
1005
+ name = stripNull(name);
1006
+ return this.schemas.get(this.schema.node.range.source.internalPath).find((s) => s.name == name) || null;
1007
+ }
883
1008
  generateEmptyMethods(node: ClassDeclaration): void {
884
1009
  let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
885
1010
  let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
886
1011
  let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return this;\n}";
887
1012
 
888
- if (DEBUG) {
1013
+ if (DEBUG > 0) {
889
1014
  console.log(SERIALIZE_EMPTY);
890
1015
  console.log(INITIALIZE_EMPTY);
891
1016
  console.log(DESERIALIZE_EMPTY);
@@ -932,39 +1057,104 @@ class JSONTransform extends Visitor {
932
1057
  this.imports = [];
933
1058
  super.visitSource(node);
934
1059
  }
935
- addRequiredImports(node: Source): void {
936
- const filePath = fileURLToPath(import.meta.url);
937
- const baseDir = path.resolve(filePath, "..", "..", "..");
938
- const nodePath = path.resolve(this.baseDir, node.range.source.normalizedPath);
1060
+ addImports(node: Source): void {
1061
+ const baseDir = path.resolve(
1062
+ fileURLToPath(import.meta.url),
1063
+ "..",
1064
+ "..",
1065
+ "..",
1066
+ );
1067
+ const pkgPath = path.join(this.baseCWD, "node_modules");
1068
+ const isLibrary = existsSync(path.join(pkgPath, "json-as"));
1069
+ let fromPath = node.range.source.normalizedPath;
1070
+
1071
+ fromPath = fromPath.startsWith("~lib/")
1072
+ ? existsSync(
1073
+ path.join(pkgPath, fromPath.slice(5, fromPath.indexOf("/", 5))),
1074
+ )
1075
+ ? path.join(pkgPath, fromPath.slice(5))
1076
+ : fromPath
1077
+ : path.join(baseDir, fromPath);
939
1078
 
940
1079
  const bsImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "bs" || d.name.text == "bs"));
941
1080
  const jsonImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "JSON" || d.name.text == "JSON"));
942
1081
 
943
- let bsPath = path.posix.join(...path.relative(path.dirname(nodePath), path.join(baseDir, "lib", "as-bs")).split(path.sep)).replace(/^.*node_modules\/json-as/, "json-as");
1082
+ let bsRel = removeExtension(
1083
+ path.posix.join(
1084
+ ...path
1085
+ .relative(path.dirname(fromPath), path.join(baseDir, "lib", "as-bs"))
1086
+ .split(path.sep),
1087
+ ),
1088
+ );
1089
+
1090
+ let jsRel = removeExtension(
1091
+ path.posix.join(
1092
+ ...path
1093
+ .relative(path.dirname(fromPath), path.join(baseDir, "assembly", "index"))
1094
+ .split(path.sep),
1095
+ ),
1096
+ );
1097
+
1098
+ if (bsRel.includes("node_modules" + path.sep + "json-as")) {
1099
+ bsRel =
1100
+ "json-as" +
1101
+ bsRel.slice(
1102
+ bsRel.indexOf("node_modules" + path.sep + "json-as") + 20,
1103
+ )
1104
+ } else if (
1105
+ !bsRel.startsWith(".") &&
1106
+ !bsRel.startsWith("/") &&
1107
+ !bsRel.startsWith("json-as")
1108
+ ) {
1109
+ bsRel = "./" + bsRel;
1110
+ }
944
1111
 
945
- let jsonPath = path.posix.join(...path.relative(path.dirname(nodePath), path.join(baseDir, "assembly", "index.ts")).split(path.sep)).replace(/^.*node_modules\/json-as/, "json-as");
1112
+ if (jsRel.includes("node_modules" + path.sep + "json-as")) {
1113
+ jsRel =
1114
+ "json-as" +
1115
+ jsRel.slice(
1116
+ jsRel.indexOf("node_modules" + path.sep + "json-as") + 20,
1117
+ );
1118
+ } else if (
1119
+ !jsRel.startsWith(".") &&
1120
+ !jsRel.startsWith("/") &&
1121
+ !jsRel.startsWith("json-as")
1122
+ ) {
1123
+ jsRel = "./" + jsRel;
1124
+ }
946
1125
 
947
1126
  if (!bsImport) {
948
- if (node.normalizedPath.startsWith("~")) {
949
- bsPath = "json-as/lib/as-bs";
950
- }
951
-
952
- const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
953
- this.topStatements.push(replaceNode);
954
- if (DEBUG) console.log("Added as-bs import: " + toString(replaceNode) + "\n");
1127
+ const replaceNode = Node.createImportStatement(
1128
+ [Node.createImportDeclaration(
1129
+ Node.createIdentifierExpression("bs", node.range, false),
1130
+ null,
1131
+ node.range
1132
+ )
1133
+ ],
1134
+ Node.createStringLiteralExpression(bsRel, node.range),
1135
+ node.range
1136
+ );
1137
+ node.range.source.statements.unshift(replaceNode);
1138
+ if (DEBUG > 0) console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
955
1139
  }
956
1140
 
957
1141
  if (!jsonImport) {
958
- if (node.normalizedPath.startsWith("~")) {
959
- jsonPath = "json-as/assembly/index.ts";
960
- }
961
1142
  const replaceNode = Node.createImportStatement(
962
- [Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)],
963
- Node.createStringLiteralExpression(jsonPath, node.range), // Ensure POSIX-style path for 'assembly'
1143
+ [Node.createImportDeclaration(
1144
+ Node.createIdentifierExpression(
1145
+ "JSON",
1146
+ node.range,
1147
+ false
1148
+ ),
1149
+ null,
1150
+ node.range
1151
+ )
1152
+ ],
1153
+ Node.createStringLiteralExpression(jsRel, node.range), // Ensure POSIX-style path for 'assembly'
964
1154
  node.range,
965
1155
  );
966
- this.topStatements.push(replaceNode);
967
- if (DEBUG) console.log("Added json-as import: " + toString(replaceNode) + "\n");
1156
+ node.range.source.statements.unshift(replaceNode);
1157
+ if (DEBUG > 0) console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
968
1158
  }
969
1159
  }
970
1160
 
@@ -996,7 +1186,7 @@ class JSONTransform extends Visitor {
996
1186
  return out;
997
1187
  }
998
1188
  isValidType(type: string, node: ClassDeclaration): boolean {
999
- const validTypes = ["string", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean", "Date", "JSON.Value", "JSON.Obj", "JSON.Raw", "Value", "Obj", "Raw", ...this.schemas.map((v) => v.name)];
1189
+ const validTypes = ["string", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean", "Date", "JSON.Value", "JSON.Obj", "JSON.Raw", "Value", "Obj", "Raw", ...this.schemas.get(this.schema.node.range.source.internalPath).map((v) => v.name)];
1000
1190
 
1001
1191
  const baseTypes = ["Array", "Map", "Set", "JSON.Box", "Box"];
1002
1192
 
@@ -1039,7 +1229,7 @@ export default class Transformer extends Transform {
1039
1229
  }
1040
1230
  });
1041
1231
 
1042
- transformer.baseDir = path.join(process.cwd(), this.baseDir);
1232
+ transformer.baseCWD = path.join(process.cwd(), this.baseDir);
1043
1233
  transformer.program = this.program;
1044
1234
  transformer.parser = parser;
1045
1235
  for (const source of sources) {
@@ -1055,13 +1245,12 @@ export default class Transformer extends Transform {
1055
1245
  for (const simd of transformer.simdStatements) source.statements.unshift(SimpleParser.parseTopLevelStatement(simd));
1056
1246
  }
1057
1247
  transformer.simdStatements = [];
1058
- }
1059
1248
 
1060
- const schemas = transformer.schemas;
1061
- for (const schema of schemas) {
1062
- if (schema.parent) {
1063
- const parent = schemas.find((v) => v.name == schema.parent?.name);
1064
- if (!parent) throwError(`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator!`, schema.parent.node.range);
1249
+ if (transformer.schemas.has(source.internalPath)) {
1250
+ transformer.addImports(source);
1251
+ }
1252
+ if (source.normalizedPath == WRITE) {
1253
+ writeFileSync(path.join(process.cwd(), this.baseDir, removeExtension(source.normalizedPath) + ".json.ts"), toString(source));
1065
1254
  }
1066
1255
  }
1067
1256
  }
@@ -1217,9 +1406,9 @@ function isBoolean(type: string): boolean {
1217
1406
  return type == "bool" || type == "boolean";
1218
1407
  }
1219
1408
 
1220
- function isStruct(type: string): boolean {
1409
+ function isStruct(type: string, source: Source): boolean {
1221
1410
  type = stripNull(type);
1222
- return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
1411
+ return JSONTransform.SN.schemas.get(source.internalPath).some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
1223
1412
  }
1224
1413
 
1225
1414
  function isString(type: string) {