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,36 +1,44 @@
1
1
  import { ClassDeclaration, FieldDeclaration, IdentifierExpression, Parser, Source, NodeKind, CommonFlags, ImportStatement, Node, Tokenizer, SourceKind, NamedTypeNode, Range, FEATURE_SIMD, FunctionExpression, MethodDeclaration, Statement, Program, Feature, CallExpression, PropertyAccessExpression } from "assemblyscript/dist/assemblyscript.js";
2
2
  import { Transform } from "assemblyscript/dist/transform.js";
3
3
  import { Visitor } from "./visitor.js";
4
- import { cloneNode, isStdlib, replaceRef, SimpleParser, toString } from "./util.js";
4
+ import { cloneNode, isStdlib, removeExtension, replaceRef, SimpleParser, toString } from "./util.js";
5
5
  import * as path from "path";
6
6
  import { fileURLToPath } from "url";
7
7
  import { Property, PropertyFlags, Schema } from "./types.js";
8
- import { getClasses, getImportedClass } from "./linker.js";
8
+ import { getClass, getClasses, getImportedClass } from "./linker.js";
9
+ import { existsSync, writeFileSync } from "fs";
9
10
 
10
11
  let indent = " ";
11
12
 
12
- const DEBUG = process.env["JSON_DEBUG"];
13
- const STRICT = !(process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "false");
13
+ let id = 0;
14
+
15
+ const WRITE = process.env["JSON_WRITE"];
16
+ const rawValue = process.env["JSON_DEBUG"];
17
+
18
+ const DEBUG = rawValue === "true"
19
+ ? 1
20
+ : rawValue === "false" || rawValue === ""
21
+ ? 0
22
+ : isNaN(Number(rawValue))
23
+ ? 0
24
+ : Number(rawValue);
25
+
26
+ const STRICT = process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "true";
14
27
 
