json-as 1.1.9 → 1.1.11

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,13 +1,23 @@
1
1
  import { Node } from "assemblyscript/dist/assemblyscript.js";
2
2
  import { Transform } from "assemblyscript/dist/transform.js";
3
3
  import { Visitor } from "./visitor.js";
4
- import { isStdlib, 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
7
  import { Property, PropertyFlags, Schema } from "./types.js";
8
- import { getClasses, getImportedClass } from "./linker.js";
8
+ import { getClass, getImportedClass } from "./linker.js";
9
+ import { existsSync, writeFileSync } from "fs";
9
10
  let indent = " ";
10
- const DEBUG = process.env["JSON_DEBUG"];
11
+ let id = 0;
12
+ const WRITE = process.env["JSON_WRITE"];
13
+ const rawValue = process.env["JSON_DEBUG"];
14
+ const DEBUG = rawValue === "true"
15
+ ? 1
16
+ : rawValue === "false" || rawValue === ""
17
+ ? 0
18
+ : isNaN(Number(rawValue))
19
+ ? 0
20
+ : Number(rawValue);
11
21
  const STRICT = process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "true";
12
22
  class CustomTransform extends Visitor {
13
23
  static SN = new CustomTransform();
@@ -41,14 +51,24 @@ class CustomTransform extends Visitor {
41
51
  class JSONTransform extends Visitor {
42
52
  static SN = new JSONTransform();
43
53
  program;
44
- baseDir;
54
+ baseCWD;
45
55
  parser;
46
- schemas = [];
56
+ schemas = new Map();
47
57
  schema;
48
58
  sources = new Set();
49
59
  imports = [];
50
60
  topStatements = [];
51
61
  simdStatements = [];
62
+ visitedClasses = new Set();
63
+ visitClassDeclarationRef(node) {
64
+ if (!node.decorators?.length ||
65
+ !node.decorators.some((decorator) => {
66
+ const name = decorator.name.text;
67
+ return name === "json" || name === "serializable";
68
+ }))
69
+ throw new Error("Class " + node.name.text + " is missing an @json or @serializable decorator in " + node.range.source.internalPath);
70
+ this.visitClassDeclaration(node);
71
+ }
52
72
  visitClassDeclaration(node) {
53
73
  if (!node.decorators?.length)
54
74
  return;
@@ -57,20 +77,154 @@ class JSONTransform extends Visitor {
57
77
  return name === "json" || name === "serializable";
58
78
  }))
59
79
  return;
60
- this.schema = new Schema();
61
- this.schema.node = node;
62
- this.schema.name = node.name.text;
63
- this.schemas.push(this.schema);
80
+ if (this.visitedClasses.has(node.range.source.internalPath + node.name.text))
81
+ return;
82
+ if (!this.schemas.has(node.range.source.internalPath))
83
+ this.schemas.set(node.range.source.internalPath, []);
84
+ const members = [...node.members.filter((v) => v.kind === 54 && v.flags !== 32 && v.flags !== 512 && v.flags !== 1024 && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
85
+ const serializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "serializer"))];
86
+ const deserializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "deserializer"))];
87
+ const schema = new Schema();
88
+ schema.node = node;
89
+ schema.name = node.name.text;
90
+ if (node.extendsType) {
91
+ const extendsName = node.extendsType?.name.identifier.text;
92
+ if (!schema.parent) {
93
+ const depSearch = schema.deps.find((v) => v.name == extendsName);
94
+ if (depSearch) {
95
+ if (DEBUG > 0)
96
+ console.log("Found " + extendsName + " in dependencies of " + node.range.source.internalPath);
97
+ if (!schema.deps.some(v => v.name == depSearch.name))
98
+ schema.deps.push(depSearch);
99
+ schema.parent = depSearch;
100
+ }
101
+ else {
102
+ const internalSearch = getClass(extendsName, node.range.source);
103
+ if (internalSearch) {
104
+ if (DEBUG > 0)
105
+ console.log("Found " + extendsName + " internally from " + node.range.source.internalPath);
106
+ if (!this.visitedClasses.has(internalSearch.range.source.internalPath + internalSearch.name.text)) {
107
+ this.visitClassDeclarationRef(internalSearch);
108
+ this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
109
+ this.visitClassDeclaration(node);
110
+ return;
111
+ }
112
+ const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find(s => s.name == internalSearch.name.text);
113
+ if (!schem)
114
+ throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
115
+ schema.deps.push(schem);
116
+ schema.parent = schem;
117
+ }
118
+ else {
119
+ const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
120
+ if (externalSearch) {
121
+ if (DEBUG > 0)
122
+ console.log("Found " + externalSearch.name.text + " externally from " + node.range.source.internalPath);
123
+ if (!this.visitedClasses.has(externalSearch.range.source.internalPath + externalSearch.name.text)) {
124
+ this.visitClassDeclarationRef(externalSearch);
125
+ this.schemas.get(externalSearch.range.source.internalPath).push(this.schema);
126
+ this.visitClassDeclaration(node);
127
+ return;
128
+ }
129
+ const schem = this.schemas.get(externalSearch.range.source.internalPath)?.find(s => s.name == externalSearch.name.text);
130
+ if (!schem)
131
+ throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSearch.range.source.internalPath);
132
+ schema.deps.push(schem);
133
+ schema.parent = schem;
134
+ }
135
+ }
136
+ }
137
+ }
138
+ if (schema.parent?.members) {
139
+ for (let i = schema.parent.members.length - 1; i >= 0; i--) {
140
+ const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
141
+ if (!replace) {
142
+ members.unshift(schema.parent?.members[i].node);
143
+ }
144
+ }
145
+ }
146
+ }
147
+ const getUnknownTypes = (type, types = []) => {
148
+ type = stripNull(type);
149
+ if (type.startsWith("Array<")) {
150
+ return getUnknownTypes(type.slice(6, -1));
151
+ }
152
+ else if (type.startsWith("Map<")) {
153
+ const parts = type.slice(4, -1).split(",");
154
+ return getUnknownTypes(parts[0]) || getUnknownTypes(parts[1]);
155
+ }
156
+ else if (isString(type) || isPrimitive(type)) {
157
+ return types;
158
+ }
159
+ else if (["JSON.Box", "JSON.Obj", "JSON.Value", "JSON.Raw"].includes(type)) {
160
+ return types;
161
+ }
162
+ else if (node.isGeneric && node.typeParameters.some((p) => p.name.text == type)) {
163
+ return types;
164
+ }
165
+ else if (type == node.name.text) {
166
+ return types;
167
+ }
168
+ types.push(type);
169
+ return types;
170
+ };
171
+ for (const member of members) {
172
+ const type = toString(member.type);
173
+ const unknown = getUnknownTypes(type);
174
+ for (const unknownType of unknown) {
175
+ const depSearch = schema.deps.find((v) => v.name == unknownType);
176
+ if (depSearch) {
177
+ if (DEBUG > 0)
178
+ console.log("Found " + unknownType + " in dependencies of " + node.range.source.internalPath);
179
+ if (!schema.deps.some(v => v.name == depSearch.name))
180
+ schema.deps.push(depSearch);
181
+ }
182
+ else {
183
+ const internalSearch = getClass(unknownType, node.range.source);
184
+ if (internalSearch) {
185
+ if (DEBUG > 0)
186
+ console.log("Found " + unknownType + " internally from " + node.range.source.internalPath);
187
+ if (!this.visitedClasses.has(internalSearch.range.source.internalPath + internalSearch.name.text)) {
188
+ this.visitClassDeclarationRef(internalSearch);
189
+ this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
190
+ this.visitClassDeclaration(node);
191
+ return;
192
+ }
193
+ const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find(s => s.name == internalSearch.name.text);
194
+ if (!schem)
195
+ throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
196
+ schema.deps.push(schem);
197
+ }
198
+ else {
199
+ const externalSearch = getImportedClass(unknownType, node.range.source, this.parser);
200
+ if (externalSearch) {
201
+ if (DEBUG > 0)
202
+ console.log("Found " + externalSearch.name.text + " externally from " + node.range.source.internalPath);
203
+ if (!this.visitedClasses.has(externalSearch.range.source.internalPath + externalSearch.name.text)) {
204
+ this.visitClassDeclarationRef(externalSearch);
205
+ this.schemas.get(externalSearch.range.source.internalPath).push(this.schema);
206
+ this.visitClassDeclaration(node);
207
+ return;
208
+ }
209
+ const schem = this.schemas.get(externalSearch.range.source.internalPath)?.find(s => s.name == externalSearch.name.text);
210
+ if (!schem)
211
+ throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSearch.range.source.internalPath);
212
+ schema.deps.push(schem);
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+ this.schemas.get(node.range.source.internalPath).push(schema);
219
+ this.schema = schema;
220
+ this.visitedClasses.add(node.range.source.internalPath + node.name.text);
64
221
  let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
65
222
  let INITIALIZE = "@inline __INITIALIZE(): this {\n";
66
223
  let DESERIALIZE = "__DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
67
224
  let DESERIALIZE_CUSTOM = "";
68
225
  let SERIALIZE_CUSTOM = "";
69
- if (DEBUG)
70
- console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath);
71
- const members = [...node.members.filter((v) => v.kind === 54 && v.flags !== 32 && v.flags !== 512 && v.flags !== 1024 && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
72
- const serializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "serializer"))];
73
- const deserializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "deserializer"))];
226
+ if (DEBUG > 0)
227
+ 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 ") : ""));
74
228
  if (serializers.length > 1)
