json-as 1.1.8 → 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,14 +1,24 @@
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
- const STRICT = !(process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "false");
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);
21
+ const STRICT = process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "true";
12
22
  class CustomTransform extends Visitor {
13
23
  static SN = new CustomTransform();
14
24
  modify = false;
@@ -41,14 +51,15 @@ 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();
52
63
  visitClassDeclaration(node) {
53
64
  if (!node.decorators?.length)
54
65
  return;
@@ -57,20 +68,127 @@ class JSONTransform extends Visitor {
57
68
  return name === "json" || name === "serializable";
58
69
  }))
59
70
  return;
60
- this.schema = new Schema();
61
- this.schema.node = node;
62
- this.schema.name = node.name.text;
63
- this.schemas.push(this.schema);
71
+ if (this.visitedClasses.has(node.range.source.internalPath + node.name.text))
72
+ return;
73
+ if (!this.schemas.has(node.range.source.internalPath))
74
+ this.schemas.set(node.range.source.internalPath, []);
75
+ 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"))];
76
+ const serializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "serializer"))];
77
+ const deserializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "deserializer"))];
78
+ const schema = new Schema();
79
+ schema.node = node;
80
+ schema.name = node.name.text;
81
+ if (node.extendsType) {
82
+ const extendsName = node.extendsType?.name.identifier.text;
83
+ if (!schema.parent) {
84
+ const depSearch = schema.deps.find((v) => v.name == extendsName);
85
+ if (depSearch) {
86
+ if (DEBUG > 0)
87
+ console.log("Found " + extendsName + " in dependencies of " + node.range.source.internalPath);
88
+ schema.deps.push(depSearch);
89
+ schema.parent = depSearch;
90
+ }
91
+ else {
92
+ const internalSearch = getClass(extendsName, node.range.source);
93
+ if (internalSearch) {
94
+ if (DEBUG > 0)
95
+ console.log("Found " + extendsName + " internally from " + node.range.source.internalPath);
96
+ this.visitClassDeclaration(internalSearch);
97
+ schema.deps.push(this.schema);
98
+ this.schemas.get(node.range.source.internalPath).push(this.schema);
99
+ schema.parent = this.schema;
100
+ this.schema = schema;
101
+ }
102
+ else {
103
+ const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
104
+ if (externalSearch) {
105
+ if (DEBUG > 0)
106
+ console.log("Found " + externalSearch.name.text + " externally from " + node.range.source.internalPath);
107
+ this.visitClassDeclaration(externalSearch);
108
+ schema.deps.push(this.schema);
109
+ this.schemas.get(node.range.source.internalPath).push(this.schema);
110
+ schema.parent = this.schema;
111
+ this.schema = schema;
112
+ }
113
+ }
114
+ }
115
+ }
116
+ if (schema.parent?.members) {
117
+ for (let i = schema.parent.members.length - 1; i >= 0; i--) {
118
+ const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
119
+ if (!replace) {
120
+ members.unshift(schema.parent?.members[i].node);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ const getUnknownTypes = (type, types = []) => {
126
+ type = stripNull(type);
127
+ if (type.startsWith("Array<")) {
128
+ return getUnknownTypes(type.slice(6, -1));
129
+ }
130
+ else if (type.startsWith("Map<")) {
131
+ const parts = type.slice(4, -1).split(",");
132
+ return getUnknownTypes(parts[0]) || getUnknownTypes(parts[1]);
133
+ }
134
+ else if (isString(type) || isPrimitive(type)) {
135
+ return types;
136
+ }
137
+ else if (["JSON.Box", "JSON.Obj", "JSON.Value", "JSON.Raw"].includes(type)) {
138
+ return types;
139
+ }
140
+ else if (node.isGeneric && node.typeParameters.some((p) => p.name.text == type)) {
141
+ return types;
142
+ }
143
+ else if (type == node.name.text) {
144
+ return types;
145
+ }
146
+ types.push(type);
147
+ return types;
148
+ };
149
+ for (const member of members) {
150
+ const type = toString(member.type);
151
+ const unknown = getUnknownTypes(type);
152
+ for (const unknownType of unknown) {
153
+ const depSearch = schema.deps.find((v) => v.name == unknownType);
154
+ if (depSearch) {
155
+ if (DEBUG > 0)
156
+ console.log("Found " + unknownType + " in dependencies of " + node.range.source.internalPath);
157
+ schema.deps.push(depSearch);
158
+ continue;
159
+ }
160
+ const internalSearch = getClass(unknownType, node.range.source);
161
+ if (internalSearch) {
162
+ if (DEBUG > 0)
163
+ console.log("Found " + unknownType + " internally from " + node.range.source.internalPath);
164
+ this.visitClassDeclaration(internalSearch);
165
+ this.schemas.get(node.range.source.internalPath).push(this.schema);
166
+ schema.deps.push(this.schema);
167
+ this.schema = schema;
168
+ }
169
+ else {
170
+ const externalSearch = getImportedClass(unknownType, node.range.source, this.parser);
171
+ if (externalSearch) {
172
+ if (DEBUG > 0)
173
+ console.log("Found " + externalSearch.name.text + " externally from " + node.range.source.internalPath);
174
+ this.visitClassDeclaration(externalSearch);
175
+ this.schemas.get(node.range.source.internalPath).push(this.schema);
176
+ schema.deps.push(this.schema);
177
+ this.schema = schema;
178
+ }
179
+ }
180
+ }
181
+ }
182
+ this.schemas.get(node.range.source.internalPath).push(schema);
183
+ this.schema = schema;
184
+ this.visitedClasses.add(node.range.source.internalPath + node.name.text);
64
185
  let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
65
186
  let INITIALIZE = "@inline __INITIALIZE(): this {\n";
66
187
  let DESERIALIZE = "__DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
67
188
  let DESERIALIZE_CUSTOM = "";
68
189
  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"))];
190
+ if (DEBUG > 0)
191
+ 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
192
  if (serializers.length > 1)
75
193
  throwError("Multiple serializers detected for class " + node.name.text + " but schemas can only have one serializer!", serializers[1].range);
76
194
  if (deserializers.length > 1)
@@ -116,41 +234,10 @@ class JSONTransform extends Visitor {
116
234
  DESERIALIZE_CUSTOM += " return inline.always(this." + deserializer.name.text + "(changetype<string>(srcStart)));\n";
117
235
  DESERIALIZE_CUSTOM += " }\n";
118
236
  }
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
237
  if (!members.length) {
150
238
  this.generateEmptyMethods(node);
151
239
  return;
152
240
  }
153
- this.addRequiredImports(node.range.source);
154
241
  for (const member of members) {
155
242
  if (!member.type)
156
243
  throwError("Fields must be strongly typed", node.range);
@@ -212,17 +299,6 @@ class JSONTransform extends Visitor {
212
299
  SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n";
213
300
  SERIALIZE += indent + "bs.offset += 2;\n";
214
301
  }
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
302
  let isPure = this.schema.static;
227
303
  let isRegular = isPure;
228
304
  let isFirst = true;
@@ -235,7 +311,7 @@ class JSONTransform extends Visitor {
235
311
  if (member.value) {
236
312
  INITIALIZE += ` this.${member.name} = ${member.value};\n`;
237
313
  }
238
- else if (this.schemas.find((v) => nonNullType == v.name)) {
314
+ else if (this.getSchema(nonNullType)) {
239
315
  INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`;
240
316
  }
241
317
  else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
@@ -338,7 +414,7 @@ class JSONTransform extends Visitor {
338
414
  DESERIALIZE += indent + " let keyStart: usize = 0;\n";
339
415
  DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
340
416
  DESERIALIZE += indent + " let isKey = false;\n";
341
- if (sortedMembers.object.length || sortedMembers.array.length)
417
+ if (!STRICT || sortedMembers.object.length || sortedMembers.array.length)
342
418
  DESERIALIZE += indent + " let depth: i32 = 0;\n";
343
419
  DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
344
420
  DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
@@ -355,6 +431,8 @@ class JSONTransform extends Visitor {
355
431
  DESERIALIZE += indent + " if (isKey) {\n";
356
432
  DESERIALIZE += indent + " keyStart = lastIndex;\n";
357
433
  DESERIALIZE += indent + " keyEnd = srcStart;\n";
434
+ if (DEBUG > 1)
435
+ DESERIALIZE += indent + " console.log(\"Key: \" + JSON.Util.ptrToStr(keyStart, keyEnd));\n";
358
436
  DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
359
437
  DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
360
438
  DESERIALIZE += indent + " isKey = false;\n";
@@ -376,27 +454,61 @@ class JSONTransform extends Visitor {
376
454
  groups.get(length).push(member);
377
455
  }
378
456
  return [...groups.values()]
379
- .map(group => group.sort((a, b) => {
457
+ .map((group) => group.sort((a, b) => {
380
458
  const aLen = (a.alias || a.name).length;
381
459
  const bLen = (b.alias || b.name).length;
382
460
  return aLen - bLen;
383
461
  }))
384
462
  .sort((a, b) => b.length - a.length);
385
463
  };
386
- const generateGroups = (members, cb, nil = false) => {
387
- const groups = groupMembers(members);
388
- DESERIALIZE += " switch (<u32>keyEnd - <u32>keyStart) {\n";
389
- for (const group of groups) {
390
- const groupLen = (group[0].alias || group[0].name).length << 1;
391
- DESERIALIZE += " case " + groupLen + ": {\n";
392
- cb(group);
393
- DESERIALIZE += "\n }\n";
394
- }
395
- DESERIALIZE += " }\n";
396
- if (!members[0].node.type.isNullable && !isBoolean(members[0].type))
397
- DESERIALIZE += " break;\n";
464
+ const generateGroups = (members, cb, type) => {
465
+ if (!members.length) {
466
+ if (STRICT) {
467
+ 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';
468
+ }
469
+ else {
470
+ if (type == "string") {
471
+ DESERIALIZE += indent + " srcStart += 4;\n";
472
+ }
473
+ else if (type == "boolean" || type == "null" || type == "number") {
474
+ DESERIALIZE += indent + " srcStart += 2;\n";
475
+ }
476
+ DESERIALIZE += indent + " keyStart = 0;\n";
477
+ if (type == "string" || type == "object" || type == "array" || type == "number")
478
+ DESERIALIZE += indent + " break;\n";
479
+ }
480
+ }
481
+ else {
482
+ const groups = groupMembers(members);
483
+ DESERIALIZE += " switch (<u32>keyEnd - <u32>keyStart) {\n";
484
+ for (const group of groups) {
485
+ const groupLen = (group[0].alias || group[0].name).length << 1;
486
+ DESERIALIZE += " case " + groupLen + ": {\n";
487
+ cb(group);
488
+ DESERIALIZE += "\n }\n";
489
+ }
490
+ DESERIALIZE += " default: {\n";
491
+ if (STRICT) {
492
+ 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
+ }
494
+ else {
495
+ if (type == "string") {
496
+ DESERIALIZE += indent + " srcStart += 4;\n";
497
+ }
498
+ else if (type == "boolean" || type == "null" || type == "number") {
499
+ DESERIALIZE += indent + " srcStart += 2;\n";
500
+ }
501
+ DESERIALIZE += indent + " keyStart = 0;\n";
502
+ if (type == "string" || type == "object" || type == "array" || type == "number")
503
+ DESERIALIZE += indent + " break;\n";
504
+ }
505
+ DESERIALIZE += " }\n";
506
+ DESERIALIZE += " }\n";
507
+ if (type != "null" && type != "boolean")
508
+ DESERIALIZE += " break;\n";
509
+ }
398
510
  };
399
- const generateComparisions = (members) => {
511
+ const generateConsts = (members) => {
400
512
  if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
401
513
  DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
402
514
  }
@@ -412,66 +524,105 @@ class JSONTransform extends Visitor {
412
524
  if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
413
525
  DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
414
526
  }
415
- const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
416
- const firstMemberName = members[0].alias || members[0].name;
417
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
418
- 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";
419
- if (isString(members[0].type))
420
- DESERIALIZE += indent + " srcStart += 4;\n";
421
- else if (!complex)
422
- DESERIALIZE += indent + " srcStart += 2;\n";
423
- DESERIALIZE += indent + " keyStart = 0;\n";
424
- DESERIALIZE += indent + " break;\n";
425
- DESERIALIZE += indent + " }";
426
- for (let i = 1; i < members.length; i++) {
427
- const member = members[i];
428
- const memberName = member.alias || member.name;
429
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
430
- 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";
431
- if (isString(member.type))
432
- DESERIALIZE += indent + " srcStart += 4;\n";
433
- else if (!complex)
434
- DESERIALIZE += indent + " srcStart += 2;\n";
435
- DESERIALIZE += indent + " keyStart = 0;\n";
436
- DESERIALIZE += indent + " break;\n";
437
- DESERIALIZE += indent + " }";
438
- }
439
- if (STRICT) {
440
- DESERIALIZE += " else {\n";
441
- DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
442
- DESERIALIZE += indent + " }\n";
443
- }
444
527
  };
445
528
  let mbElse = " ";
446
- if (sortedMembers.string.length) {
529
+ if (!STRICT || sortedMembers.string.length) {
447
530
  DESERIALIZE += mbElse + "if (code == 34) {\n";
448
531
  DESERIALIZE += " lastIndex = srcStart;\n";
449
532
  DESERIALIZE += " srcStart += 2;\n";
450
533
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
451
534
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
452
535
  DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
453
- generateGroups(sortedMembers.string, generateComparisions);
536
+ if (DEBUG > 1)
537
+ DESERIALIZE += " console.log(\"Value (string, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart + 2));";
538
+ generateGroups(sortedMembers.string, (group) => {
539
+ generateConsts(group);
540
+ const first = group[0];
541
+ const fName = first.alias || first.name;
542
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
543
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
544
+ DESERIALIZE += indent + " srcStart += 4;\n";
545
+ DESERIALIZE += indent + " keyStart = 0;\n";
546
+ DESERIALIZE += indent + " break;\n";
547
+ DESERIALIZE += indent + " }";
548
+ for (let i = 1; i < group.length; i++) {
549
+ const mem = group[i];
550
+ const memName = mem.alias || mem.name;
551
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
552
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
553
+ DESERIALIZE += indent + " srcStart += 4;\n";
554
+ DESERIALIZE += indent + " keyStart = 0;\n";
555
+ DESERIALIZE += indent + " break;\n";
556
+ DESERIALIZE += indent + " }";
557
+ }
558
+ if (STRICT) {
559
+ DESERIALIZE += " else {\n";
560
+ 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';
561
+ DESERIALIZE += indent + " }\n";
562
+ }
563
+ else {
564
+ DESERIALIZE += " else {\n";
565
+ DESERIALIZE += indent + " srcStart += 4;\n";
566
+ DESERIALIZE += indent + " keyStart = 0;\n";
567
+ DESERIALIZE += indent + " break;\n";
568
+ DESERIALIZE += indent + " }\n";
569
+ }
570
+ }, "string");
454
571
  DESERIALIZE += " }\n";
455
572
  DESERIALIZE += " srcStart += 2;\n";
456
573
  DESERIALIZE += " }\n";
457
574
  DESERIALIZE += " }\n";
458
575
  mbElse = " else ";
459
576
  }
460
- if (sortedMembers.number.length) {
577
+ if (!STRICT || sortedMembers.number.length) {
461
578
  DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
462
579
  DESERIALIZE += " lastIndex = srcStart;\n";
463
580
  DESERIALIZE += " srcStart += 2;\n";
464
581
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
465
582
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
466
583
  DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
467
- generateGroups(sortedMembers.number, generateComparisions);
584
+ if (DEBUG > 1)
585
+ DESERIALIZE += " console.log(\"Value (number, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
586
+ generateGroups(sortedMembers.number, (group) => {
587
+ generateConsts(group);
588
+ const first = group[0];
589
+ const fName = first.alias || first.name;
590
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
591
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
592
+ DESERIALIZE += indent + " srcStart += 2;\n";
593
+ DESERIALIZE += indent + " keyStart = 0;\n";
594
+ DESERIALIZE += indent + " break;\n";
595
+ DESERIALIZE += indent + " }";
596
+ for (let i = 1; i < group.length; i++) {
597
+ const mem = group[i];
598
+ const memName = mem.alias || mem.name;
599
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
600
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
601
+ DESERIALIZE += indent + " srcStart += 2;\n";
602
+ DESERIALIZE += indent + " keyStart = 0;\n";
603
+ DESERIALIZE += indent + " break;\n";
604
+ DESERIALIZE += indent + " }";
605
+ }
606
+ if (STRICT) {
607
+ DESERIALIZE += " else {\n";
608
+ 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';
609
+ DESERIALIZE += indent + " }\n";
610
+ }
611
+ else {
612
+ DESERIALIZE += " else {\n";
613
+ DESERIALIZE += indent + " srcStart += 2;\n";
614
+ DESERIALIZE += indent + " keyStart = 0;\n";
615
+ DESERIALIZE += indent + " break;\n";
616
+ DESERIALIZE += indent + " }\n";
617
+ }
618
+ }, "number");
468
619
  DESERIALIZE += " }\n";
469
620
  DESERIALIZE += " srcStart += 2;\n";
470
621
  DESERIALIZE += " }\n";
471
622
  DESERIALIZE += " }";
472
623
  mbElse = " else ";
473
624
  }
474
- if (sortedMembers.object.length) {
625
+ if (!STRICT || sortedMembers.object.length) {
475
626
  DESERIALIZE += mbElse + "if (code == 123) {\n";
476
627
  DESERIALIZE += " lastIndex = srcStart;\n";
477
628
  DESERIALIZE += " depth++;\n";
@@ -484,8 +635,39 @@ class JSONTransform extends Visitor {
484
635
  DESERIALIZE += " } else if (code == 125) {\n";
485
636
  DESERIALIZE += " if (--depth == 0) {\n";
486
637
  DESERIALIZE += " srcStart += 2;\n";
638
+ if (DEBUG > 1)
639
+ DESERIALIZE += " console.log(\"Value (object, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
487
640
  indent = " ";
488
- generateGroups(sortedMembers.object, generateComparisions);
641
+ generateGroups(sortedMembers.object, (group) => {
642
+ generateConsts(group);
643
+ const first = group[0];
644
+ const fName = first.alias || first.name;
645
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
646
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
647
+ DESERIALIZE += indent + " keyStart = 0;\n";
648
+ DESERIALIZE += indent + " break;\n";
649
+ DESERIALIZE += indent + " }";
650
+ for (let i = 1; i < group.length; i++) {
651
+ const mem = group[i];
652
+ const memName = mem.alias || mem.name;
653
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
654
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
655
+ DESERIALIZE += indent + " keyStart = 0;\n";
656
+ DESERIALIZE += indent + " break;\n";
657
+ DESERIALIZE += indent + " }";
658
+ }
659
+ if (STRICT) {
660
+ DESERIALIZE += " else {\n";
661
+ 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';
662
+ DESERIALIZE += indent + " }\n";
663
+ }
664
+ else {
665
+ DESERIALIZE += " else {\n";
666
+ DESERIALIZE += indent + " keyStart = 0;\n";
667
+ DESERIALIZE += indent + " break;\n";
668
+ DESERIALIZE += indent + " }\n";
669
+ }
670
+ }, "object");
489
671
  indent = "";
490
672
  DESERIALIZE += " }\n";
491
673
  DESERIALIZE += " } else if (code == 123) depth++;\n";
@@ -494,7 +676,7 @@ class JSONTransform extends Visitor {
494
676
  DESERIALIZE += " }";
495
677
  mbElse = " else ";
496
678
  }
497
- if (sortedMembers.array.length) {
679
+ if (!STRICT || sortedMembers.array.length) {
498
680
  DESERIALIZE += mbElse + "if (code == 91) {\n";
499
681
  DESERIALIZE += " lastIndex = srcStart;\n";
500
682
  DESERIALIZE += " depth++;\n";
@@ -507,8 +689,39 @@ class JSONTransform extends Visitor {
507
689
  DESERIALIZE += " } else if (code == 93) {\n";
508
690
  DESERIALIZE += " if (--depth == 0) {\n";
509
691
  DESERIALIZE += " srcStart += 2;\n";
692
+ if (DEBUG > 1)
693
+ DESERIALIZE += " console.log(\"Value (object, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
510
694
  indent = " ";
511
- generateGroups(sortedMembers.array, generateComparisions);
695
+ generateGroups(sortedMembers.array, (group) => {
696
+ generateConsts(group);
697
+ const first = group[0];
698
+ const fName = first.alias || first.name;
699
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
700
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
701
+ DESERIALIZE += indent + " keyStart = 0;\n";
702
+ DESERIALIZE += indent + " break;\n";
703
+ DESERIALIZE += indent + " }";
704
+ for (let i = 1; i < group.length; i++) {
705
+ const mem = group[i];
706
+ const memName = mem.alias || mem.name;
707
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
708
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
709
+ DESERIALIZE += indent + " keyStart = 0;\n";
710
+ DESERIALIZE += indent + " break;\n";
711
+ DESERIALIZE += indent + " }";
712
+ }
713
+ if (STRICT) {
714
+ DESERIALIZE += " else {\n";
715
+ 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';
716
+ DESERIALIZE += indent + " }\n";
717
+ }
718
+ else {
719
+ DESERIALIZE += " else {\n";
720
+ DESERIALIZE += indent + " keyStart = 0;\n";
721
+ DESERIALIZE += indent + " break;\n";
722
+ DESERIALIZE += indent + " }\n";
723
+ }
724
+ }, "array");
512
725
  indent = "";
513
726
  DESERIALIZE += " }\n";
514
727
  DESERIALIZE += " } else if (code == 91) depth++;\n";
@@ -517,38 +730,27 @@ class JSONTransform extends Visitor {
517
730
  DESERIALIZE += " }";
518
731
  mbElse = " else ";
519
732
  }
520
- if (sortedMembers.boolean.length) {
733
+ if (!STRICT || sortedMembers.boolean.length) {
521
734
  DESERIALIZE += mbElse + "if (code == 116) {\n";
522
735
  DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
523
736
  DESERIALIZE += " srcStart += 8;\n";
737
+ if (DEBUG > 1)
738
+ DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
524
739
  generateGroups(sortedMembers.boolean, (group) => {
525
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
526
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
527
- }
528
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
529
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
530
- }
531
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
532
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
533
- }
534
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
535
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
536
- }
537
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
538
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
539
- }
540
- const firstMemberName = group[0].alias || group[0].name;
541
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
542
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
543
- DESERIALIZE += indent + " srcStart += 2;\n";
544
- DESERIALIZE += indent + " keyStart = 0;\n";
545
- DESERIALIZE += indent + " break;\n";
546
- DESERIALIZE += indent + " }";
740
+ generateConsts(group);
741
+ const first = group[0];
742
+ const fName = first.alias || first.name;
743
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
744
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
745
+ DESERIALIZE += indent + " srcStart += 2;\n";
746
+ DESERIALIZE += indent + " keyStart = 0;\n";
747
+ DESERIALIZE += indent + " break;\n";
748
+ DESERIALIZE += indent + " }";
547
749
  for (let i = 1; i < group.length; i++) {
548
- const member = group[i];
549
- const memberName = member.alias || member.name;
550
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
551
- DESERIALIZE += indent + " store<" + member.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
750
+ const mem = group[i];
751
+ const memName = mem.alias || mem.name;
752
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
753
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
552
754
  DESERIALIZE += indent + " srcStart += 2;\n";
553
755
  DESERIALIZE += indent + " keyStart = 0;\n";
554
756
  DESERIALIZE += indent + " break;\n";
@@ -556,42 +758,43 @@ class JSONTransform extends Visitor {
556
758
  }
557
759
  if (STRICT) {
558
760
  DESERIALIZE += " else {\n";
559
- DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
761
+ 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';
560
762
  DESERIALIZE += indent + " }\n";
561
763
  }
562
- });
764
+ else {
765
+ DESERIALIZE += " else { \n";
766
+ DESERIALIZE += indent + " srcStart += 2;\n";
767
+ DESERIALIZE += indent + " keyStart = 0;\n";
768
+ DESERIALIZE += indent + " break;\n";
769
+ DESERIALIZE += indent + " }\n";
770
+ }
771
+ }, "boolean");
563
772
  DESERIALIZE += " }";
773
+ DESERIALIZE += " else {\n";
774
+ DESERIALIZE += " throw new Error(\"Expected to find 'true' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
775
+ DESERIALIZE += " }";
776
+ DESERIALIZE += "\n }";
564
777
  mbElse = " else ";
565
- DESERIALIZE += " else if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
778
+ DESERIALIZE += mbElse + "if (code == 102) {\n";
779
+ DESERIALIZE += " if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
566
780
  DESERIALIZE += " srcStart += 10;\n";
781
+ if (DEBUG > 1)
782
+ DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 10));";
567
783
  generateGroups(sortedMembers.boolean, (group) => {
568
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
569
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
570
- }
571
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
572
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
573
- }
574
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
575
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
576
- }
577
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
578
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
579
- }
580
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
581
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
582
- }
583
- const firstMemberName = group[0].alias || group[0].name;
584
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
585
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
784
+ generateConsts(group);
785
+ const first = group[0];
786
+ const fName = first.alias || first.name;
787
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
788
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
586
789
  DESERIALIZE += indent + " srcStart += 2;\n";
587
790
  DESERIALIZE += indent + " keyStart = 0;\n";
588
791
  DESERIALIZE += indent + " break;\n";
589
792
  DESERIALIZE += indent + " }";
590
793
  for (let i = 1; i < group.length; i++) {
591
- const member = group[i];
592
- const memberName = member.alias || member.name;
593
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
594
- DESERIALIZE += indent + " store<" + member.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
794
+ const mem = group[i];
795
+ const memName = mem.alias || mem.name;
796
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
797
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
595
798
  DESERIALIZE += indent + " srcStart += 2;\n";
596
799
  DESERIALIZE += indent + " keyStart = 0;\n";
597
800
  DESERIALIZE += indent + " break;\n";
@@ -599,45 +802,45 @@ class JSONTransform extends Visitor {
599
802
  }
600
803
  if (STRICT) {
601
804
  DESERIALIZE += " else {\n";
602
- DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
805
+ 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';
603
806
  DESERIALIZE += indent + " }\n";
604
807
  }
605
- });
606
- DESERIALIZE += " }\n";
607
- DESERIALIZE += " }";
808
+ else {
809
+ DESERIALIZE += " else { \n";
810
+ DESERIALIZE += indent + " srcStart += 2;\n";
811
+ DESERIALIZE += indent + " keyStart = 0;\n";
812
+ DESERIALIZE += indent + " break;\n";
813
+ DESERIALIZE += indent + " }\n";
814
+ }
815
+ }, "boolean");
816
+ DESERIALIZE += " }";
817
+ DESERIALIZE += " else {\n";
818
+ DESERIALIZE += " throw new Error(\"Expected to find 'false' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
819
+ DESERIALIZE += " }";
820
+ DESERIALIZE += "\n }";
821
+ mbElse = " else ";
608
822
  }
609
- if (sortedMembers.null.length) {
823
+ if (!STRICT || sortedMembers.null.length) {
610
824
  DESERIALIZE += mbElse + "if (code == 110) {\n";
611
825
  DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
612
826
  DESERIALIZE += " srcStart += 8;\n";
827
+ if (DEBUG > 1)
828
+ DESERIALIZE += " console.log(\"Value (null, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
613
829
  generateGroups(sortedMembers.null, (group) => {
614
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
615
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
616
- }
617
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
618
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
619
- }
620
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
621
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
622
- }
623
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
624
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
625
- }
626
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
627
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
628
- }
629
- const firstMemberName = group[0].alias || group[0].name;
630
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
631
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
830
+ generateConsts(group);
831
+ const first = group[0];
832
+ const fName = first.alias || first.name;
833
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
834
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
632
835
  DESERIALIZE += indent + " srcStart += 2;\n";
633
836
  DESERIALIZE += indent + " keyStart = 0;\n";
634
837
  DESERIALIZE += indent + " break;\n";
635
838
  DESERIALIZE += indent + " }";
636
839
  for (let i = 1; i < group.length; i++) {
637
- const member = group[i];
638
- const memberName = member.alias || member.name;
639
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
640
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
840
+ const mem = group[i];
841
+ const memName = mem.alias || mem.name;
842
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
843
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
641
844
  DESERIALIZE += indent + " srcStart += 2;\n";
642
845
  DESERIALIZE += indent + " keyStart = 0;\n";
643
846
  DESERIALIZE += indent + " break;\n";
@@ -645,16 +848,24 @@ class JSONTransform extends Visitor {
645
848
  }
646
849
  if (STRICT) {
647
850
  DESERIALIZE += " else {\n";
648
- DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
851
+ 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';
649
852
  DESERIALIZE += indent + " }\n";
650
853
  }
651
- }, true);
854
+ else {
855
+ DESERIALIZE += " else { \n";
856
+ DESERIALIZE += indent + " srcStart += 2;\n";
857
+ DESERIALIZE += indent + " keyStart = 0;\n";
858
+ DESERIALIZE += indent + " break;\n";
859
+ DESERIALIZE += indent + " }\n";
860
+ }
861
+ }, "null");
652
862
  DESERIALIZE += " }";
653
863
  DESERIALIZE += "\n }";
654
864
  mbElse = " else ";
655
865
  }
656
866
  DESERIALIZE += " else {\n";
657
867
  DESERIALIZE += " srcStart += 2;\n";
868
+ DESERIALIZE += " keyStart = 0;\n";
658
869
  DESERIALIZE += "}\n";
659
870
  DESERIALIZE += "\n }\n";
660
871
  indentDec();
@@ -669,7 +880,7 @@ class JSONTransform extends Visitor {
669
880
  SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
670
881
  INITIALIZE += " return this;\n";
671
882
  INITIALIZE += "}";
672
- if (DEBUG) {
883
+ if (DEBUG > 0) {
673
884
  console.log(SERIALIZE_CUSTOM || SERIALIZE);
674
885
  console.log(INITIALIZE);
675
886
  console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
@@ -685,11 +896,15 @@ class JSONTransform extends Visitor {
685
896
  node.members.push(DESERIALIZE_METHOD);
686
897
  super.visitClassDeclaration(node);
687
898
  }
899
+ getSchema(name) {
900
+ name = stripNull(name);
901
+ return this.schemas.get(this.schema.node.range.source.internalPath).find((s) => s.name == name) || null;
902
+ }
688
903
  generateEmptyMethods(node) {
689
904
  let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
690
905
  let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
691
906
  let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return this;\n}";
692
- if (DEBUG) {
907
+ if (DEBUG > 0) {
693
908
  console.log(SERIALIZE_EMPTY);
694
909
  console.log(INITIALIZE_EMPTY);
695
910
  console.log(DESERIALIZE_EMPTY);
@@ -712,31 +927,57 @@ class JSONTransform extends Visitor {
712
927
  this.imports = [];
713
928
  super.visitSource(node);
714
929
  }
715
- addRequiredImports(node) {
716
- const filePath = fileURLToPath(import.meta.url);
717
- const baseDir = path.resolve(filePath, "..", "..", "..");
718
- const nodePath = path.resolve(this.baseDir, node.range.source.normalizedPath);
930
+ addImports(node) {
931
+ const baseDir = path.resolve(fileURLToPath(import.meta.url), "..", "..", "..");
932
+ const pkgPath = path.join(this.baseCWD, "node_modules");
933
+ const isLibrary = existsSync(path.join(pkgPath, "json-as"));
934
+ let fromPath = node.range.source.normalizedPath;
935
+ fromPath = fromPath.startsWith("~lib/")
936
+ ? existsSync(path.join(pkgPath, fromPath.slice(5, fromPath.indexOf("/", 5))))
937
+ ? path.join(pkgPath, fromPath.slice(5))
938
+ : fromPath
939
+ : path.join(baseDir, fromPath);
719
940
  const bsImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "bs" || d.name.text == "bs"));
720
941
  const jsonImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "JSON" || d.name.text == "JSON"));
721
- 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");
722
- 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");
942
+ let bsRel = removeExtension(path.posix.join(...path
943
+ .relative(path.dirname(fromPath), path.join(baseDir, "lib", "as-bs"))
944
+ .split(path.sep)));
945
+ let jsRel = removeExtension(path.posix.join(...path
946
+ .relative(path.dirname(fromPath), path.join(baseDir, "assembly", "index"))
947
+ .split(path.sep)));
948
+ if (bsRel.includes("node_modules" + path.sep + "json-as")) {
949
+ bsRel =
950
+ "json-as" +
951
+ bsRel.slice(bsRel.indexOf("node_modules" + path.sep + "json-as") + 20);
952
+ }
953
+ else if (!bsRel.startsWith(".") &&
954
+ !bsRel.startsWith("/") &&
955
+ !bsRel.startsWith("json-as")) {
956
+ bsRel = "./" + bsRel;
957
+ }
958
+ if (jsRel.includes("node_modules" + path.sep + "json-as")) {
959
+ jsRel =
960
+ "json-as" +
961
+ jsRel.slice(jsRel.indexOf("node_modules" + path.sep + "json-as") + 20);
962
+ }
963
+ else if (!jsRel.startsWith(".") &&
964
+ !jsRel.startsWith("/") &&
965
+ !jsRel.startsWith("json-as")) {
966
+ jsRel = "./" + jsRel;
967
+ }
723
968
  if (!bsImport) {
724
- if (node.normalizedPath.startsWith("~")) {
725
- bsPath = "json-as/lib/as-bs";
726
- }
727
- const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
728
- this.topStatements.push(replaceNode);
729
- if (DEBUG)
730
- console.log("Added as-bs import: " + toString(replaceNode) + "\n");
969
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)
970
+ ], Node.createStringLiteralExpression(bsRel, node.range), node.range);
971
+ node.range.source.statements.unshift(replaceNode);
972
+ if (DEBUG > 0)
973
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
731
974
  }
732
975
  if (!jsonImport) {
733
- if (node.normalizedPath.startsWith("~")) {
734
- jsonPath = "json-as/assembly/index.ts";
735
- }
736
- const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(jsonPath, node.range), node.range);
737
- this.topStatements.push(replaceNode);
738
- if (DEBUG)
739
- console.log("Added json-as import: " + toString(replaceNode) + "\n");
976
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)
977
+ ], Node.createStringLiteralExpression(jsRel, node.range), node.range);
978
+ node.range.source.statements.unshift(replaceNode);
979
+ if (DEBUG > 0)
980
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
740
981
  }
741
982
  }
742
983
  getStores(data, simd = false) {
@@ -769,7 +1010,7 @@ class JSONTransform extends Visitor {
769
1010
  return out;
770
1011
  }
771
1012
  isValidType(type, node) {
772
- 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)];
1013
+ 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)];
773
1014
  const baseTypes = ["Array", "Map", "Set", "JSON.Box", "Box"];
774
1015
  if (node && node.isGeneric && node.typeParameters)
775
1016
  validTypes.push(...node.typeParameters.map((v) => v.name.text));
@@ -815,7 +1056,7 @@ export default class Transformer extends Transform {
815
1056
  return 0;
816
1057
  }
817
1058
  });
818
- transformer.baseDir = path.join(process.cwd(), this.baseDir);
1059
+ transformer.baseCWD = path.join(process.cwd(), this.baseDir);
819
1060
  transformer.program = this.program;
820
1061
  transformer.parser = parser;
821
1062
  for (const source of sources) {
@@ -831,13 +1072,11 @@ export default class Transformer extends Transform {
831
1072
  source.statements.unshift(SimpleParser.parseTopLevelStatement(simd));
832
1073
  }
833
1074
  transformer.simdStatements = [];
834
- }
835
- const schemas = transformer.schemas;
836
- for (const schema of schemas) {
837
- if (schema.parent) {
838
- const parent = schemas.find((v) => v.name == schema.parent?.name);
839
- if (!parent)
840
- 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);
1075
+ if (transformer.schemas.has(source.internalPath)) {
1076
+ transformer.addImports(source);
1077
+ }
1078
+ if (source.normalizedPath == WRITE) {
1079
+ writeFileSync(path.join(process.cwd(), this.baseDir, removeExtension(source.normalizedPath) + ".json.ts"), toString(source));
841
1080
  }
842
1081
  }
843
1082
  }
@@ -972,9 +1211,9 @@ function isPrimitive(type) {
972
1211
  function isBoolean(type) {
973
1212
  return type == "bool" || type == "boolean";
974
1213
  }
975
- function isStruct(type) {
1214
+ function isStruct(type, source) {
976
1215
  type = stripNull(type);
977
- return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
1216
+ return JSONTransform.SN.schemas.get(source.internalPath).some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
978
1217
  }
979
1218
  function isString(type) {
980
1219
  return stripNull(type) == "string" || stripNull(type) == "String";