15
28
  class CustomTransform extends Visitor {
16
29
  static SN: CustomTransform = new CustomTransform();
17
30
 
18
31
  private modify: boolean = false;
19
32
  visitCallExpression(node: CallExpression) {
20
-
21
33
  super.visit(node.args, node);
22
34
  if (node.expression.kind != NodeKind.PropertyAccess || (node.expression as PropertyAccessExpression).property.text != "stringify") return;
23
35
  if ((node.expression as PropertyAccessExpression).expression.kind != NodeKind.Identifier || ((node.expression as PropertyAccessExpression).expression as IdentifierExpression).text != "JSON") return;
24
36
 
25
37
  if (this.modify) {
26
- (node.expression as PropertyAccessExpression).expression = Node.createPropertyAccessExpression(
27
- Node.createIdentifierExpression("JSON", node.expression.range),
28
- Node.createIdentifierExpression("internal", node.expression.range),
29
- node.expression.range
30
- );
38
+ (node.expression as PropertyAccessExpression).expression = Node.createPropertyAccessExpression(Node.createIdentifierExpression("JSON", node.expression.range), Node.createIdentifierExpression("internal", node.expression.range), node.expression.range);
31
39
  }
32
40
  this.modify = true;
33
-
41
+
34
42
  // console.log(toString(node));
35
43
  // console.log(SimpleParser.parseStatement("JSON.internal.stringify").expression.expression)
36
44
  }
@@ -52,9 +60,9 @@ class JSONTransform extends Visitor {
52
60
  static SN: JSONTransform = new JSONTransform();
53
61
 
54
62
  public program!: Program;
55
- public baseDir!: string;
63
+ public baseCWD!: string;
56
64
  public parser!: Parser;
57
- public schemas: Schema[] = [];
65
+ public schemas: Map<string, Schema[]> = new Map<string, Schema[]>();
58
66
  public schema!: Schema;
59
67
  public sources = new Set<Source>();
60
68
  public imports: ImportStatement[] = [];
@@ -62,6 +70,8 @@ class JSONTransform extends Visitor {
62
70
  public topStatements: Statement[] = [];
63
71
  public simdStatements: string[] = [];
64
72
 
73
+ private visitedClasses: Set<string> = new Set<string>();
74
+
65
75
  visitClassDeclaration(node: ClassDeclaration): void {
66
76
  if (!node.decorators?.length) return;
67
77
 
@@ -73,11 +83,111 @@ class JSONTransform extends Visitor {
73
83
  )
74
84
  return;
75
85
 
76
- this.schema = new Schema();
77
- this.schema.node = node;
78
- this.schema.name = node.name.text;
86
+ if (this.visitedClasses.has(node.range.source.internalPath + node.name.text)) return;
87
+ if (!this.schemas.has(node.range.source.internalPath)) this.schemas.set(node.range.source.internalPath, []);
88
+
89
+ const members: FieldDeclaration[] = [...(node.members.filter((v) => v.kind === NodeKind.FieldDeclaration && v.flags !== CommonFlags.Static && v.flags !== CommonFlags.Private && v.flags !== CommonFlags.Protected && !v.decorators?.some((decorator) => (<IdentifierExpression>decorator.name).text === "omit")) as FieldDeclaration[])];
90
+ const serializers: MethodDeclaration[] = [...node.members.filter((v) => v.kind === NodeKind.MethodDeclaration && v.decorators && v.decorators.some((e) => (<IdentifierExpression>e.name).text.toLowerCase() === "serializer"))] as MethodDeclaration[];
91
+ const deserializers: MethodDeclaration[] = [...node.members.filter((v) => v.kind === NodeKind.MethodDeclaration && v.decorators && v.decorators.some((e) => (<IdentifierExpression>e.name).text.toLowerCase() === "deserializer"))] as MethodDeclaration[];
92
+
93
+ const schema = new Schema();
94
+ schema.node = node;
95
+ schema.name = node.name.text;
96
+
97
+ if (node.extendsType) {
98
+ const extendsName = node.extendsType?.name.identifier.text;
99
+ if (!schema.parent) {
100
+ const depSearch = schema.deps.find((v) => v.name == extendsName);
101
+ if (depSearch) {
102
+ if (DEBUG > 0) console.log("Found " + extendsName + " in dependencies of " + node.range.source.internalPath);
103
+ schema.deps.push(depSearch);
104
+ schema.parent = depSearch
105
+ } else {
106
+ const internalSearch = getClass(extendsName, node.range.source);
107
+ if (internalSearch) {
108
+ if (DEBUG > 0) console.log("Found " + extendsName + " internally from " + node.range.source.internalPath);
109
+ this.visitClassDeclaration(internalSearch);
110
+ schema.deps.push(this.schema);
111
+ this.schemas.get(node.range.source.internalPath).push(this.schema);
112
+ schema.parent = this.schema;
113
+ this.schema = schema;
114
+ } else {
115
+ const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
116
+ if (externalSearch) {
117
+ if (DEBUG > 0) console.log("Found " + externalSearch.name.text + " externally from " + node.range.source.internalPath);
118
+ this.visitClassDeclaration(externalSearch);
119
+ schema.deps.push(this.schema);
120
+ this.schemas.get(node.range.source.internalPath).push(this.schema);
121
+ schema.parent = this.schema;
122
+ this.schema = schema;
123
+ }
124
+ }
125
+ }
126
+ }
127
+ if (schema.parent?.members) {
128
+ for (let i = schema.parent.members.length - 1; i >= 0; i--) {
129
+ const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
130
+ if (!replace) {
131
+ members.unshift(schema.parent?.members[i]!.node);
132
+ }
133
+ }
134
+ }
135
+ }
79
136
 
80
- this.schemas.push(this.schema);
137
+ const getUnknownTypes = (type: string, types: string[] = []): string[] => {
138
+ type = stripNull(type);
139
+ if (type.startsWith("Array<")) {
140
+ return getUnknownTypes(type.slice(6, -1));
141
+ } else if (type.startsWith("Map<")) {
142
+ const parts = type.slice(4, -1).split(",");
143
+ return getUnknownTypes(parts[0]) || getUnknownTypes(parts[1]);
144
+ } else if (isString(type) || isPrimitive(type)) {
145
+ return types;
146
+ } else if (["JSON.Box", "JSON.Obj", "JSON.Value", "JSON.Raw"].includes(type)) {
147
+ return types;
148
+ } else if (node.isGeneric && node.typeParameters.some((p) => p.name.text == type)) {
149
+ return types;
150
+ } else if (type == node.name.text) {
151
+ return types;
152
+ }
153
+ types.push(type);
154
+ return types;
155
+ }
156
+
157
+ for (const member of members) {
158
+ const type = toString(member.type);
159
+ const unknown = getUnknownTypes(type);
160
+
161
+ for (const unknownType of unknown) {
162
+ const depSearch = schema.deps.find((v) => v.name == unknownType);
163
+ if (depSearch) {
164
+ if (DEBUG > 0) console.log("Found " + unknownType + " in dependencies of " + node.range.source.internalPath);
165
+ schema.deps.push(depSearch);
166
+ continue;
167
+ }
168
+ const internalSearch = getClass(unknownType, node.range.source);
169
+ if (internalSearch) {
170
+ if (DEBUG > 0) console.log("Found " + unknownType + " internally from " + node.range.source.internalPath);
171
+ this.visitClassDeclaration(internalSearch);
172
+ this.schemas.get(node.range.source.internalPath).push(this.schema);
173
+ schema.deps.push(this.schema);
174
+ this.schema = schema;
175
+ } else {
176
+ const externalSearch = getImportedClass(unknownType, node.range.source, this.parser);
177
+ if (externalSearch) {
178
+ if (DEBUG > 0) console.log("Found " + externalSearch.name.text + " externally from " + node.range.source.internalPath);
179
+ this.visitClassDeclaration(externalSearch);
180
+ this.schemas.get(node.range.source.internalPath).push(this.schema);
181
+ schema.deps.push(this.schema);
182
+ this.schema = schema;
183
+ }
184
+ }
185
+ }
186
+ }
187
+
188
+ this.schemas.get(node.range.source.internalPath).push(schema);
189
+ this.schema = schema;
190
+ this.visitedClasses.add(node.range.source.internalPath + node.name.text);
81
191
 
82
192
  let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
83
193
  let INITIALIZE = "@inline __INITIALIZE(): this {\n";
@@ -85,11 +195,7 @@ class JSONTransform extends Visitor {
85
195
  let DESERIALIZE_CUSTOM = "";
86
196
  let SERIALIZE_CUSTOM = "";
87
197
 
88
- if (DEBUG) console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath);
89
-
90
- const members: FieldDeclaration[] = [...(node.members.filter((v) => v.kind === NodeKind.FieldDeclaration && v.flags !== CommonFlags.Static && v.flags !== CommonFlags.Private && v.flags !== CommonFlags.Protected && !v.decorators?.some((decorator) => (<IdentifierExpression>decorator.name).text === "omit")) as FieldDeclaration[])];
91
- const serializers: MethodDeclaration[] = [...node.members.filter((v) => v.kind === NodeKind.MethodDeclaration && v.decorators && v.decorators.some((e) => (<IdentifierExpression>e.name).text.toLowerCase() === "serializer"))] as MethodDeclaration[];
92
- const deserializers: MethodDeclaration[] = [...node.members.filter((v) => v.kind === NodeKind.MethodDeclaration && v.decorators && v.decorators.some((e) => (<IdentifierExpression>e.name).text.toLowerCase() === "deserializer"))] as MethodDeclaration[];
198
+ if (DEBUG > 0) console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath + (this.schema.deps.length ? " with dependencies:\n " + this.schema.deps.map((v) => v.name).join("\n ") : ""));
93
199
 
94
200
  if (serializers.length > 1) throwError("Multiple serializers detected for class " + node.name.text + " but schemas can only have one serializer!", serializers[1].range);
95
201
  if (deserializers.length > 1) throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
@@ -98,7 +204,7 @@ class JSONTransform extends Visitor {
98
204
  this.schema.custom = true;
99
205
  const serializer = serializers[0];
100
206
  const hasCall = CustomTransform.hasCall(serializer);
101
-
207
+
102
208
  CustomTransform.visit(serializer);
103
209
 
104
210
  // if (!serializer.signature.parameters.length) throwError("Could not find any parameters in custom serializer for " + this.schema.name + ". Serializers must have one parameter like 'serializer(self: " + this.schema.name + "): string {}'", serializer.range);
@@ -135,43 +241,11 @@ class JSONTransform extends Visitor {
135
241
  DESERIALIZE_CUSTOM += " }\n";
136
242
  }
137
243
 
138
- if (node.extendsType) {
139
- const extendsName = node.extendsType?.name.identifier.text;
140
- this.schema.parent = this.schemas.find((v) => v.name == extendsName) as Schema | null;
141
- if (!this.schema.parent) {
142
- const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
143
- if (internalSearch) {
144
- if (DEBUG) console.log("Found " + extendsName + " internally");
145
- this.visitClassDeclaration(internalSearch);
146
- this.visitClassDeclaration(node);
147
- return;
148
- }
149
-
150
- const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
151
- if (externalSearch) {
152
- if (DEBUG) console.log("Found " + extendsName + " externally");
153
- this.visitClassDeclaration(externalSearch);
154
- this.visitClassDeclaration(node);
155
- return;
156
- }
157
- }
158
- if (this.schema.parent?.members) {
159
- for (let i = this.schema.parent.members.length - 1; i >= 0; i--) {
160
- const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name);
161
- if (!replace) {
162
- members.unshift(this.schema.parent?.members[i]!.node);
163
- }
164
- }
165
- }
166
- }
167
-
168
244
  if (!members.length) {
169
245
  this.generateEmptyMethods(node);
170
246
  return;
171
247
  }
172
248
 
173
- this.addRequiredImports(node.range.source);
174
-
175
249
  for (const member of members) {
176
250
  if (!member.type) throwError("Fields must be strongly typed", node.range);
177
251
  const type = toString(member.type!);
@@ -239,22 +313,6 @@ class JSONTransform extends Visitor {
239
313
  SERIALIZE += indent + "bs.offset += 2;\n";
240
314
  }
241
315
 
242
- for (const member of this.schema.members) {
243
- if (isStruct(member.type)) {
244
- const schema = this.schemas.find((v) => v.name == stripNull(member.type));
245
- if (!schema) continue;
246
-
247
- if (!this.schema.deps.includes(schema)) {
248
- this.schema.deps.push(schema);
249
- this.schema.byteSize += schema.byteSize;
250
- }
251
-
252
- // if (schema.custom) {
253
- // member.flags.set(PropertyFlags.Custom, null);
254
- // }
255
- }
256
- }
257
-
258
316
  let isPure = this.schema.static;
259
317
  let isRegular = isPure;
260
318
  let isFirst = true;
@@ -268,7 +326,7 @@ class JSONTransform extends Visitor {
268
326
 
269
327
  if (member.value) {
270
328
  INITIALIZE += ` this.${member.name} = ${member.value};\n`;
271
- } else if (this.schemas.find((v) => nonNullType == v.name)) {
329
+ } else if (this.getSchema(nonNullType)) {
272
330
  INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`;
273
331
  } else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
274
332
  INITIALIZE += ` this.${member.name} = [];\n`;
@@ -371,11 +429,10 @@ class JSONTransform extends Visitor {
371
429
  indent = "";
372
430
  let shouldGroup = false;
373
431
 
374
- // DESERIALIZE += indent + " console.log(\"data: \" + JSON.Util.ptrToStr(srcStart,srcEnd))\n";
375
432
  DESERIALIZE += indent + " let keyStart: usize = 0;\n";
376
433
  DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
377
434
  DESERIALIZE += indent + " let isKey = false;\n";
378
- if (sortedMembers.object.length || sortedMembers.array.length) DESERIALIZE += indent + " let depth: i32 = 0;\n";
435
+ if (!STRICT || sortedMembers.object.length || sortedMembers.array.length) DESERIALIZE += indent + " let depth: i32 = 0;\n";
379
436
  DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
380
437
 
381
438
  DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
@@ -393,6 +450,7 @@ class JSONTransform extends Visitor {
393
450
  DESERIALIZE += indent + " if (isKey) {\n";
394
451
  DESERIALIZE += indent + " keyStart = lastIndex;\n";
395
452
  DESERIALIZE += indent + " keyEnd = srcStart;\n";
453
+ if (DEBUG > 1) DESERIALIZE += indent + " console.log(\"Key: \" + JSON.Util.ptrToStr(keyStart, keyEnd));\n";
396
454
  DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
397
455
  DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
398
456
  DESERIALIZE += indent + " isKey = false;\n";
@@ -425,12 +483,12 @@ class JSONTransform extends Visitor {
425
483
  }
426
484
 
427
485
  return [...groups.values()]
428
- .map(group =>
486
+ .map((group) =>
429
487
  group.sort((a, b) => {
430
488
  const aLen = (a.alias || a.name).length;
431
489
  const bLen = (b.alias || b.name).length;
432
490
  return aLen - bLen;
433
- })
491
+ }),
434
492
  )
435
493
  .sort((a, b) => b.length - a.length);
436
494
  };
@@ -471,23 +529,50 @@ class JSONTransform extends Visitor {
471
529
  // });
472
530
  // };
473
531
 
532
+ const generateGroups = (members: Property[], cb: (group: Property[]) => void, type: "string" | "array" | "object" | "number" | "boolean" | "null") => {
533
+ if (!members.length) {
534
+ if (STRICT) {
535
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
536
+ } else {
537
+ if (type == "string") {
538
+ DESERIALIZE += indent + " srcStart += 4;\n";
539
+ } else if (type == "boolean" || type == "null" || type == "number") {
540
+ DESERIALIZE += indent + " srcStart += 2;\n";
541
+ }
474
542
 
475
- const generateGroups = (members: Property[], cb: (group: Property[]) => void, nil: boolean = false) => {
476
- const groups = groupMembers(members);
477
- DESERIALIZE += " switch (<u32>keyEnd - <u32>keyStart) {\n";
543
+ DESERIALIZE += indent + " keyStart = 0;\n";
544
+ if (type == "string" || type == "object" || type == "array" || type == "number") DESERIALIZE += indent + " break;\n";
545
+ }
546
+ } else {
547
+ const groups = groupMembers(members);
548
+ DESERIALIZE += " switch (<u32>keyEnd - <u32>keyStart) {\n";
549
+
550
+ for (const group of groups) {
551
+ const groupLen = (group[0].alias || group[0].name).length << 1;
552
+ DESERIALIZE += " case " + groupLen + ": {\n";
553
+ cb(group);
554
+ DESERIALIZE += "\n }\n";
555
+ }
478
556
 
479
- for (const group of groups) {
480
- const groupLen = (group[0].alias || group[0].name).length << 1
481
- DESERIALIZE += " case " + groupLen + ": {\n";
482
- cb(group);
483
- DESERIALIZE += "\n }\n";
557
+ DESERIALIZE += " default: {\n";
558
+ if (STRICT) {
559
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
560
+ } else {
561
+ if (type == "string") {
562
+ DESERIALIZE += indent + " srcStart += 4;\n";
563
+ } else if (type == "boolean" || type == "null" || type == "number") {
564
+ DESERIALIZE += indent + " srcStart += 2;\n";
565
+ }
566
+ DESERIALIZE += indent + " keyStart = 0;\n";
567
+ if (type == "string" || type == "object" || type == "array" || type == "number") DESERIALIZE += indent + " break;\n";
568
+ }
569
+ DESERIALIZE += " }\n";
570
+ DESERIALIZE += " }\n";
571
+ if (type != "null" && type != "boolean") DESERIALIZE += " break;\n";
484
572
  }
573
+ };
485
574
 
486
- DESERIALIZE += " }\n";
487
- if (!members[0].node.type.isNullable && !isBoolean(members[0].type)) DESERIALIZE += " break;\n";
488
- }
489
-
490
- const generateComparisions = (members: Property[]) => {
575
+ const generateConsts = (members: Property[]): void => {
491
576
  if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
492
577
  DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
493
578
  }
@@ -503,38 +588,10 @@ class JSONTransform extends Visitor {
503
588
  if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
504
589
  DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
505
590
  }
506
-
507
- const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
508
- const firstMemberName = members[0].alias || members[0].name;
509
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
510
- 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";
511
- if (isString(members[0].type)) DESERIALIZE += indent + " srcStart += 4;\n";
512
- else if (!complex) DESERIALIZE += indent + " srcStart += 2;\n";
513
- DESERIALIZE += indent + " keyStart = 0;\n";
514
- DESERIALIZE += indent + " break;\n";
515
- DESERIALIZE += indent + " }";
516
-
517
- for (let i = 1; i < members.length; i++) {
518
- const member = members[i];
519
- const memberName = member.alias || member.name;
520
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
521
- 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";
522
- if (isString(member.type)) DESERIALIZE += indent + " srcStart += 4;\n";
523
- else if (!complex) DESERIALIZE += indent + " srcStart += 2;\n";
524
- DESERIALIZE += indent + " keyStart = 0;\n";
525
- DESERIALIZE += indent + " break;\n";
526
- DESERIALIZE += indent + " }";
527
- }
528
-
529
- if (STRICT) {
530
- DESERIALIZE += " else {\n";
531
- DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
532
- DESERIALIZE += indent + " }\n";
533
- }
534
- };
591
+ }
535
592
 
536
593
  let mbElse = " ";
537
- if (sortedMembers.string.length) {
594
+ if (!STRICT || sortedMembers.string.length) {
538
595
  // generateGroups(sortedMembers.string, generateComparisions)
539
596
  DESERIALIZE += mbElse + "if (code == 34) {\n";
540
597
  DESERIALIZE += " lastIndex = srcStart;\n";
@@ -542,8 +599,41 @@ class JSONTransform extends Visitor {
542
599
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
543
600
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
544
601
  DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
545
- // DESERIALIZE += " console.log(JSON.Util.ptrToStr(keyStart,keyEnd) + \" = \" + load<u16>(keyStart).toString() + \" val \" + JSON.Util.ptrToStr(lastIndex, srcStart));\n";
546
- generateGroups(sortedMembers.string, generateComparisions);
602
+ if (DEBUG > 1)DESERIALIZE += " console.log(\"Value (string, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart + 2));";
603
+ generateGroups(sortedMembers.string, (group) => {
604
+ generateConsts(group);
605
+ const first = group[0];
606
+ const fName = first.alias || first.name;
607
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
608
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
609
+ DESERIALIZE += indent + " srcStart += 4;\n";
610
+ DESERIALIZE += indent + " keyStart = 0;\n";
611
+ DESERIALIZE += indent + " break;\n";
612
+ DESERIALIZE += indent + " }";
613
+
614
+ for (let i = 1; i <group.length; i++) {
615
+ const mem = group[i];
616
+ const memName = mem.alias || mem.name;
617
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
618
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
619
+ DESERIALIZE += indent + " srcStart += 4;\n";
620
+ DESERIALIZE += indent + " keyStart = 0;\n";
621
+ DESERIALIZE += indent + " break;\n";
622
+ DESERIALIZE += indent + " }";
623
+ }
624
+
625
+ if (STRICT) {
626
+ DESERIALIZE += " else {\n";
627
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
628
+ DESERIALIZE += indent + " }\n";
629
+ } else {
630
+ DESERIALIZE += " else {\n";
631
+ DESERIALIZE += indent + " srcStart += 4;\n";
632
+ DESERIALIZE += indent + " keyStart = 0;\n";
633
+ DESERIALIZE += indent + " break;\n";
634
+ DESERIALIZE += indent + " }\n";
635
+ }
636
+ }, "string");
547
637
  DESERIALIZE += " }\n"; // Close break char check
548
638
  DESERIALIZE += " srcStart += 2;\n";
549
639
  DESERIALIZE += " }\n"; // Close char scan loop
@@ -551,16 +641,50 @@ class JSONTransform extends Visitor {
551
641
  mbElse = " else ";
552
642
  }
553
643
 
554
- if (sortedMembers.number.length) {
644
+ if (!STRICT || sortedMembers.number.length) {
555
645
  DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
556
646
  DESERIALIZE += " lastIndex = srcStart;\n";
557
647
  DESERIALIZE += " srcStart += 2;\n";
558
648
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
559
649
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
560
650
  DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
651
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (number, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
561
652
  // DESERIALIZE += " console.log(JSON.Util.ptrToStr(keyStart,keyEnd) + \" = \" + load<u16>(keyStart).toString() + \" val \" + JSON.Util.ptrToStr(lastIndex, srcStart));\n";
562
653
 
563
- generateGroups(sortedMembers.number, generateComparisions);
654
+ generateGroups(sortedMembers.number, (group) => {
655
+ generateConsts(group);
656
+ const first = group[0];
657
+ const fName = first.alias || first.name;
658
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
659
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
660
+ DESERIALIZE += indent + " srcStart += 2;\n";
661
+ DESERIALIZE += indent + " keyStart = 0;\n";
662
+ DESERIALIZE += indent + " break;\n";
663
+ DESERIALIZE += indent + " }";
664
+
665
+ for (let i = 1; i < group.length; i++) {
666
+ const mem = group[i];
667
+ const memName = mem.alias || mem.name;
668
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
669
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
670
+ DESERIALIZE += indent + " srcStart += 2;\n";
671
+ DESERIALIZE += indent + " keyStart = 0;\n";
672
+ DESERIALIZE += indent + " break;\n";
673
+ DESERIALIZE += indent + " }";
674
+ }
675
+
676
+ if (STRICT) {
677
+ DESERIALIZE += " else {\n";
678
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
679
+ DESERIALIZE += indent + " }\n";
680
+ } else {
681
+ DESERIALIZE += " else {\n";
682
+ DESERIALIZE += indent + " srcStart += 2;\n";
683
+ DESERIALIZE += indent + " keyStart = 0;\n";
684
+ DESERIALIZE += indent + " break;\n";
685
+ DESERIALIZE += indent + " }\n";
686
+ }
687
+ }, "number");
564
688
  DESERIALIZE += " }\n"; // Close break char check
565
689
  DESERIALIZE += " srcStart += 2;\n";
566
690
  DESERIALIZE += " }\n"; // Close char scan loop
@@ -568,7 +692,7 @@ class JSONTransform extends Visitor {
568
692
  mbElse = " else ";
569
693
  }
570
694
 
571
- if (sortedMembers.object.length) {
695
+ if (!STRICT || sortedMembers.object.length) {
572
696
  DESERIALIZE += mbElse + "if (code == 123) {\n";
573
697
  DESERIALIZE += " lastIndex = srcStart;\n";
574
698
  DESERIALIZE += " depth++;\n";
@@ -581,9 +705,40 @@ class JSONTransform extends Visitor {
581
705
  DESERIALIZE += " } else if (code == 125) {\n";
582
706
  DESERIALIZE += " if (--depth == 0) {\n";
583
707
  DESERIALIZE += " srcStart += 2;\n";
708
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (object, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
584
709
 
585
710
  indent = " ";
586
- generateGroups(sortedMembers.object, generateComparisions);
711
+ generateGroups(sortedMembers.object, (group) => {
712
+ generateConsts(group);
713
+ const first = group[0];
714
+ const fName = first.alias || first.name;
715
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
716
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
717
+ DESERIALIZE += indent + " keyStart = 0;\n";
718
+ DESERIALIZE += indent + " break;\n";
719
+ DESERIALIZE += indent + " }";
720
+
721
+ for (let i = 1; i < group.length; i++) {
722
+ const mem = group[i];
723
+ const memName = mem.alias || mem.name;
724
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
725
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
726
+ DESERIALIZE += indent + " keyStart = 0;\n";
727
+ DESERIALIZE += indent + " break;\n";
728
+ DESERIALIZE += indent + " }";
729
+ }
730
+
731
+ if (STRICT) {
732
+ DESERIALIZE += " else {\n";
733
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
734
+ DESERIALIZE += indent + " }\n";
735
+ } else {
736
+ DESERIALIZE += " else {\n";
737
+ DESERIALIZE += indent + " keyStart = 0;\n";
738
+ DESERIALIZE += indent + " break;\n";
739
+ DESERIALIZE += indent + " }\n";
740
+ }
741
+ }, "object");
587
742
  indent = "";
588
743
 
589
744
  DESERIALIZE += " }\n"; // Close break char check
@@ -593,7 +748,7 @@ class JSONTransform extends Visitor {
593
748
  DESERIALIZE += " }"; // Close first char check
594
749
  mbElse = " else ";
595
750
  }
596
- if (sortedMembers.array.length) {
751
+ if (!STRICT || sortedMembers.array.length) {
597
752
  DESERIALIZE += mbElse + "if (code == 91) {\n";
598
753
  DESERIALIZE += " lastIndex = srcStart;\n";
599
754
  DESERIALIZE += " depth++;\n";
@@ -606,10 +761,40 @@ class JSONTransform extends Visitor {
606
761
  DESERIALIZE += " } else if (code == 93) {\n";
607
762
  DESERIALIZE += " if (--depth == 0) {\n";
608
763
  DESERIALIZE += " srcStart += 2;\n";
609
- // DESERIALIZE += " console.log(ptrToStr(keyStart,keyEnd) + \" = \" + (load<u64>(keyStart) & 0x0000FFFFFFFFFFFF) .toString());\n";
764
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (object, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart));";
610
765
 
611
766
  indent = " ";
612
- generateGroups(sortedMembers.array, generateComparisions);
767
+ generateGroups(sortedMembers.array, (group) => {
768
+ generateConsts(group);
769
+ const first = group[0];
770
+ const fName = first.alias || first.name;
771
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
772
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
773
+ DESERIALIZE += indent + " keyStart = 0;\n";
774
+ DESERIALIZE += indent + " break;\n";
775
+ DESERIALIZE += indent + " }";
776
+
777
+ for (let i = 1; i < group.length; i++) {
778
+ const mem = group[i];
779
+ const memName = mem.alias || mem.name;
780
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
781
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
782
+ DESERIALIZE += indent + " keyStart = 0;\n";
783
+ DESERIALIZE += indent + " break;\n";
784
+ DESERIALIZE += indent + " }";
785
+ }
786
+
787
+ if (STRICT) {
788
+ DESERIALIZE += " else {\n";
789
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
790
+ DESERIALIZE += indent + " }\n";
791
+ } else {
792
+ DESERIALIZE += " else {\n";
793
+ DESERIALIZE += indent + " keyStart = 0;\n";
794
+ DESERIALIZE += indent + " break;\n";
795
+ DESERIALIZE += indent + " }\n";
796
+ }
797
+ }, "array");
613
798
  indent = "";
614
799
 
615
800
  DESERIALIZE += " }\n"; // Close break char check
@@ -620,152 +805,154 @@ class JSONTransform extends Visitor {
620
805
  mbElse = " else ";
621
806
  }
622
807
 
623
- if (sortedMembers.boolean.length) {
808
+ if (!STRICT || sortedMembers.boolean.length) {
809
+ // TRUE
624
810
  DESERIALIZE += mbElse + "if (code == 116) {\n";
811
+
625
812
  DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
626
813
  DESERIALIZE += " srcStart += 8;\n";
627
-
814
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
628
815
  generateGroups(sortedMembers.boolean, (group) => {
629
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
630
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
631
- }
632
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
633
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
634
- }
635
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
636
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
637
- }
638
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
639
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
640
- }
641
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
642
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
643
- }
644
- const firstMemberName = group[0].alias || group[0].name;
645
-
646
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
647
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
648
- DESERIALIZE += indent + " srcStart += 2;\n";
649
- DESERIALIZE += indent + " keyStart = 0;\n";
650
- DESERIALIZE += indent + " break;\n";
651
- DESERIALIZE += indent + " }";
652
-
653
- for (let i = 1; i < group.length; i++) {
654
- const member = group[i];
655
- const memberName = member.alias || member.name;
656
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
657
- DESERIALIZE += indent + " store<" + member.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
816
+ generateConsts(group);
817
+ const first = group[0];
818
+ const fName =first.alias || first.name;
819
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
820
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
658
821
  DESERIALIZE += indent + " srcStart += 2;\n";
659
822
  DESERIALIZE += indent + " keyStart = 0;\n";
660
823
  DESERIALIZE += indent + " break;\n";
661
824
  DESERIALIZE += indent + " }";
662
- }
663
825
 
664
- if (STRICT) {
665
- DESERIALIZE += " else {\n";
666
- DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
667
- DESERIALIZE += indent + " }\n";
668
- }
669
- });
826
+ for (let i = 1; i < group.length; i++) {
827
+ const mem = group[i];
828
+ const memName = mem.alias || mem.name;
829
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
830
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
831
+ DESERIALIZE += indent + " srcStart += 2;\n";
832
+ DESERIALIZE += indent + " keyStart = 0;\n";
833
+ DESERIALIZE += indent + " break;\n";
834
+ DESERIALIZE += indent + " }";
835
+ }
836
+
837
+ if (STRICT) {
838
+ DESERIALIZE += " else {\n";
839
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
840
+ DESERIALIZE += indent + " }\n";
841
+ } else {
842
+ DESERIALIZE += " else { \n";
843
+ DESERIALIZE += indent + " srcStart += 2;\n";
844
+ DESERIALIZE += indent + " keyStart = 0;\n";
845
+ DESERIALIZE += indent + " break;\n";
846
+ DESERIALIZE += indent + " }\n";
847
+ }
848
+ },
849
+ "boolean",
850
+ );
670
851
 
671
852
  DESERIALIZE += " }"; // Close first char check
672
- mbElse = " else ";
673
- DESERIALIZE += " else if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
674
- DESERIALIZE += " srcStart += 10;\n";
853
+ DESERIALIZE += " else {\n";
854
+ DESERIALIZE += " throw new Error(\"Expected to find 'true' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
855
+ DESERIALIZE += " }"; // Close error check
856
+ DESERIALIZE += "\n }"; // Close first char check
675
857
 
676
- generateGroups(sortedMembers.boolean, (group) => {
677
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
678
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
679
- }
680
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
681
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
682
- }
683
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
684
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
685
- }
686
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
687
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
688
- }
689
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
690
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
691
- }
692
- const firstMemberName = group[0].alias || group[0].name;
858
+ mbElse = " else ";
693
859
 
694
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
695
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
696
- DESERIALIZE += indent + " srcStart += 2;\n";
697
- DESERIALIZE += indent + " keyStart = 0;\n";
698
- DESERIALIZE += indent + " break;\n";
699
- DESERIALIZE += indent + " }";
860
+ // FALSE
861
+ DESERIALIZE += mbElse + "if (code == 102) {\n";
700
862
 
701
- for (let i = 1; i < group.length; i++) {
702
- const member = group[i];
703
- const memberName = member.alias || member.name;
704
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
705
- DESERIALIZE += indent + " store<" + member.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(member.name) + "));\n";
863
+ DESERIALIZE += " if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
864
+ DESERIALIZE += " srcStart += 10;\n";
865
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (bool, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 10));";
866
+ generateGroups( sortedMembers.boolean, (group) => {
867
+ generateConsts(group);
868
+
869
+ const first = group[0];
870
+ const fName = first.alias || first.name;
871
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
872
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
706
873
  DESERIALIZE += indent + " srcStart += 2;\n";
707
874
  DESERIALIZE += indent + " keyStart = 0;\n";
708
875
  DESERIALIZE += indent + " break;\n";
709
876
  DESERIALIZE += indent + " }";
710
- }
711
877
 
712
- if (STRICT) {
713
- DESERIALIZE += " else {\n";
714
- DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
715
- DESERIALIZE += indent + " }\n";
716
- }
717
- });
718
- DESERIALIZE += " }\n"; // Close first char check
719
- DESERIALIZE += " }"; // Close first char check
878
+ for (let i = 1; i < group.length; i++) {
879
+ const mem = group[i];
880
+ const memName = mem.alias || mem.name;
881
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
882
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
883
+ DESERIALIZE += indent + " srcStart += 2;\n";
884
+ DESERIALIZE += indent + " keyStart = 0;\n";
885
+ DESERIALIZE += indent + " break;\n";
886
+ DESERIALIZE += indent + " }";
887
+ }
888
+
889
+ if (STRICT) {
890
+ DESERIALIZE += " else {\n";
891
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
892
+ DESERIALIZE += indent + " }\n";
893
+ } else {
894
+ DESERIALIZE += " else { \n";
895
+ DESERIALIZE += indent + " srcStart += 2;\n";
896
+ DESERIALIZE += indent + " keyStart = 0;\n";
897
+ DESERIALIZE += indent + " break;\n";
898
+ DESERIALIZE += indent + " }\n";
899
+ }
900
+ },
901
+ "boolean",
902
+ );
903
+
904
+ DESERIALIZE += " }"; // Close first char check
905
+ DESERIALIZE += " else {\n";
906
+ DESERIALIZE += " throw new Error(\"Expected to find 'false' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
907
+ DESERIALIZE += " }"; // Close error check
908
+ DESERIALIZE += "\n }"; // Close first char check
909
+
910
+ mbElse = " else ";
720
911
  }
721
912
 
722
- if (sortedMembers.null.length) {
913
+ if (!STRICT || sortedMembers.null.length) {
723
914
  DESERIALIZE += mbElse + "if (code == 110) {\n";
724
915
 
725
916
  DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
726
917
  DESERIALIZE += " srcStart += 8;\n";
918
+ if (DEBUG > 1) DESERIALIZE += " console.log(\"Value (null, " + (++id) + "): \" + JSON.Util.ptrToStr(lastIndex, srcStart - 8));";
727
919
  generateGroups(sortedMembers.null, (group) => {
728
- if (group.some((m) => (m.alias || m.name).length << 1 == 2)) {
729
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
730
- }
731
- if (group.some((m) => (m.alias || m.name).length << 1 == 4)) {
732
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
733
- }
734
- if (group.some((m) => (m.alias || m.name).length << 1 == 6)) {
735
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
736
- }
737
- if (group.some((m) => (m.alias || m.name).length << 1 == 8)) {
738
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
739
- }
740
- if (group.some((m) => (m.alias || m.name).length << 1 > 8)) {
741
- DESERIALIZE += toMemCDecl(Math.max(...group.map((m) => (m.alias || m.name).length << 1)), " ");
742
- }
920
+ generateConsts(group);
743
921
 
744
- const firstMemberName = group[0].alias || group[0].name;
745
- DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
746
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
747
- DESERIALIZE += indent + " srcStart += 2;\n";
748
- DESERIALIZE += indent + " keyStart = 0;\n";
749
- DESERIALIZE += indent + " break;\n";
750
- DESERIALIZE += indent + " }";
751
-
752
- for (let i = 1; i < group.length; i++) {
753
- const member = group[i];
754
- const memberName = member.alias || member.name;
755
- DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
756
- DESERIALIZE += indent + " store<" + group[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(group[0].name) + "));\n";
922
+ const first = group[0];
923
+ const fName = first.alias || first.name;
924
+ DESERIALIZE += indent + " if (" + getComparision(fName) + ") { // " + fName + "\n";
925
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
757
926
  DESERIALIZE += indent + " srcStart += 2;\n";
758
927
  DESERIALIZE += indent + " keyStart = 0;\n";
759
928
  DESERIALIZE += indent + " break;\n";
760
929
  DESERIALIZE += indent + " }";
761
- }
762
930
 
763
- if (STRICT) {
764
- DESERIALIZE += " else {\n";
765
- DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
766
- DESERIALIZE += indent + " }\n";
767
- }
768
- }, true);
931
+ for (let i = 1; i < group.length; i++) {
932
+ const mem = group[i];
933
+ const memName = mem.alias || mem.name;
934
+ DESERIALIZE += indent + " else if (" + getComparision(memName) + ") { // " + memName + "\n";
935
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
936
+ DESERIALIZE += indent + " srcStart += 2;\n";
937
+ DESERIALIZE += indent + " keyStart = 0;\n";
938
+ DESERIALIZE += indent + " break;\n";
939
+ DESERIALIZE += indent + " }";
940
+ }
941
+
942
+ if (STRICT) {
943
+ DESERIALIZE += " else {\n";
944
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
945
+ DESERIALIZE += indent + " }\n";
946
+ } else {
947
+ DESERIALIZE += " else { \n";
948
+ DESERIALIZE += indent + " srcStart += 2;\n";
949
+ DESERIALIZE += indent + " keyStart = 0;\n";
950
+ DESERIALIZE += indent + " break;\n";
951
+ DESERIALIZE += indent + " }\n";
952
+ }
953
+ },
954
+ "null",
955
+ );
769
956
 
770
957
  DESERIALIZE += " }"; // Close first char check
771
958
  DESERIALIZE += "\n }"; // Close first char check
@@ -775,6 +962,7 @@ class JSONTransform extends Visitor {
775
962
 
776
963
  DESERIALIZE += " else {\n";
777
964
  DESERIALIZE += " srcStart += 2;\n";
965
+ DESERIALIZE += " keyStart = 0;\n";
778
966
  DESERIALIZE += "}\n";
779
967
  DESERIALIZE += "\n }\n"; // Close value portion
780
968
 
@@ -798,7 +986,7 @@ class JSONTransform extends Visitor {
798
986
  // if (DESERIALIZE_CUSTOM) {
799
987
  // DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): usize {\n if (isDefined(this.__DESERIALIZE_CUSTOM) return changetype<usize>(this." + deserializers[0].name + "(changetype<switch (<u32>keyEnd - <u32>keyStart) {\n"
800
988
  // }
801
- if (DEBUG) {
989
+ if (DEBUG > 0) {
802
990
  console.log(SERIALIZE_CUSTOM || SERIALIZE);
803
991
  console.log(INITIALIZE);
804
992
  console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
@@ -813,12 +1001,16 @@ class JSONTransform extends Visitor {
813
1001
  if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD);
814
1002
  super.visitClassDeclaration(node);
815
1003
  }
1004
+ getSchema(name: string): Schema | null {
1005
+ name = stripNull(name);
1006
+ return this.schemas.get(this.schema.node.range.source.internalPath).find((s) => s.name == name) || null;
1007
+ }
816
1008
  generateEmptyMethods(node: ClassDeclaration): void {
817
1009
  let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
818
1010
  let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
819
1011
  let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return this;\n}";
820
1012
 
821
- if (DEBUG) {
1013
+ if (DEBUG > 0) {
822
1014
  console.log(SERIALIZE_EMPTY);
823
1015
  console.log(INITIALIZE_EMPTY);
824
1016
  console.log(DESERIALIZE_EMPTY);
@@ -865,39 +1057,104 @@ class JSONTransform extends Visitor {
865
1057
  this.imports = [];
866
1058
  super.visitSource(node);
867
1059
  }
868
- addRequiredImports(node: Source): void {
869
- const filePath = fileURLToPath(import.meta.url);
870
- const baseDir = path.resolve(filePath, "..", "..", "..");
871
- const nodePath = path.resolve(this.baseDir, node.range.source.normalizedPath);
1060
+ addImports(node: Source): void {
1061
+ const baseDir = path.resolve(
1062
+ fileURLToPath(import.meta.url),
1063
+ "..",
1064
+ "..",
1065
+ "..",
1066
+ );
1067
+ const pkgPath = path.join(this.baseCWD, "node_modules");
1068
+ const isLibrary = existsSync(path.join(pkgPath, "json-as"));
1069
+ let fromPath = node.range.source.normalizedPath;
1070
+
1071
+ fromPath = fromPath.startsWith("~lib/")
1072
+ ? existsSync(
1073
+ path.join(pkgPath, fromPath.slice(5, fromPath.indexOf("/", 5))),
1074
+ )
1075
+ ? path.join(pkgPath, fromPath.slice(5))
1076
+ : fromPath
1077
+ : path.join(baseDir, fromPath);
872
1078
 
873
1079
  const bsImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "bs" || d.name.text == "bs"));
874
1080
  const jsonImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "JSON" || d.name.text == "JSON"));
875
1081
 
876
- let bsPath = path.posix.join(...path.relative(path.dirname(nodePath), path.join(baseDir, "lib", "as-bs")).split(path.sep)).replace(/^.*node_modules\/json-as/, "json-as");
1082
+ let bsRel = removeExtension(
1083
+ path.posix.join(
1084
+ ...path
1085
+ .relative(path.dirname(fromPath), path.join(baseDir, "lib", "as-bs"))
1086
+ .split(path.sep),
1087
+ ),
1088
+ );
1089
+
1090
+ let jsRel = removeExtension(
1091
+ path.posix.join(
1092
+ ...path
1093
+ .relative(path.dirname(fromPath), path.join(baseDir, "assembly", "index"))
1094
+ .split(path.sep),
1095
+ ),
1096
+ );
1097
+
1098
+ if (bsRel.includes("node_modules" + path.sep + "json-as")) {
1099
+ bsRel =
1100
+ "json-as" +
1101
+ bsRel.slice(
1102
+ bsRel.indexOf("node_modules" + path.sep + "json-as") + 20,
1103
+ )
1104
+ } else if (
1105
+ !bsRel.startsWith(".") &&
1106
+ !bsRel.startsWith("/") &&
1107
+ !bsRel.startsWith("json-as")
1108
+ ) {
1109
+ bsRel = "./" + bsRel;
1110
+ }
877
1111
 
878
- let jsonPath = path.posix.join(...path.relative(path.dirname(nodePath), path.join(baseDir, "assembly", "index.ts")).split(path.sep)).replace(/^.*node_modules\/json-as/, "json-as");
1112
+ if (jsRel.includes("node_modules" + path.sep + "json-as")) {
1113
+ jsRel =
1114
+ "json-as" +
1115
+ jsRel.slice(
1116
+ jsRel.indexOf("node_modules" + path.sep + "json-as") + 20,
1117
+ );
1118
+ } else if (
1119
+ !jsRel.startsWith(".") &&
1120
+ !jsRel.startsWith("/") &&
1121
+ !jsRel.startsWith("json-as")
1122
+ ) {
1123
+ jsRel = "./" + jsRel;
1124
+ }
879
1125
 
880
1126
  if (!bsImport) {
881
- if (node.normalizedPath.startsWith("~")) {
882
- bsPath = "json-as/lib/as-bs";
883
- }
884
-
885
- const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
886
- this.topStatements.push(replaceNode);
887
- if (DEBUG) console.log("Added as-bs import: " + toString(replaceNode) + "\n");
1127
+ const replaceNode = Node.createImportStatement(
1128
+ [Node.createImportDeclaration(
1129
+ Node.createIdentifierExpression("bs", node.range, false),
1130
+ null,
1131
+ node.range
1132
+ )
1133
+ ],
1134
+ Node.createStringLiteralExpression(bsRel, node.range),
1135
+ node.range
1136
+ );
1137
+ node.range.source.statements.unshift(replaceNode);
1138
+ if (DEBUG > 0) console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
888
1139
  }
889
1140
 
890
1141
  if (!jsonImport) {
891
- if (node.normalizedPath.startsWith("~")) {
892
- jsonPath = "json-as/assembly/index.ts";
893
- }
894
1142
  const replaceNode = Node.createImportStatement(
895
- [Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)],
896
- Node.createStringLiteralExpression(jsonPath, node.range), // Ensure POSIX-style path for 'assembly'
1143
+ [Node.createImportDeclaration(
1144
+ Node.createIdentifierExpression(
1145
+ "JSON",
1146
+ node.range,
1147
+ false
1148
+ ),
1149
+ null,
1150
+ node.range
1151
+ )
1152
+ ],
1153
+ Node.createStringLiteralExpression(jsRel, node.range), // Ensure POSIX-style path for 'assembly'
897
1154
  node.range,
898
1155
  );
899
- this.topStatements.push(replaceNode);
900
- if (DEBUG) console.log("Added json-as import: " + toString(replaceNode) + "\n");
1156
+ node.range.source.statements.unshift(replaceNode);
1157
+ if (DEBUG > 0) console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
901
1158
  }
902
1159
  }
903
1160
 
@@ -929,7 +1186,7 @@ class JSONTransform extends Visitor {
929
1186
  return out;
930
1187
  }
931
1188
  isValidType(type: string, node: ClassDeclaration): boolean {
932
- const validTypes = ["string", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean", "Date", "JSON.Value", "JSON.Obj", "JSON.Raw", "Value", "Obj", "Raw", ...this.schemas.map((v) => v.name)];
1189
+ const validTypes = ["string", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean", "Date", "JSON.Value", "JSON.Obj", "JSON.Raw", "Value", "Obj", "Raw", ...this.schemas.get(this.schema.node.range.source.internalPath).map((v) => v.name)];
933
1190
 
934
1191
  const baseTypes = ["Array", "Map", "Set", "JSON.Box", "Box"];
935
1192
 
@@ -972,7 +1229,7 @@ export default class Transformer extends Transform {
972
1229
  }
973
1230
  });
974
1231
 
975
- transformer.baseDir = path.join(process.cwd(), this.baseDir);
1232
+ transformer.baseCWD = path.join(process.cwd(), this.baseDir);
976
1233
  transformer.program = this.program;
977
1234
  transformer.parser = parser;
978
1235
  for (const source of sources) {
@@ -988,13 +1245,12 @@ export default class Transformer extends Transform {
988
1245
  for (const simd of transformer.simdStatements) source.statements.unshift(SimpleParser.parseTopLevelStatement(simd));
989
1246
  }
990
1247
  transformer.simdStatements = [];
991
- }
992
1248
 
993
- const schemas = transformer.schemas;
994
- for (const schema of schemas) {
995
- if (schema.parent) {
996
- const parent = schemas.find((v) => v.name == schema.parent?.name);
997
- if (!parent) throwError(`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator!`, schema.parent.node.range);
1249
+ if (transformer.schemas.has(source.internalPath)) {
1250
+ transformer.addImports(source);
1251
+ }
1252
+ if (source.normalizedPath == WRITE) {
1253
+ writeFileSync(path.join(process.cwd(), this.baseDir, removeExtension(source.normalizedPath) + ".json.ts"), toString(source));
998
1254
  }
999
1255
  }
1000
1256
  }
@@ -1150,9 +1406,9 @@ function isBoolean(type: string): boolean {
1150
1406
  return type == "bool" || type == "boolean";
1151
1407
  }
1152
1408
 
1153
- function isStruct(type: string): boolean {
1409
+ function isStruct(type: string, source: Source): boolean {
1154
1410
  type = stripNull(type);
1155
- return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
1411
+ return JSONTransform.SN.schemas.get(source.internalPath).some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
1156
1412
  }
1157
1413
 
1158
1414
  function isString(type: string) {
@@ -1188,4 +1444,4 @@ function getComparision(data: string) {
1188
1444
  return toMemCCheck(data);
1189
1445
  }
1190
1446
  }
1191
- }
1447
+ }