75
229
  throwError("Multiple serializers detected for class " + node.name.text + " but schemas can only have one serializer!", serializers[1].range);
76
230
  if (deserializers.length > 1)
@@ -116,41 +270,10 @@ class JSONTransform extends Visitor {
116
270
  DESERIALIZE_CUSTOM += " return inline.always(this." + deserializer.name.text + "(changetype<string>(srcStart)));\n";
117
271
  DESERIALIZE_CUSTOM += " }\n";
118
272
  }
119
- if (node.extendsType) {
120
- const extendsName = node.extendsType?.name.identifier.text;
121
- this.schema.parent = this.schemas.find((v) => v.name == extendsName);
122
- if (!this.schema.parent) {
123
- const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
124
- if (internalSearch) {
125
- if (DEBUG)
126
- console.log("Found " + extendsName + " internally");
127
- this.visitClassDeclaration(internalSearch);
128
- this.visitClassDeclaration(node);
129
- return;
130
- }
131
- const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
132
- if (externalSearch) {
133
- if (DEBUG)
134
- console.log("Found " + extendsName + " externally");
135
- this.visitClassDeclaration(externalSearch);
136
- this.visitClassDeclaration(node);
137
- return;
138
- }
139
- }
140
- if (this.schema.parent?.members) {
141
- for (let i = this.schema.parent.members.length - 1; i >= 0; i--) {
142
- const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name);
143
- if (!replace) {
144
- members.unshift(this.schema.parent?.members[i].node);
145
- }
146
- }
147
- }
148
- }
149
273
  if (!members.length) {
150
274
  this.generateEmptyMethods(node);
151
275
  return;
152
276
  }
153
- this.addRequiredImports(node.range.source);
154
277
  for (const member of members) {
155
278
  if (!member.type)
156
279
  throwError("Fields must be strongly typed", node.range);
@@ -212,17 +335,6 @@ class JSONTransform extends Visitor {
212
335
  SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n";
213
336
  SERIALIZE += indent + "bs.offset += 2;\n";
214
337
  }
215
- for (const member of this.schema.members) {
216
- if (isStruct(member.type)) {
217
- const schema = this.schemas.find((v) => v.name == stripNull(member.type));
218
- if (!schema)
219
- continue;
220
- if (!this.schema.deps.includes(schema)) {
221
- this.schema.deps.push(schema);
222
- this.schema.byteSize += schema.byteSize;
223
- }
224
- }
225
- }
226
338
  let isPure = this.schema.static;
227
339
  let isRegular = isPure;
228
340
  let isFirst = true;
@@ -235,7 +347,7 @@ class JSONTransform extends Visitor {
235
347
  if (member.value) {
236
348
  INITIALIZE += ` this.${member.name} = ${member.value};\n`;
237
349
  }
238
- else if (this.schemas.find((v) => nonNullType == v.name)) {
350
+ else if (this.getSchema(nonNullType)) {
239
351
  INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`;
240
352
  }
241
353
  else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
@@ -355,6 +467,8 @@ class JSONTransform extends Visitor {
355
467
  DESERIALIZE += indent + " if (isKey) {\n";
356
468
  DESERIALIZE += indent + " keyStart = lastIndex;\n";
357
469
  DESERIALIZE += indent + " keyEnd = srcStart;\n";
470
+ if (DEBUG > 1)
471
+ DESERIALIZE += indent + " console.log(\"Key: \" + JSON.Util.ptrToStr(keyStart, keyEnd));\n";
358
472
  DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
359
473
  DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
360
474
  DESERIALIZE += indent + " isKey = false;\n";
@@ -389,12 +503,14 @@ class JSONTransform extends Visitor {
389
503
  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';
390
504
  }
391
505
  else {
392
- if (type == "string")
506
+ if (type == "string") {
393
507
  DESERIALIZE += indent + " srcStart += 4;\n";
394
- else
508
+ }
509
+ else if (type == "boolean" || type == "null" || type == "number") {
395
510
  DESERIALIZE += indent + " srcStart += 2;\n";
511
+ }
396
512
  DESERIALIZE += indent + " keyStart = 0;\n";
397
- if (type != "boolean" && type != "null")
513
+ if (type == "string" || type == "object" || type == "array" || type == "number")
398
514
  DESERIALIZE += indent + " break;\n";
399
515
  }
400
516
  }
@@ -412,19 +528,23 @@ class JSONTransform extends Visitor {
412
528
  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';
413
529
  }
414
530
  else {
415
- if (type == "string")
531
+ if (type == "string") {
416
532
  DESERIALIZE += indent + " srcStart += 4;\n";
417
- else
533
+ }
534
+ else if (type == "boolean" || type == "null" || type == "number") {
418
535
  DESERIALIZE += indent + " srcStart += 2;\n";
536
+ }
419
537
  DESERIALIZE += indent + " keyStart = 0;\n";
538
+ if (type == "string" || type == "object" || type == "array" || type == "number")
539
+ DESERIALIZE += indent + " break;\n";
420
540
  }
421
541
  DESERIALIZE += " }\n";
422
542
  DESERIALIZE += " }\n";
423
- if (!members[0].node.type.isNullable && !isBoolean(members[0].type))
543
+ if (type != "null" && type != "boolean")
424
544
  DESERIALIZE += " break;\n";
425
545
  }
426
546
  };
427
- const generateComparisions = (members) => {
547
+ const generateConsts = (members) => {
428
548
  if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
429
549
  DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
430
550
  }
@@ -440,45 +560,6 @@ class JSONTransform extends Visitor {
440
560
  if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
441
561
  DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
442
562
  }
443
- const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
444
- const firstMemberName = members[0].alias || members[0].name;
445
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
446
- 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";
447
- if (isString(members[0].type))
448
- DESERIALIZE += indent + " srcStart += 4;\n";
449
- else if (!complex)
450
- DESERIALIZE += indent + " srcStart += 2;\n";
451
- DESERIALIZE += indent + " keyStart = 0;\n";
452
- DESERIALIZE += indent + " break;\n";
453
- DESERIALIZE += indent + " }";
454
- for (let i = 1; i < members.length; i++) {
455
- const member = members[i];
456
- const memberName = member.alias || member.name;
457
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
458
- 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";
459
- if (isString(member.type))
460
- DESERIALIZE += indent + " srcStart += 4;\n";
461
- else if (!complex)
462
- DESERIALIZE += indent + " srcStart += 2;\n";
463
- DESERIALIZE += indent + " keyStart = 0;\n";
464
- DESERIALIZE += indent + " break;\n";
465
- DESERIALIZE += indent + " }";
466
- }
467
- if (STRICT) {
468
- DESERIALIZE += " else {\n";
469
- 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';
470
- DESERIALIZE += indent + " }\n";
471
- }
472
- else {
473
- DESERIALIZE += " else {\n";
474
- if (isString(members[0].type))
475
- DESERIALIZE += indent + " srcStart += 4;\n";
476
- else if (!complex)
477
- DESERIALIZE += indent + " srcStart += 2;\n";
478
- DESERIALIZE += indent + " keyStart = 0;\n";
479
- DESERIALIZE += indent + " break;\n";
480
- DESERIALIZE += indent + " }\n";
481
- }
482
563
  };
483
564
  let mbElse = " ";
484
565
  if (!STRICT || sortedMembers.string.length) {
@@ -488,7 +569,41 @@ class JSONTransform extends Visitor {
488
569
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
489
570
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
490
571
  DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
491
- generateGroups(sortedMembers.string, generateComparisions, "string");
572
+ if (DEBUG > 1)
573
+ DESERIALIZE += " console.log(\"Value (string, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart + 2));";
574
+ generateGroups(sortedMembers.string, (group) => {
575
+ generateConsts(group);
576
+ const first = group[0];
577
+ const fName = first.alias || first.name;
578
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
579
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
580
+ DESERIALIZE += indent + " srcStart += 4;\n";
581
+ DESERIALIZE += indent + " keyStart = 0;\n";
582
+ DESERIALIZE += indent + " break;\n";
583
+ DESERIALIZE += indent + " }";
584
+ for (let i = 1; i < group.length; i++) {
585
+ const mem = group[i];
586
+ const memName = mem.alias || mem.name;
587
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
588
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
589
+ DESERIALIZE += indent + " srcStart += 4;\n";
590
+ DESERIALIZE += indent + " keyStart = 0;\n";
591
+ DESERIALIZE += indent + " break;\n";
592
+ DESERIALIZE += indent + " }";
593
+ }
594
+ if (STRICT) {
595
+ DESERIALIZE += " else {\n";
596
+ 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';
597
+ DESERIALIZE += indent + " }\n";
598
+ }
599
+ else {
600
+ DESERIALIZE += " else {\n";
601
+ DESERIALIZE += indent + " srcStart += 4;\n";
602
+ DESERIALIZE += indent + " keyStart = 0;\n";
603
+ DESERIALIZE += indent + " break;\n";
604
+ DESERIALIZE += indent + " }\n";
605
+ }
606
+ }, "string");
492
607
  DESERIALIZE += " }\n";
493
608
  DESERIALIZE += " srcStart += 2;\n";
494
609
  DESERIALIZE += " }\n";
@@ -502,7 +617,41 @@ class JSONTransform extends Visitor {
502
617
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
503
618
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
504
619
  DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
505
- generateGroups(sortedMembers.number, generateComparisions, "number");
620
+ if (DEBUG > 1)
621
+ DESERIALIZE += " console.log(\"Value (number, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
622
+ generateGroups(sortedMembers.number, (group) => {
623
+ generateConsts(group);
624
+ const first = group[0];
625
+ const fName = first.alias || first.name;
626
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
627
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
628
+ DESERIALIZE += indent + " srcStart += 2;\n";
629
+ DESERIALIZE += indent + " keyStart = 0;\n";
630
+ DESERIALIZE += indent + " break;\n";
631
+ DESERIALIZE += indent + " }";
632
+ for (let i = 1; i < group.length; i++) {
633
+ const mem = group[i];
634
+ const memName = mem.alias || mem.name;
635
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
636
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
637
+ DESERIALIZE += indent + " srcStart += 2;\n";
638
+ DESERIALIZE += indent + " keyStart = 0;\n";
639
+ DESERIALIZE += indent + " break;\n";
640
+ DESERIALIZE += indent + " }";
641
+ }
642
+ if (STRICT) {
643
+ DESERIALIZE += " else {\n";
644
+ 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';
645
+ DESERIALIZE += indent + " }\n";
646
+ }
647
+ else {
648
+ DESERIALIZE += " else {\n";
649
+ DESERIALIZE += indent + " srcStart += 2;\n";
650
+ DESERIALIZE += indent + " keyStart = 0;\n";
651
+ DESERIALIZE += indent + " break;\n";
652
+ DESERIALIZE += indent + " }\n";
653
+ }
654
+ }, "number");
506
655
  DESERIALIZE += " }\n";
507
656
  DESERIALIZE += " srcStart += 2;\n";
508
657
  DESERIALIZE += " }\n";
@@ -522,8 +671,39 @@ class JSONTransform extends Visitor {
522
671
  DESERIALIZE += " } else if (code == 125) {\n";
523
672
  DESERIALIZE += " if (--depth == 0) {\n";
524
673
  DESERIALIZE += " srcStart += 2;\n";
674
+ if (DEBUG > 1)
675
+ DESERIALIZE += " console.log(\"Value (object, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
525
676
  indent = " ";
526
- generateGroups(sortedMembers.object, generateComparisions, "object");
677
+ generateGroups(sortedMembers.object, (group) => {
678
+ generateConsts(group);
679
+ const first = group[0];
680
+ const fName = first.alias || first.name;
681
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
682
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
683
+ DESERIALIZE += indent + " keyStart = 0;\n";
684
+ DESERIALIZE += indent + " break;\n";
685
+ DESERIALIZE += indent + " }";
686
+ for (let i = 1; i < group.length; i++) {
687
+ const mem = group[i];
688
+ const memName = mem.alias || mem.name;
689
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
690
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
691
+ DESERIALIZE += indent + " keyStart = 0;\n";
692
+ DESERIALIZE += indent + " break;\n";
693
+ DESERIALIZE += indent + " }";
694
+ }
695
+ if (STRICT) {
696
+ DESERIALIZE += " else {\n";
697
+ 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';
698
+ DESERIALIZE += indent + " }\n";
699
+ }
700
+ else {
701
+ DESERIALIZE += " else {\n";
702
+ DESERIALIZE += indent + " keyStart = 0;\n";
703
+ DESERIALIZE += indent + " break;\n";
704
+ DESERIALIZE += indent + " }\n";
705
+ }
706
+ }, "object");
527
707
  indent = "";
528
708
  DESERIALIZE += " }\n";
529
709
  DESERIALIZE += " } else if (code == 123) depth++;\n";
@@ -545,8 +725,39 @@ class JSONTransform extends Visitor {
545
725
  DESERIALIZE += " } else if (code == 93) {\n";
546
726
  DESERIALIZE += " if (--depth == 0) {\n";
547
727
  DESERIALIZE += " srcStart += 2;\n";
728
+ if (DEBUG > 1)
729
+ DESERIALIZE += " console.log(\"Value (object, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
548
730
  indent = " ";
549
- generateGroups(sortedMembers.array, generateComparisions, "array");
731
+ generateGroups(sortedMembers.array, (group) => {
732
+ generateConsts(group);
733
+ const first = group[0];
734
+ const fName = first.alias || first.name;
735
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
736
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
737
+ DESERIALIZE += indent + " keyStart = 0;\n";
738
+ DESERIALIZE += indent + " break;\n";
739
+ DESERIALIZE += indent + " }";
740
+ for (let i = 1; i < group.length; i++) {
741
+ const mem = group[i];
742
+ const memName = mem.alias || mem.name;
743
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
744
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
745
+ DESERIALIZE += indent + " keyStart = 0;\n";
746
+ DESERIALIZE += indent + " break;\n";
747
+ DESERIALIZE += indent + " }";
748
+ }
749
+ if (STRICT) {
750
+ DESERIALIZE += " else {\n";
751
+ 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';
752
+ DESERIALIZE += indent + " }\n";
753
+ }
754
+ else {
755
+ DESERIALIZE += " else {\n";
756
+ DESERIALIZE += indent + " keyStart = 0;\n";
757
+ DESERIALIZE += indent + " break;\n";
758
+ DESERIALIZE += indent + " }\n";
759
+ }
760
+ }, "array");
550
761
  indent = "";
551
762
  DESERIALIZE += " }\n";
552
763
  DESERIALIZE += " } else if (code == 91) depth++;\n";
@@ -559,34 +770,23 @@ class JSONTransform extends Visitor {
559
770
  DESERIALIZE += mbElse + "if (code == 116) {\n";
560
771
  DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
561
772
  DESERIALIZE += " srcStart += 8;\n";
773
+ if (DEBUG > 1)
774
+ DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
562
775
  generateGroups(sortedMembers.boolean, (group) => {
563
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
564
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
565
- }
566
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
567
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
568
- }
569
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
570
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
571
- }
572
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
573
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
574
- }
575
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
576
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
577
- }
578
- const firstMemberName = group[0].alias || group[0].name;
579
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
580
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
776
+ generateConsts(group);
777
+ const first = group[0];
778
+ const fName = first.alias || first.name;
779
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
780
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
581
781
  DESERIALIZE += indent + " srcStart += 2;\n";
582
782
  DESERIALIZE += indent + " keyStart = 0;\n";
583
783
  DESERIALIZE += indent + " break;\n";
584
784
  DESERIALIZE += indent + " }";
585
785
  for (let i = 1; i < group.length; i++) {
586
- const member = group[i];
587
- const memberName = member.alias || member.name;
588
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
589
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
786
+ const mem = group[i];
787
+ const memName = mem.alias || mem.name;
788
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
789
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
590
790
  DESERIALIZE += indent + " srcStart += 2;\n";
591
791
  DESERIALIZE += indent + " keyStart = 0;\n";
592
792
  DESERIALIZE += indent + " break;\n";
@@ -614,34 +814,23 @@ class JSONTransform extends Visitor {
614
814
  DESERIALIZE += mbElse + "if (code == 102) {\n";
615
815
  DESERIALIZE += " if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
616
816
  DESERIALIZE += " srcStart += 10;\n";
817
+ if (DEBUG > 1)
818
+ DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 10));";
617
819
  generateGroups(sortedMembers.boolean, (group) => {
618
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
619
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
620
- }
621
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
622
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
623
- }
624
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
625
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
626
- }
627
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
628
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
629
- }
630
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
631
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
632
- }
633
- const firstMemberName = group[0].alias || group[0].name;
634
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
635
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
820
+ generateConsts(group);
821
+ const first = group[0];
822
+ const fName = first.alias || first.name;
823
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
824
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
636
825
  DESERIALIZE += indent + " srcStart += 2;\n";
637
826
  DESERIALIZE += indent + " keyStart = 0;\n";
638
827
  DESERIALIZE += indent + " break;\n";
639
828
  DESERIALIZE += indent + " }";
640
829
  for (let i = 1; i < group.length; i++) {
641
- const member = group[i];
642
- const memberName = member.alias || member.name;
643
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
644
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
830
+ const mem = group[i];
831
+ const memName = mem.alias || mem.name;
832
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
833
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
645
834
  DESERIALIZE += indent + " srcStart += 2;\n";
646
835
  DESERIALIZE += indent + " keyStart = 0;\n";
647
836
  DESERIALIZE += indent + " break;\n";
@@ -671,34 +860,23 @@ class JSONTransform extends Visitor {
671
860
  DESERIALIZE += mbElse + "if (code == 110) {\n";
672
861
  DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
673
862
  DESERIALIZE += " srcStart += 8;\n";
863
+ if (DEBUG > 1)
864
+ DESERIALIZE += " console.log(\"Value (null, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
674
865
  generateGroups(sortedMembers.null, (group) => {
675
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
676
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
677
- }
678
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
679
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
680
- }
681
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
682
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
683
- }
684
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
685
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
686
- }
687
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
688
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
689
- }
690
- const firstMemberName = group[0].alias || group[0].name;
691
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
692
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
866
+ generateConsts(group);
867
+ const first = group[0];
868
+ const fName = first.alias || first.name;
869
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
870
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
693
871
  DESERIALIZE += indent + " srcStart += 2;\n";
694
872
  DESERIALIZE += indent + " keyStart = 0;\n";
695
873
  DESERIALIZE += indent + " break;\n";
696
874
  DESERIALIZE += indent + " }";
697
875
  for (let i = 1; i < group.length; i++) {
698
- const member = group[i];
699
- const memberName = member.alias || member.name;
700
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
701
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
876
+ const mem = group[i];
877
+ const memName = mem.alias || mem.name;
878
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
879
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
702
880
  DESERIALIZE += indent + " srcStart += 2;\n";
703
881
  DESERIALIZE += indent + " keyStart = 0;\n";
704
882
  DESERIALIZE += indent + " break;\n";
@@ -738,7 +916,7 @@ class JSONTransform extends Visitor {
738
916
  SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
739
917
  INITIALIZE += " return this;\n";
740
918
  INITIALIZE += "}";
741
- if (DEBUG) {
919
+ if (DEBUG > 0) {
742
920
  console.log(SERIALIZE_CUSTOM || SERIALIZE);
743
921
  console.log(INITIALIZE);
744
922
  console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
@@ -754,11 +932,15 @@ class JSONTransform extends Visitor {
754
932
  node.members.push(DESERIALIZE_METHOD);
755
933
  super.visitClassDeclaration(node);
756
934
  }
935
+ getSchema(name) {
936
+ name = stripNull(name);
937
+ return this.schemas.get(this.schema.node.range.source.internalPath).find((s) => s.name == name) || null;
938
+ }
757
939
  generateEmptyMethods(node) {
758
940
  let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
759
941
  let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
760
942
  let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return this;\n}";
761
- if (DEBUG) {
943
+ if (DEBUG > 0) {
762
944
  console.log(SERIALIZE_EMPTY);
763
945
  console.log(INITIALIZE_EMPTY);
764
946
  console.log(DESERIALIZE_EMPTY);
@@ -781,31 +963,57 @@ class JSONTransform extends Visitor {
781
963
  this.imports = [];
782
964
  super.visitSource(node);
783
965
  }
784
- addRequiredImports(node) {
785
- const filePath = fileURLToPath(import.meta.url);
786
- const baseDir = path.resolve(filePath, "..", "..", "..");
787
- const nodePath = path.resolve(this.baseDir, node.range.source.normalizedPath);
966
+ addImports(node) {
967
+ const baseDir = path.resolve(fileURLToPath(import.meta.url), "..", "..", "..");
968
+ const pkgPath = path.join(this.baseCWD, "node_modules");
969
+ const isLibrary = existsSync(path.join(pkgPath, "json-as"));
970
+ let fromPath = node.range.source.normalizedPath;
971
+ fromPath = fromPath.startsWith("~lib/")
972
+ ? existsSync(path.join(pkgPath, fromPath.slice(5, fromPath.indexOf("/", 5))))
973
+ ? path.join(pkgPath, fromPath.slice(5))
974
+ : fromPath
975
+ : path.join(this.baseCWD, fromPath);
788
976
  const bsImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "bs" || d.name.text == "bs"));
789
977
  const jsonImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "JSON" || d.name.text == "JSON"));
790
- 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");
791
- 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");
978
+ let bsRel = removeExtension(path.posix.join(...path
979
+ .relative(path.dirname(fromPath), path.join(baseDir, "lib", "as-bs"))
980
+ .split(path.sep)));
981
+ let jsRel = removeExtension(path.posix.join(...path
982
+ .relative(path.dirname(fromPath), path.join(baseDir, "assembly", "index"))
983
+ .split(path.sep)));
984
+ if (bsRel.includes("node_modules" + path.sep + "json-as")) {
985
+ bsRel =
986
+ "json-as" +
987
+ bsRel.slice(bsRel.indexOf("node_modules" + path.sep + "json-as") + 20);
988
+ }
989
+ else if (!bsRel.startsWith(".") &&
990
+ !bsRel.startsWith("/") &&
991
+ !bsRel.startsWith("json-as")) {
992
+ bsRel = "./" + bsRel;
993
+ }
994
+ if (jsRel.includes("node_modules" + path.sep + "json-as")) {
995
+ jsRel =
996
+ "json-as" +
997
+ jsRel.slice(jsRel.indexOf("node_modules" + path.sep + "json-as") + 20);
998
+ }
999
+ else if (!jsRel.startsWith(".") &&
1000
+ !jsRel.startsWith("/") &&
1001
+ !jsRel.startsWith("json-as")) {
1002
+ jsRel = "./" + jsRel;
1003
+ }
792
1004
  if (!bsImport) {
793
- if (node.normalizedPath.startsWith("~")) {
794
- bsPath = "json-as/lib/as-bs";
795
- }
796
- const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
797
- this.topStatements.push(replaceNode);
798
- if (DEBUG)
799
- console.log("Added as-bs import: " + toString(replaceNode) + "\n");
1005
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)
1006
+ ], Node.createStringLiteralExpression(bsRel, node.range), node.range);
1007
+ node.range.source.statements.unshift(replaceNode);
1008
+ if (DEBUG > 0)
1009
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
800
1010
  }
801
1011
  if (!jsonImport) {
802
- if (node.normalizedPath.startsWith("~")) {
803
- jsonPath = "json-as/assembly/index.ts";
804
- }
805
- const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(jsonPath, node.range), node.range);
806
- this.topStatements.push(replaceNode);
807
- if (DEBUG)
808
- console.log("Added json-as import: " + toString(replaceNode) + "\n");
1012
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)
1013
+ ], Node.createStringLiteralExpression(jsRel, node.range), node.range);
1014
+ node.range.source.statements.unshift(replaceNode);
1015
+ if (DEBUG > 0)
1016
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
809
1017
  }
810
1018
  }
811
1019
  getStores(data, simd = false) {
@@ -838,7 +1046,7 @@ class JSONTransform extends Visitor {
838
1046
  return out;
839
1047
  }
840
1048
  isValidType(type, node) {
841
- 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)];
1049
+ 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)];
842
1050
  const baseTypes = ["Array", "Map", "Set", "JSON.Box", "Box"];
843
1051
  if (node && node.isGeneric && node.typeParameters)
844
1052
  validTypes.push(...node.typeParameters.map((v) => v.name.text));
@@ -884,7 +1092,7 @@ export default class Transformer extends Transform {
884
1092
  return 0;
885
1093
  }
886
1094
  });
887
- transformer.baseDir = path.join(process.cwd(), this.baseDir);
1095
+ transformer.baseCWD = path.join(process.cwd(), this.baseDir);
888
1096
  transformer.program = this.program;
889
1097
  transformer.parser = parser;
890
1098
  for (const source of sources) {
@@ -900,13 +1108,11 @@ export default class Transformer extends Transform {
900
1108
  source.statements.unshift(SimpleParser.parseTopLevelStatement(simd));
901
1109
  }
902
1110
  transformer.simdStatements = [];
903
- }
904
- const schemas = transformer.schemas;
905
- for (const schema of schemas) {
906
- if (schema.parent) {
907
- const parent = schemas.find((v) => v.name == schema.parent?.name);
908
- if (!parent)
909
- 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);
1111
+ if (transformer.schemas.has(source.internalPath)) {
1112
+ transformer.addImports(source);
1113
+ }
1114
+ if (source.normalizedPath == WRITE) {
1115
+ writeFileSync(path.join(process.cwd(), this.baseDir, removeExtension(source.normalizedPath) + ".json.ts"), toString(source));
910
1116
  }
911
1117
  }
912
1118
  }
@@ -1041,9 +1247,9 @@ function isPrimitive(type) {
1041
1247
  function isBoolean(type) {
1042
1248
  return type == "bool" || type == "boolean";
1043
1249
  }
1044
- function isStruct(type) {
1250
+ function isStruct(type, source) {
1045
1251
  type = stripNull(type);
1046
- return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
1252
+ return JSONTransform.SN.schemas.get(source.internalPath).some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
1047
1253
  }
1048
1254
  function isString(type) {
1049
1255
  return stripNull(type) == "string" || stripNull(type) == "String";