json-as 1.2.1 → 1.2.2-beta.1

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.
Files changed (79) hide show
  1. package/package.json +1 -1
  2. package/.github/FUNDING.yml +0 -1
  3. package/.github/dependabot.yml +0 -11
  4. package/.github/workflows/benchmark.yml +0 -72
  5. package/.github/workflows/release-package.yml +0 -47
  6. package/.github/workflows/tests.yml +0 -25
  7. package/.prettierignore +0 -9
  8. package/.prettierrc.json +0 -7
  9. package/.trunk/configs/.markdownlint.yaml +0 -2
  10. package/.trunk/configs/.shellcheckrc +0 -7
  11. package/.trunk/configs/.yamllint.yaml +0 -7
  12. package/.trunk/trunk.yaml +0 -37
  13. package/CHANGELOG.md +0 -334
  14. package/SECURITY.md +0 -32
  15. package/asconfig.json +0 -7
  16. package/assembly/__benches__/abc.bench.ts +0 -28
  17. package/assembly/__benches__/large.bench.ts +0 -238
  18. package/assembly/__benches__/lib/bench.ts +0 -85
  19. package/assembly/__benches__/medium.bench.ts +0 -128
  20. package/assembly/__benches__/small.bench.ts +0 -46
  21. package/assembly/__benches__/throughput.ts +0 -172
  22. package/assembly/__benches__/vec3.bench.ts +0 -37
  23. package/assembly/__tests__/arbitrary.spec.ts +0 -35
  24. package/assembly/__tests__/array.spec.ts +0 -145
  25. package/assembly/__tests__/bool.spec.ts +0 -12
  26. package/assembly/__tests__/box.spec.ts +0 -27
  27. package/assembly/__tests__/custom.spec.ts +0 -56
  28. package/assembly/__tests__/date.spec.ts +0 -36
  29. package/assembly/__tests__/enum.spec.ts +0 -35
  30. package/assembly/__tests__/float.spec.ts +0 -42
  31. package/assembly/__tests__/generics.spec.ts +0 -49
  32. package/assembly/__tests__/hierarchy.spec.ts +0 -61
  33. package/assembly/__tests__/integer.spec.ts +0 -26
  34. package/assembly/__tests__/lib/index.ts +0 -41
  35. package/assembly/__tests__/map.spec.ts +0 -7
  36. package/assembly/__tests__/namespace.spec.ts +0 -63
  37. package/assembly/__tests__/null.spec.ts +0 -12
  38. package/assembly/__tests__/raw.spec.ts +0 -23
  39. package/assembly/__tests__/resolving.spec.ts +0 -55
  40. package/assembly/__tests__/staticarray.spec.ts +0 -12
  41. package/assembly/__tests__/string.spec.ts +0 -30
  42. package/assembly/__tests__/struct.spec.ts +0 -163
  43. package/assembly/__tests__/test.spec.ts +0 -3
  44. package/assembly/__tests__/types.spec.ts +0 -27
  45. package/assembly/__tests__/types.ts +0 -98
  46. package/assembly/test.tmp.ts +0 -133
  47. package/bench/abc.bench.ts +0 -25
  48. package/bench/large.bench.ts +0 -127
  49. package/bench/lib/bench.d.ts +0 -27
  50. package/bench/lib/bench.js +0 -53
  51. package/bench/lib/chart.ts +0 -217
  52. package/bench/medium.bench.ts +0 -68
  53. package/bench/runners/assemblyscript.js +0 -34
  54. package/bench/small.bench.ts +0 -34
  55. package/bench/throughput.ts +0 -87
  56. package/bench/tsconfig.json +0 -13
  57. package/bench/vec3.bench.ts +0 -30
  58. package/bench.ts +0 -18
  59. package/ci/bench/lib/bench.ts +0 -42
  60. package/ci/bench/runners/assemblyscript.js +0 -29
  61. package/ci/run-bench.as.sh +0 -63
  62. package/publish.sh +0 -78
  63. package/run-bench.as.sh +0 -60
  64. package/run-bench.js.sh +0 -36
  65. package/run-tests.sh +0 -51
  66. package/scripts/build-chart01.ts +0 -38
  67. package/scripts/build-chart02.ts +0 -38
  68. package/scripts/build-chart03.ts +0 -139
  69. package/scripts/build-chart05.ts +0 -47
  70. package/scripts/generate-as-class.ts +0 -50
  71. package/scripts/lib/bench-utils.ts +0 -308
  72. package/transform/src/builder.ts +0 -1375
  73. package/transform/src/index.ts +0 -1486
  74. package/transform/src/linkers/alias.ts +0 -58
  75. package/transform/src/linkers/custom.ts +0 -32
  76. package/transform/src/linkers/imports.ts +0 -22
  77. package/transform/src/types.ts +0 -300
  78. package/transform/src/util.ts +0 -128
  79. package/transform/src/visitor.ts +0 -530
@@ -1,1486 +0,0 @@
1
- import { ClassDeclaration, FieldDeclaration, IdentifierExpression, Parser, Source, NodeKind, CommonFlags, ImportStatement, Node, SourceKind, NamedTypeNode, Range, FunctionExpression, MethodDeclaration, Program, Feature } from "assemblyscript/dist/assemblyscript.js";
2
- import { Transform } from "assemblyscript/dist/transform.js";
3
- import { Visitor } from "./visitor.js";
4
- import { isStdlib, removeExtension, SimpleParser, toString } from "./util.js";
5
- import * as path from "path";
6
- import { fileURLToPath } from "url";
7
- import { Property, PropertyFlags, Schema, Src, SourceSet } from "./types.js";
8
- import { readFileSync, writeFileSync } from "fs";
9
- import { CustomTransform } from "./linkers/custom.js";
10
-
11
- let indent = " ";
12
-
13
- let id = 0;
14
-
15
- const WRITE = process.env["JSON_WRITE"]?.trim();
16
- const rawValue = process.env["JSON_DEBUG"]?.trim();
17
-
18
- const DEBUG = rawValue === "true" ? 1 : rawValue === "false" || rawValue === "" ? 0 : isNaN(Number(rawValue)) ? 0 : Number(rawValue);
19
-
20
- const STRICT = process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "true";
21
- export class JSONTransform extends Visitor {
22
- static SN: JSONTransform = new JSONTransform();
23
-
24
- public program!: Program;
25
- public baseCWD!: string;
26
- public parser!: Parser;
27
- public schemas: Map<string, Schema[]> = new Map<string, Schema[]>();
28
- public schema!: Schema;
29
- public sources: SourceSet = new SourceSet();
30
- public imports: ImportStatement[] = [];
31
- public simdStatements: string[] = [];
32
-
33
- private visitedClasses: Set<string> = new Set<string>();
34
-
35
- visitClassDeclarationRef(node: ClassDeclaration): void {
36
- if (
37
- !node.decorators?.length ||
38
- !node.decorators.some((decorator) => {
39
- const name = (<IdentifierExpression>decorator.name).text;
40
- return name === "json" || name === "serializable";
41
- })
42
- )
43
- throw new Error("Class " + node.name.text + " is missing an @json or @serializable decorator in " + node.range.source.internalPath);
44
- this.visitClassDeclaration(node);
45
- }
46
-
47
- resolveType(type: string, source: Src, visited = new Set<string>()): string {
48
- const stripped = stripNull(type);
49
-
50
- if (visited.has(stripped)) {
51
- return stripped;
52
- }
53
- visited.add(stripped);
54
-
55
- const resolvedType = source.aliases.find((v) => stripNull(v.name) === stripped)?.getBaseType();
56
-
57
- if (resolvedType) {
58
- return this.resolveType(resolvedType, source, visited);
59
- }
60
-
61
- for (const imp of source.imports) {
62
- if (!imp.declarations) continue;
63
-
64
- for (const decl of imp.declarations) {
65
- if (decl.name.text === stripped) {
66
- const externalSource = this.parser.sources.find((s) => s.internalPath === imp.internalPath);
67
- if (externalSource) {
68
- const externalSrc = this.sources.get(externalSource);
69
- if (!externalSrc) continue;
70
-
71
- const externalAlias = externalSrc.aliases.find((a) => a.name === decl.foreignName.text);
72
-
73
- if (externalAlias) {
74
- const externalType = externalAlias.getBaseType();
75
- return this.resolveType(externalType, externalSrc, visited);
76
- }
77
- }
78
- }
79
- }
80
- }
81
-
82
- return type;
83
- }
84
-
85
- visitClassDeclaration(node: ClassDeclaration): void {
86
- if (!node.decorators?.length) return;
87
-
88
- if (
89
- !node.decorators.some((decorator) => {
90
- const name = (<IdentifierExpression>decorator.name).text;
91
- return name === "json" || name === "serializable";
92
- })
93
- )
94
- return;
95
-
96
- const source = this.sources.get(node.range.source);
97
-
98
- const fullClassPath = source.getFullPath(node);
99
-
100
- if (this.visitedClasses.has(fullClassPath)) return;
101
- if (!this.schemas.has(source.internalPath)) this.schemas.set(source.internalPath, []);
102
-
103
- 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[])];
104
- 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[];
105
- 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[];
106
-
107
- const schema = new Schema();
108
- schema.node = node;
109
- schema.name = source.getQualifiedName(node);
110
-
111
- if (node.extendsType) {
112
- const extendsName = source.resolveExtendsName(node);
113
-
114
- if (!schema.parent) {
115
- const depSearch = schema.deps.find((v) => v.name == extendsName);
116
- if (depSearch) {
117
- if (DEBUG > 0) console.log("Found " + extendsName + " in dependencies of " + source.internalPath);
118
- if (!schema.deps.some((v) => v.name == depSearch.name)) schema.deps.push(depSearch);
119
- schema.parent = depSearch;
120
- } else {
121
- const internalSearch = source.getClass(extendsName);
122
- if (internalSearch) {
123
- if (DEBUG > 0) console.log("Found " + extendsName + " internally from " + source.internalPath);
124
- if (!this.visitedClasses.has(source.getFullPath(internalSearch))) {
125
- this.visitClassDeclarationRef(internalSearch);
126
- this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
127
- this.visitClassDeclaration(node);
128
- return;
129
- }
130
- const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == extendsName);
131
- if (!schem) throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
132
- schema.deps.push(schem);
133
- schema.parent = schem;
134
- } else {
135
- const externalSearch = source.getImportedClass(extendsName, this.parser);
136
- if (externalSearch) {
137
- if (DEBUG > 0) console.log("Found " + externalSearch.name.text + " externally from " + source.internalPath);
138
- const externalSource = this.sources.get(externalSearch.range.source);
139
- if (!this.visitedClasses.has(externalSource.getFullPath(externalSearch))) {
140
- this.visitClassDeclarationRef(externalSearch);
141
- this.schemas.get(externalSource.internalPath).push(this.schema);
142
- this.visitClassDeclaration(node);
143
- return;
144
- }
145
- const schem = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == extendsName);
146
- if (!schem) throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSource.internalPath);
147
- schema.deps.push(schem);
148
- schema.parent = schem;
149
- }
150
- }
151
- }
152
- }
153
- if (schema.parent?.members) {
154
- for (let i = schema.parent.members.length - 1; i >= 0; i--) {
155
- const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
156
- if (!replace) {
157
- members.unshift(schema.parent?.members[i]!.node);
158
- }
159
- }
160
- }
161
- }
162
-
163
- const getUnknownTypes = (type: string, types: string[] = []): string[] => {
164
- type = stripNull(type);
165
- type = this.resolveType(type, source);
166
- if (type.startsWith("Array<")) {
167
- return getUnknownTypes(type.slice(6, -1));
168
- } else if (type.startsWith("Map<")) {
169
- const parts = type.slice(4, -1).split(",");
170
- return getUnknownTypes(parts[0]) || getUnknownTypes(parts[1]);
171
- } else if (isString(type) || isPrimitive(type)) {
172
- return types;
173
- } else if (["JSON.Box", "JSON.Obj", "JSON.Value", "JSON.Raw"].includes(type)) {
174
- return types;
175
- } else if (node.isGeneric && node.typeParameters.some((p) => p.name.text == type)) {
176
- return types;
177
- } else if (type == node.name.text) {
178
- return types;
179
- }
180
- types.push(type);
181
- return types;
182
- };
183
-
184
- for (const member of members) {
185
- const type = toString(member.type);
186
- const unknown = getUnknownTypes(type);
187
-
188
- for (const unknownType of unknown) {
189
- const depSearch = schema.deps.find((v) => v.name == unknownType);
190
- if (depSearch) {
191
- if (DEBUG > 0) console.log("Found " + unknownType + " in dependencies of " + source.internalPath);
192
- if (!schema.deps.some((v) => v.name == depSearch.name)) {
193
- schema.deps.push(depSearch);
194
- }
195
- } else {
196
- const internalSearch = source.getClass(unknownType);
197
- if (internalSearch) {
198
- if (DEBUG > 0) console.log("Found " + unknownType + " internally from " + source.internalPath);
199
- if (!this.visitedClasses.has(source.getFullPath(internalSearch))) {
200
- this.visitClassDeclarationRef(internalSearch);
201
- const internalSchema = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == unknownType);
202
- // if (internalSchema.custom) mem.custom = true;
203
- schema.deps.push(internalSchema);
204
- this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
205
- this.visitClassDeclaration(node);
206
- return;
207
- }
208
- const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == unknownType);
209
- if (!schem) throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
210
- schema.deps.push(schem);
211
- } else {
212
- const externalSearch = source.getImportedClass(unknownType, this.parser);
213
- if (externalSearch) {
214
- if (DEBUG > 0) console.log("Found " + externalSearch.name.text + " externally from " + source.internalPath);
215
- const externalSource = this.sources.get(externalSearch.range.source);
216
- if (!this.visitedClasses.has(externalSource.getFullPath(externalSearch))) {
217
- this.visitClassDeclarationRef(externalSearch);
218
- const externalSchema = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == unknownType);
219
- schema.deps.push(externalSchema);
220
- this.schemas.get(externalSource.internalPath).push(this.schema);
221
- this.visitClassDeclaration(node);
222
- return;
223
- }
224
- const schem = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == unknownType);
225
- if (!schem) throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSource.internalPath);
226
- schema.deps.push(schem);
227
- }
228
- }
229
- }
230
- }
231
- }
232
-
233
- this.schemas.get(source.internalPath).push(schema);
234
- this.schema = schema;
235
- this.visitedClasses.add(fullClassPath);
236
-
237
- let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
238
- let INITIALIZE = "@inline __INITIALIZE(): this {\n";
239
- let DESERIALIZE = "__DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
240
- let DESERIALIZE_CUSTOM = "";
241
- let SERIALIZE_CUSTOM = "";
242
-
243
- if (DEBUG > 0) console.log("Created schema: " + this.schema.name + " in file " + source.normalizedPath + (this.schema.deps.length ? " with dependencies:\n " + this.schema.deps.map((v) => v.name).join("\n ") : ""));
244
-
245
- if (serializers.length > 1) throwError("Multiple serializers detected for class " + node.name.text + " but schemas can only have one serializer!", serializers[1].range);
246
- if (deserializers.length > 1) throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
247
-
248
- if (serializers.length) {
249
- this.schema.custom = true;
250
- const serializer = serializers[0];
251
- const hasCall = CustomTransform.hasCall(serializer);
252
-
253
- CustomTransform.visit(serializer);
254
-
255
- // 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);
256
- if (serializer.signature.parameters.length > 1) throwError("Found too many parameters in custom serializer for " + this.schema.name + ", but serializers can only accept one parameter of type '" + this.schema.name + "'!", serializer.signature.parameters[1].range);
257
- if (serializer.signature.parameters.length > 0 && (<NamedTypeNode>serializer.signature.parameters[0].type).name.identifier.text != node.name.text && (<NamedTypeNode>serializer.signature.parameters[0].type).name.identifier.text != "this") throwError("Type of parameter for custom serializer does not match! It should be 'string'either be 'this' or '" + this.schema.name + "'", serializer.signature.parameters[0].type.range);
258
- if (!serializer.signature.returnType || !(<NamedTypeNode>serializer.signature.returnType).name.identifier.text.includes("string")) throwError("Could not find valid return type for serializer in " + this.schema.name + "!. Set the return type to type 'string' and try again", serializer.signature.returnType.range);
259
-
260
- if (!serializer.decorators.some((v) => (<IdentifierExpression>v.name).text == "inline")) {
261
- serializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", serializer.range), null, serializer.range));
262
- }
263
- SERIALIZE_CUSTOM += " __SERIALIZE(ptr: usize): void {\n";
264
- SERIALIZE_CUSTOM += " const data = this." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "this" : "") + ");\n";
265
- if (hasCall) SERIALIZE_CUSTOM += " bs.resetState();\n";
266
- SERIALIZE_CUSTOM += " const dataSize = data.length << 1;\n";
267
- SERIALIZE_CUSTOM += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
268
- SERIALIZE_CUSTOM += " bs.offset += dataSize;\n";
269
- SERIALIZE_CUSTOM += " }\n";
270
- }
271
-
272
- if (deserializers.length) {
273
- this.schema.custom = true;
274
- const deserializer = deserializers[0];
275
- if (!deserializer.signature.parameters.length) throwError("Could not find any parameters in custom deserializer for " + this.schema.name + ". Deserializers must have one parameter like 'deserializer(data: string): " + this.schema.name + " {}'", deserializer.range);
276
- if (deserializer.signature.parameters.length > 1) throwError("Found too many parameters in custom deserializer for " + this.schema.name + ", but deserializers can only accept one parameter of type 'string'!", deserializer.signature.parameters[1].range);
277
- if ((<NamedTypeNode>deserializer.signature.parameters[0].type).name.identifier.text != "string") throwError("Type of parameter for custom deserializer does not match! It must be 'string'", deserializer.signature.parameters[0].type.range);
278
- if (!deserializer.signature.returnType || !((<NamedTypeNode>deserializer.signature.returnType).name.identifier.text.includes(this.schema.name) || (<NamedTypeNode>deserializer.signature.returnType).name.identifier.text.includes("this"))) throwError("Could not find valid return type for deserializer in " + this.schema.name + "!. Set the return type to type '" + this.schema.name + "' or 'this' and try again", deserializer.signature.returnType.range);
279
-
280
- if (!deserializer.decorators.some((v) => (<IdentifierExpression>v.name).text == "inline")) {
281
- deserializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", deserializer.range), null, deserializer.range));
282
- }
283
-
284
- DESERIALIZE_CUSTOM += " __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
285
- DESERIALIZE_CUSTOM += " return inline.always(this." + deserializer.name.text + "(JSON.Util.ptrToStr(srcStart, srcEnd)));\n";
286
- DESERIALIZE_CUSTOM += " }\n";
287
- }
288
-
289
- if (!members.length && !deserializers.length && !serializers.length) {
290
- this.generateEmptyMethods(node);
291
- return;
292
- }
293
-
294
- for (const member of members) {
295
- if (!member.type) throwError("Fields must be strongly typed", node.range);
296
- let type = toString(member.type!);
297
- type = this.resolveType(type, source);
298
-
299
- const name = member.name;
300
- const value = member.initializer ? toString(member.initializer!) : null;
301
-
302
- // if (!this.isValidType(type, node)) throwError("Invalid Type. " + type + " is not a JSON-compatible type. Either decorate it with @omit, set it to private, or remove it.", member.type.range);
303
-
304
- if (type.startsWith("(") && type.includes("=>")) continue;
305
-
306
- const mem = new Property();
307
- mem.parent = this.schema;
308
- mem.name = name.text;
309
- mem.type = type;
310
- mem.value = value;
311
- mem.node = member;
312
- mem.byteSize = sizeof(mem.type);
313
-
314
- this.schema.byteSize += mem.byteSize;
315
-
316
- if (member.decorators) {
317
- for (const decorator of member.decorators) {
318
- const decoratorName = (decorator.name as IdentifierExpression).text.toLowerCase().trim();
319
- switch (decoratorName) {
320
- case "alias": {
321
- const arg = decorator.args[0];
322
- if (!arg || arg.kind != NodeKind.Literal) throwError("@alias must have an argument of type string or number", member.range);
323
- // @ts-ignore: exists
324
- mem.alias = arg.value.toString();
325
- break;
326
- }
327
- case "omitif": {
328
- let arg = decorator.args[0];
329
- if (!decorator.args?.length) throwError("@omitif must have an argument or callback that resolves to type bool", member.range);
330
- mem.flags.set(PropertyFlags.OmitIf, arg);
331
- this.schema.static = false;
332
- break;
333
- }
334
- case "omitnull": {
335
- if (isPrimitive(type)) {
336
- throwError("@omitnull cannot be used on primitive types!", member.range);
337
- } else if (!member.type.isNullable) {
338
- throwError("@omitnull cannot be used on non-nullable types!", member.range);
339
- }
340
- mem.flags.set(PropertyFlags.OmitNull, null);
341
- this.schema.static = false;
342
- break;
343
- }
344
- }
345
- }
346
- }
347
-
348
- this.schema.members.push(mem);
349
- }
350
-
351
- if (!this.schema.static) this.schema.members = sortMembers(this.schema.members);
352
-
353
- indent = " ";
354
-
355
- if (this.schema.static == false) {
356
- if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
357
- SERIALIZE += indent + "let block: usize = 0;\n";
358
- }
359
- this.schema.byteSize += 2;
360
- SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n";
361
- SERIALIZE += indent + "bs.offset += 2;\n";
362
- }
363
-
364
- let isPure = this.schema.static;
365
- let isRegular = isPure;
366
- let isFirst = true;
367
-
368
- for (let i = 0; i < this.schema.members.length; i++) {
369
- const member = this.schema.members[i];
370
- const aliasName = JSON.stringify(member.alias || member.name);
371
- const realName = member.name;
372
- const isLast = i == this.schema.members.length - 1;
373
-
374
- if (member.value) {
375
- if (member.value != "null" && member.value != "0" && member.value != "0.0" && member.value != "false") {
376
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), ${member.value}, offsetof<this>(${JSON.stringify(member.name)}));\n`;
377
- }
378
- } else if (member.generic) {
379
- INITIALIZE += ` if (isManaged<nonnull<${member.type}>>() || isReference<nonnull<${member.type}>>()) {\n`;
380
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())), offsetof<this>(${JSON.stringify(member.name)}));\n`;
381
- INITIALIZE += ` if (isDefined(this.${member.name}.__INITIALIZE)) changetype<nonnull<${member.type}>>(this.${member.name}).__INITIALIZE();\n`;
382
- INITIALIZE += ` }\n`;
383
- } else if (!member.node.type.isNullable) {
384
- if (this.getSchema(member.type)) {
385
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
386
- } else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
387
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), [], offsetof<this>(${JSON.stringify(member.name)}));\n`;
388
- } else if (member.type == "string" || member.type == "String") {
389
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), "", offsetof<this>(${JSON.stringify(member.name)}));\n`;
390
- }
391
- }
392
-
393
- const SIMD_ENABLED = this.program.options.hasFeature(Feature.Simd);
394
- if (!isRegular && !member.flags.has(PropertyFlags.OmitIf) && !member.flags.has(PropertyFlags.OmitNull)) isRegular = true;
395
- if (isRegular && isPure) {
396
- const keyPart = (isFirst ? "{" : ",") + aliasName + ":";
397
- this.schema.byteSize += keyPart.length << 1;
398
- SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
399
- .map((v) => indent + v + "\n")
400
- .join("");
401
- SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
402
- if (isFirst) isFirst = false;
403
- } else if (isRegular && !isPure) {
404
- const keyPart = (isFirst ? "" : ",") + aliasName + ":";
405
- this.schema.byteSize += keyPart.length << 1;
406
- SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
407
- .map((v) => indent + v + "\n")
408
- .join("");
409
- SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
410
- if (isFirst) isFirst = false;
411
- } else {
412
- if (member.flags.has(PropertyFlags.OmitNull)) {
413
- SERIALIZE += indent + `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`;
414
- indentInc();
415
- const keyPart = aliasName + ":";
416
- this.schema.byteSize += keyPart.length << 1;
417
- SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
418
- .map((v) => indent + v + "\n")
419
- .join("");
420
- SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
421
-
422
- if (!isLast) {
423
- this.schema.byteSize += 2;
424
- SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
425
- SERIALIZE += indent + `bs.offset += 2;\n`;
426
- }
427
-
428
- indentDec();
429
- this.schema.byteSize += 2;
430
- SERIALIZE += indent + `}\n`;
431
- } else if (member.flags.has(PropertyFlags.OmitIf)) {
432
- if (member.flags.get(PropertyFlags.OmitIf).kind == NodeKind.Function) {
433
- const arg = member.flags.get(PropertyFlags.OmitIf) as FunctionExpression;
434
- // @ts-ignore: type
435
- arg.declaration.signature.parameters[0].type = Node.createNamedType(Node.createSimpleTypeName("this", node.range), null, false, node.range);
436
- // @ts-ignore: type
437
- arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range);
438
- SERIALIZE += indent + `if (!(${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`;
439
- } else {
440
- SERIALIZE += indent + `if (${toString(member.flags.get(PropertyFlags.OmitIf))}) {\n`;
441
- }
442
- indentInc();
443
- SERIALIZE += this.getStores(aliasName + ":", SIMD_ENABLED)
444
- .map((v) => indent + v + "\n")
445
- .join("");
446
- SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
447
-
448
- if (!isLast) {
449
- this.schema.byteSize += 2;
450
- SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
451
- SERIALIZE += indent + `bs.offset += 2;\n`;
452
- }
453
-
454
- indentDec();
455
- SERIALIZE += indent + `}\n`;
456
- }
457
- }
458
- }
459
-
460
- const sortedMembers: {
461
- string: Property[];
462
- number: Property[];
463
- boolean: Property[];
464
- null: Property[];
465
- array: Property[];
466
- object: Property[];
467
- } = {
468
- string: [],
469
- number: [],
470
- boolean: [],
471
- null: [],
472
- array: [],
473
- object: [],
474
- };
475
-
476
- for (const member of this.schema.members) {
477
- const type = stripNull(member.type);
478
- if (member.custom || member.generic) {
479
- sortedMembers.string.push(member);
480
- sortedMembers.number.push(member);
481
- sortedMembers.object.push(member);
482
- sortedMembers.array.push(member);
483
- sortedMembers.boolean.push(member);
484
- sortedMembers.null.push(member);
485
- } else {
486
- if (member.node.type.isNullable) sortedMembers.null.push(member);
487
- if (isString(type) || type == "JSON.Raw") sortedMembers.string.push(member);
488
- else if (isBoolean(type) || type.startsWith("JSON.Box<bool")) sortedMembers.boolean.push(member);
489
- else if (isPrimitive(type) || type.startsWith("JSON.Box<") || isEnum(type, this.sources.get(this.schema.node.range.source), this.parser)) sortedMembers.number.push(member);
490
- else if (isArray(type)) sortedMembers.array.push(member);
491
- /*else if (isStruct(type)) */ sortedMembers.object.push(member);
492
- // else console.warn("Could not determine type " + type + " for member " + member.name + " in class " + this.schema.name);
493
- }
494
- }
495
-
496
- indent = "";
497
-
498
- DESERIALIZE += indent + " let keyStart: usize = 0;\n";
499
- DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
500
- DESERIALIZE += indent + " let isKey = false;\n";
501
- if (!STRICT || sortedMembers.object.length || sortedMembers.array.length) DESERIALIZE += indent + " let depth: i32 = 0;\n";
502
- DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
503
-
504
- DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
505
- DESERIALIZE += indent + " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
506
- DESERIALIZE += indent + ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
507
- DESERIALIZE += indent + " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
508
- DESERIALIZE += indent + " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
509
- DESERIALIZE += indent + " srcStart += 2;\n\n";
510
-
511
- DESERIALIZE += indent + " while (srcStart < srcEnd) {\n";
512
- DESERIALIZE += indent + " let code = load<u16>(srcStart);\n";
513
- DESERIALIZE += indent + " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
514
- DESERIALIZE += indent + " if (keyStart == 0) {\n";
515
- DESERIALIZE += indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
516
- DESERIALIZE += indent + " if (isKey) {\n";
517
- DESERIALIZE += indent + " keyStart = lastIndex;\n";
518
- DESERIALIZE += indent + " keyEnd = srcStart;\n";
519
- if (DEBUG > 1) DESERIALIZE += indent + ' console.log("Key: " + JSON.Util.ptrToStr(keyStart, keyEnd));\n';
520
- DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
521
- DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
522
- DESERIALIZE += indent + " isKey = false;\n";
523
- DESERIALIZE += indent + " } else {\n";
524
- DESERIALIZE += indent + " isKey = true;\n";
525
- DESERIALIZE += indent + " lastIndex = srcStart + 2;\n";
526
- DESERIALIZE += indent + " }\n";
527
- DESERIALIZE += indent + " }\n";
528
- DESERIALIZE += indent + " srcStart += 2;\n";
529
- DESERIALIZE += indent + " } else {\n";
530
- // if (shouldGroup) DESERIALIZE += " const keySize = keyEnd - keyStart;\n";
531
-
532
- const groupMembers = (members: Property[]): Property[][] => {
533
- // const customMembers = this.schema.members.filter((m) => m.flags.has(PropertyFlags.Custom));
534
- // console.log("Custom members: ", customMembers.map((m) => m.name));
535
-
536
- // members.push(...customMembers)
537
-
538
- const groups = new Map<number, Property[]>();
539
-
540
- for (const member of members) {
541
- const name = member.alias || member.name;
542
- const length = name.length;
543
-
544
- if (!groups.has(length)) {
545
- groups.set(length, []);
546
- }
547
-
548
- groups.get(length)!.push(member);
549
- }
550
-
551
- return [...groups.values()]
552
- .map((group) =>
553
- group.sort((a, b) => {
554
- const aLen = (a.alias || a.name).length;
555
- const bLen = (b.alias || b.name).length;
556
- return aLen - bLen;
557
- }),
558
- )
559
- .sort((a, b) => b.length - a.length);
560
- };
561
-
562
- // const groupMembers = (members: Property[]): Property[][] => {
563
- // const customMembers = this.schema.members.filter((m) =>
564
- // m.flags.has(PropertyFlags.Custom)
565
- // );
566
- // console.log("Custom members: ", customMembers.map((m) => m.name));
567
-
568
- // const customSet = new Set(customMembers);
569
- // members = members.filter((m) => !customSet.has(m));
570
- // members.push(...customMembers);
571
-
572
- // const groups = new Map<number, Property[]>();
573
-
574
- // for (const member of members) {
575
- // const name = member.alias || member.name;
576
- // const length = name.length;
577
-
578
- // if (!groups.has(length)) {
579
- // groups.set(length, []);
580
- // }
581
-
582
- // groups.get(length)!.push(member);
583
- // }
584
-
585
- // return [...groups.entries()]
586
- // .sort(([a], [b]) => a - b)
587
- // .map(([_, group]) => {
588
- // const regulars = group.filter((m) => !customSet.has(m));
589
- // const customs = group.filter((m) => customSet.has(m));
590
-
591
- // const sortByLength = (a: Property, b: Property) =>
592
- // (a.alias || a.name).length - (b.alias || b.name).length;
593
-
594
- // return [...regulars.sort(sortByLength), ...customs.sort(sortByLength)];
595
- // });
596
- // };
597
-
598
- const generateGroups = (members: Property[], cb: (group: Property[]) => void, type: "string" | "array" | "object" | "number" | "boolean" | "null") => {
599
- if (!members.length) {
600
- if (STRICT) {
601
- 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';
602
- } else {
603
- if (type == "string") {
604
- DESERIALIZE += indent + " srcStart += 4;\n";
605
- } else if (type == "boolean" || type == "null" || type == "number") {
606
- DESERIALIZE += indent + " srcStart += 2;\n";
607
- }
608
-
609
- DESERIALIZE += indent + " keyStart = 0;\n";
610
- if (type == "string" || type == "object" || type == "array" || type == "number") DESERIALIZE += indent + " break;\n";
611
- }
612
- } else {
613
- const groups = groupMembers(members);
614
- DESERIALIZE += " switch (<u32>keyEnd - <u32>keyStart) {\n";
615
-
616
- for (const group of groups) {
617
- const groupLen = (group[0].alias || group[0].name).length << 1;
618
- DESERIALIZE += " case " + groupLen + ": {\n";
619
- cb(group);
620
- DESERIALIZE += "\n }\n";
621
- }
622
-
623
- DESERIALIZE += " default: {\n";
624
- if (STRICT) {
625
- 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';
626
- } else {
627
- if (type == "string") {
628
- DESERIALIZE += indent + " srcStart += 4;\n";
629
- } else if (type == "boolean" || type == "null" || type == "number") {
630
- DESERIALIZE += indent + " srcStart += 2;\n";
631
- }
632
- DESERIALIZE += indent + " keyStart = 0;\n";
633
- if (type == "string" || type == "object" || type == "array" || type == "number") DESERIALIZE += indent + " break;\n";
634
- }
635
- DESERIALIZE += " }\n";
636
- DESERIALIZE += " }\n";
637
- if (type != "null" && type != "boolean") DESERIALIZE += " break;\n";
638
- }
639
- };
640
-
641
- const generateConsts = (members: Property[]): void => {
642
- if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
643
- DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
644
- }
645
- if (members.some((m) => (m.alias || m.name).length << 1 == 4)) {
646
- DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
647
- }
648
- if (members.some((m) => (m.alias || m.name).length << 1 == 6)) {
649
- DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
650
- }
651
- if (members.some((m) => (m.alias || m.name).length << 1 == 8)) {
652
- DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
653
- }
654
- if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
655
- DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
656
- }
657
- };
658
-
659
- let mbElse = " ";
660
- if (!STRICT || sortedMembers.string.length) {
661
- // generateGroups(sortedMembers.string, generateComparisons)
662
- DESERIALIZE += mbElse + "if (code == 34) {\n";
663
- DESERIALIZE += " lastIndex = srcStart;\n";
664
- DESERIALIZE += " srcStart += 2;\n";
665
- DESERIALIZE += " while (srcStart < srcEnd) {\n";
666
- DESERIALIZE += " const code = load<u16>(srcStart);\n";
667
- DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
668
- if (DEBUG > 1) DESERIALIZE += ' console.log("Value (string, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart + 2));';
669
- generateGroups(
670
- sortedMembers.string,
671
- (group) => {
672
- generateConsts(group);
673
- const first = group[0];
674
- const fName = first.alias || first.name;
675
- DESERIALIZE += indent + " if (" + (first.generic ? "isString<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
676
- DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
677
- DESERIALIZE += indent + " srcStart += 4;\n";
678
- DESERIALIZE += indent + " keyStart = 0;\n";
679
- DESERIALIZE += indent + " break;\n";
680
- DESERIALIZE += indent + " }";
681
-
682
- for (let i = 1; i < group.length; i++) {
683
- const mem = group[i];
684
- const memName = mem.alias || mem.name;
685
- DESERIALIZE += indent + " else if (" + (mem.generic ? "isString<" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
686
- DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
687
- DESERIALIZE += indent + " srcStart += 4;\n";
688
- DESERIALIZE += indent + " keyStart = 0;\n";
689
- DESERIALIZE += indent + " break;\n";
690
- DESERIALIZE += indent + " }";
691
- }
692
-
693
- if (STRICT) {
694
- DESERIALIZE += " else {\n";
695
- 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';
696
- DESERIALIZE += indent + " }\n";
697
- } else {
698
- DESERIALIZE += " else {\n";
699
- DESERIALIZE += indent + " srcStart += 4;\n";
700
- DESERIALIZE += indent + " keyStart = 0;\n";
701
- DESERIALIZE += indent + " break;\n";
702
- DESERIALIZE += indent + " }\n";
703
- }
704
- },
705
- "string",
706
- );
707
- DESERIALIZE += " }\n"; // Close break char check
708
- DESERIALIZE += " srcStart += 2;\n";
709
- DESERIALIZE += " }\n"; // Close char scan loop
710
- DESERIALIZE += " }\n"; // Close first char check
711
- mbElse = " else ";
712
- }
713
-
714
- if (!STRICT || sortedMembers.number.length) {
715
- DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
716
- DESERIALIZE += " lastIndex = srcStart;\n";
717
- DESERIALIZE += " srcStart += 2;\n";
718
- DESERIALIZE += " while (srcStart < srcEnd) {\n";
719
- DESERIALIZE += " const code = load<u16>(srcStart);\n";
720
- DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
721
- if (DEBUG > 1) DESERIALIZE += ' console.log("Value (number, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
722
- // DESERIALIZE += " console.log(JSON.Util.ptrToStr(keyStart,keyEnd) + \" = \" + load<u16>(keyStart).toString() + \" val \" + JSON.Util.ptrToStr(lastIndex, srcStart));\n";
723
-
724
- generateGroups(
725
- sortedMembers.number,
726
- (group) => {
727
- generateConsts(group);
728
- const first = group[0];
729
- const fName = first.alias || first.name;
730
- DESERIALIZE += indent + " if (" + (first.generic ? "(isInteger<" + first.type + ">() || isFloat<" + first.type + ">()) && " : "") + getComparison(fName) + ") { // " + fName + "\n";
731
- DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
732
- DESERIALIZE += indent + " srcStart += 2;\n";
733
- DESERIALIZE += indent + " keyStart = 0;\n";
734
- DESERIALIZE += indent + " break;\n";
735
- DESERIALIZE += indent + " }";
736
-
737
- for (let i = 1; i < group.length; i++) {
738
- const mem = group[i];
739
- const memName = mem.alias || mem.name;
740
- DESERIALIZE += indent + " else if (" + (mem.generic ? "(isInteger<" + mem.type + ">() || isFloat<" + mem.type + ">()) && " : "") + getComparison(memName) + ") { // " + memName + "\n";
741
- DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
742
- DESERIALIZE += indent + " srcStart += 2;\n";
743
- DESERIALIZE += indent + " keyStart = 0;\n";
744
- DESERIALIZE += indent + " break;\n";
745
- DESERIALIZE += indent + " }";
746
- }
747
-
748
- if (STRICT) {
749
- DESERIALIZE += " else {\n";
750
- 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';
751
- DESERIALIZE += indent + " }\n";
752
- } else {
753
- DESERIALIZE += " else {\n";
754
- DESERIALIZE += indent + " srcStart += 2;\n";
755
- DESERIALIZE += indent + " keyStart = 0;\n";
756
- DESERIALIZE += indent + " break;\n";
757
- DESERIALIZE += indent + " }\n";
758
- }
759
- },
760
- "number",
761
- );
762
- DESERIALIZE += " }\n"; // Close break char check
763
- DESERIALIZE += " srcStart += 2;\n";
764
- DESERIALIZE += " }\n"; // Close char scan loop
765
- DESERIALIZE += " }"; // Close first char check
766
- mbElse = " else ";
767
- }
768
-
769
- if (!STRICT || sortedMembers.object.length) {
770
- DESERIALIZE += mbElse + "if (code == 123) {\n";
771
- DESERIALIZE += " lastIndex = srcStart;\n";
772
- DESERIALIZE += " depth++;\n";
773
- DESERIALIZE += " srcStart += 2;\n";
774
- DESERIALIZE += " while (srcStart < srcEnd) {\n";
775
- DESERIALIZE += " const code = load<u16>(srcStart);\n";
776
- DESERIALIZE += " if (code == 34) {\n";
777
- DESERIALIZE += " srcStart += 2;\n";
778
- DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
779
- DESERIALIZE += " } else if (code == 125) {\n";
780
- DESERIALIZE += " if (--depth == 0) {\n";
781
- DESERIALIZE += " srcStart += 2;\n";
782
- if (DEBUG > 1) DESERIALIZE += ' console.log("Value (object, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
783
-
784
- indent = " ";
785
- generateGroups(
786
- sortedMembers.object,
787
- (group) => {
788
- generateConsts(group);
789
- const first = group[0];
790
- const fName = first.alias || first.name;
791
- DESERIALIZE += indent + " if (" + (first.generic ? "isDefined(out.__DESERIALIZE) &&" : "") + getComparison(fName) + ") { // " + fName + "\n";
792
- DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
793
- DESERIALIZE += indent + " keyStart = 0;\n";
794
- DESERIALIZE += indent + " break;\n";
795
- DESERIALIZE += indent + " }";
796
-
797
- for (let i = 1; i < group.length; i++) {
798
- const mem = group[i];
799
- const memName = mem.alias || mem.name;
800
- DESERIALIZE += indent + " else if (" + (mem.generic ? "isDefined(out.__DESERIALIZE) &&" : "") + getComparison(memName) + ") { // " + memName + "\n";
801
- DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
802
- DESERIALIZE += indent + " keyStart = 0;\n";
803
- DESERIALIZE += indent + " break;\n";
804
- DESERIALIZE += indent + " }";
805
- }
806
-
807
- if (STRICT) {
808
- DESERIALIZE += " else {\n";
809
- 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';
810
- DESERIALIZE += indent + " }\n";
811
- } else {
812
- DESERIALIZE += " else {\n";
813
- DESERIALIZE += indent + " keyStart = 0;\n";
814
- DESERIALIZE += indent + " break;\n";
815
- DESERIALIZE += indent + " }\n";
816
- }
817
- },
818
- "object",
819
- );
820
- indent = "";
821
-
822
- DESERIALIZE += " }\n"; // Close break char check
823
- DESERIALIZE += " } else if (code == 123) depth++;\n";
824
- DESERIALIZE += " srcStart += 2;\n";
825
- DESERIALIZE += " }\n"; // Close char scan loop
826
- DESERIALIZE += " }"; // Close first char check
827
- mbElse = " else ";
828
- }
829
- if (!STRICT || sortedMembers.array.length) {
830
- DESERIALIZE += mbElse + "if (code == 91) {\n";
831
- DESERIALIZE += " lastIndex = srcStart;\n";
832
- DESERIALIZE += " depth++;\n";
833
- DESERIALIZE += " srcStart += 2;\n";
834
- DESERIALIZE += " while (srcStart < srcEnd) {\n";
835
- DESERIALIZE += " const code = load<u16>(srcStart);\n";
836
- DESERIALIZE += " if (code == 34) {\n";
837
- DESERIALIZE += " srcStart += 2;\n";
838
- DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
839
- DESERIALIZE += " } else if (code == 93) {\n";
840
- DESERIALIZE += " if (--depth == 0) {\n";
841
- DESERIALIZE += " srcStart += 2;\n";
842
- if (DEBUG > 1) DESERIALIZE += ' console.log("Value (object, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
843
-
844
- indent = " ";
845
- generateGroups(
846
- sortedMembers.array,
847
- (group) => {
848
- generateConsts(group);
849
- const first = group[0];
850
- const fName = first.alias || first.name;
851
- DESERIALIZE += indent + " if (" + (first.generic ? "isArray<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
852
- DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
853
- DESERIALIZE += indent + " keyStart = 0;\n";
854
- DESERIALIZE += indent + " break;\n";
855
- DESERIALIZE += indent + " }";
856
-
857
- for (let i = 1; i < group.length; i++) {
858
- const mem = group[i];
859
- const memName = mem.alias || mem.name;
860
- DESERIALIZE += indent + " else if (" + (mem.generic ? "isArray" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
861
- DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
862
- DESERIALIZE += indent + " keyStart = 0;\n";
863
- DESERIALIZE += indent + " break;\n";
864
- DESERIALIZE += indent + " }";
865
- }
866
-
867
- if (STRICT) {
868
- DESERIALIZE += " else {\n";
869
- 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';
870
- DESERIALIZE += indent + " }\n";
871
- } else {
872
- DESERIALIZE += " else {\n";
873
- DESERIALIZE += indent + " keyStart = 0;\n";
874
- DESERIALIZE += indent + " break;\n";
875
- DESERIALIZE += indent + " }\n";
876
- }
877
- },
878
- "array",
879
- );
880
- indent = "";
881
-
882
- DESERIALIZE += " }\n"; // Close break char check
883
- DESERIALIZE += " } else if (code == 91) depth++;\n";
884
- DESERIALIZE += " srcStart += 2;\n";
885
- DESERIALIZE += " }\n"; // Close char scan loop
886
- DESERIALIZE += " }"; // Close first char check
887
- mbElse = " else ";
888
- }
889
-
890
- if (!STRICT || sortedMembers.boolean.length) {
891
- // TRUE
892
- DESERIALIZE += mbElse + "if (code == 116) {\n";
893
-
894
- DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
895
- DESERIALIZE += " srcStart += 8;\n";
896
- if (DEBUG > 1) DESERIALIZE += ' console.log("Value (bool, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));';
897
- generateGroups(
898
- sortedMembers.boolean,
899
- (group) => {
900
- generateConsts(group);
901
- const first = group[0];
902
- const fName = first.alias || first.name;
903
- DESERIALIZE += indent + " if (" + (first.generic ? "isBoolean<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
904
- DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
905
- DESERIALIZE += indent + " srcStart += 2;\n";
906
- DESERIALIZE += indent + " keyStart = 0;\n";
907
- DESERIALIZE += indent + " break;\n";
908
- DESERIALIZE += indent + " }";
909
-
910
- for (let i = 1; i < group.length; i++) {
911
- const mem = group[i];
912
- const memName = mem.alias || mem.name;
913
- DESERIALIZE += indent + " else if (" + (mem.generic ? "isBoolean<" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
914
- DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
915
- DESERIALIZE += indent + " srcStart += 2;\n";
916
- DESERIALIZE += indent + " keyStart = 0;\n";
917
- DESERIALIZE += indent + " break;\n";
918
- DESERIALIZE += indent + " }";
919
- }
920
-
921
- if (STRICT) {
922
- DESERIALIZE += " else {\n";
923
- 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';
924
- DESERIALIZE += indent + " }\n";
925
- } else {
926
- DESERIALIZE += " else { \n";
927
- DESERIALIZE += indent + " srcStart += 2;\n";
928
- DESERIALIZE += indent + " keyStart = 0;\n";
929
- DESERIALIZE += indent + " break;\n";
930
- DESERIALIZE += indent + " }\n";
931
- }
932
- },
933
- "boolean",
934
- );
935
-
936
- DESERIALIZE += " }"; // Close first char check
937
- DESERIALIZE += " else {\n";
938
- DESERIALIZE += " throw new Error(\"Expected to find 'true' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
939
- DESERIALIZE += " }"; // Close error check
940
- DESERIALIZE += "\n }"; // Close first char check
941
-
942
- mbElse = " else ";
943
-
944
- // FALSE
945
- DESERIALIZE += mbElse + "if (code == 102) {\n";
946
-
947
- DESERIALIZE += " if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
948
- DESERIALIZE += " srcStart += 10;\n";
949
- if (DEBUG > 1) DESERIALIZE += ' console.log("Value (bool, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 10));';
950
- generateGroups(
951
- sortedMembers.boolean,
952
- (group) => {
953
- generateConsts(group);
954
-
955
- const first = group[0];
956
- const fName = first.alias || first.name;
957
- DESERIALIZE += indent + " if (" + (first.generic ? "isBoolean<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
958
- DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
959
- DESERIALIZE += indent + " srcStart += 2;\n";
960
- DESERIALIZE += indent + " keyStart = 0;\n";
961
- DESERIALIZE += indent + " break;\n";
962
- DESERIALIZE += indent + " }";
963
-
964
- for (let i = 1; i < group.length; i++) {
965
- const mem = group[i];
966
- const memName = mem.alias || mem.name;
967
- DESERIALIZE += indent + " else if (" + (mem.generic ? "isBoolean<" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
968
- DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
969
- DESERIALIZE += indent + " srcStart += 2;\n";
970
- DESERIALIZE += indent + " keyStart = 0;\n";
971
- DESERIALIZE += indent + " break;\n";
972
- DESERIALIZE += indent + " }";
973
- }
974
-
975
- if (STRICT) {
976
- DESERIALIZE += " else {\n";
977
- 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';
978
- DESERIALIZE += indent + " }\n";
979
- } else {
980
- DESERIALIZE += " else { \n";
981
- DESERIALIZE += indent + " srcStart += 2;\n";
982
- DESERIALIZE += indent + " keyStart = 0;\n";
983
- DESERIALIZE += indent + " break;\n";
984
- DESERIALIZE += indent + " }\n";
985
- }
986
- },
987
- "boolean",
988
- );
989
-
990
- DESERIALIZE += " }"; // Close first char check
991
- DESERIALIZE += " else {\n";
992
- DESERIALIZE += " throw new Error(\"Expected to find 'false' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
993
- DESERIALIZE += " }"; // Close error check
994
- DESERIALIZE += "\n }"; // Close first char check
995
-
996
- mbElse = " else ";
997
- }
998
-
999
- if (!STRICT || sortedMembers.null.length) {
1000
- DESERIALIZE += mbElse + "if (code == 110) {\n";
1001
-
1002
- DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
1003
- DESERIALIZE += " srcStart += 8;\n";
1004
- if (DEBUG > 1) DESERIALIZE += ' console.log("Value (null, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));';
1005
- generateGroups(
1006
- sortedMembers.null,
1007
- (group) => {
1008
- generateConsts(group);
1009
-
1010
- const first = group[0];
1011
- const fName = first.alias || first.name;
1012
- DESERIALIZE += indent + " if (" + (first.generic ? "isNullable<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
1013
- DESERIALIZE += indent + " store<usize>(changetype<usize>(out), 0, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1014
- DESERIALIZE += indent + " srcStart += 2;\n";
1015
- DESERIALIZE += indent + " keyStart = 0;\n";
1016
- DESERIALIZE += indent + " break;\n";
1017
- DESERIALIZE += indent + " }";
1018
-
1019
- for (let i = 1; i < group.length; i++) {
1020
- const mem = group[i];
1021
- const memName = mem.alias || mem.name;
1022
- DESERIALIZE += indent + " else if (" + (mem.generic ? "isNullable<" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
1023
- DESERIALIZE += indent + " store<usize>(changetype<usize>(out), 0, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1024
- DESERIALIZE += indent + " srcStart += 2;\n";
1025
- DESERIALIZE += indent + " keyStart = 0;\n";
1026
- DESERIALIZE += indent + " break;\n";
1027
- DESERIALIZE += indent + " }";
1028
- }
1029
-
1030
- if (STRICT) {
1031
- DESERIALIZE += " else {\n";
1032
- 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';
1033
- DESERIALIZE += indent + " }\n";
1034
- } else {
1035
- DESERIALIZE += " else { \n";
1036
- DESERIALIZE += indent + " srcStart += 2;\n";
1037
- DESERIALIZE += indent + " keyStart = 0;\n";
1038
- DESERIALIZE += indent + " break;\n";
1039
- DESERIALIZE += indent + " }\n";
1040
- }
1041
- },
1042
- "null",
1043
- );
1044
-
1045
- DESERIALIZE += " }"; // Close first char check
1046
- DESERIALIZE += "\n }"; // Close first char check
1047
-
1048
- mbElse = " else ";
1049
- }
1050
-
1051
- DESERIALIZE += " else {\n";
1052
- DESERIALIZE += " srcStart += 2;\n";
1053
- DESERIALIZE += " keyStart = 0;\n";
1054
- DESERIALIZE += "}\n";
1055
- DESERIALIZE += "\n }\n"; // Close value portion
1056
-
1057
- indentDec();
1058
- DESERIALIZE += ` }\n`; // Close while loop
1059
- indentDec();
1060
- DESERIALIZE += ` return out;\n}\n`; // Close function
1061
-
1062
- indent = " ";
1063
-
1064
- this.schema.byteSize += 2;
1065
- SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
1066
- SERIALIZE += indent + "bs.offset += 2;\n";
1067
- SERIALIZE += "}";
1068
-
1069
- SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
1070
-
1071
- INITIALIZE += " return this;\n";
1072
- INITIALIZE += "}";
1073
-
1074
- // if (DESERIALIZE_CUSTOM) {
1075
- // 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"
1076
- // }
1077
- if (DEBUG > 0) {
1078
- console.log(SERIALIZE_CUSTOM || SERIALIZE);
1079
- console.log(INITIALIZE);
1080
- console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
1081
- }
1082
-
1083
- const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM || SERIALIZE, node);
1084
- const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
1085
- const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE_CUSTOM || DESERIALIZE, node);
1086
-
1087
- if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_METHOD);
1088
- if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD);
1089
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD);
1090
- super.visitClassDeclaration(node);
1091
- }
1092
- getSchema(name: string): Schema | null {
1093
- name = stripNull(name);
1094
- return this.schemas.get(this.schema.node.range.source.internalPath).find((s) => s.name == name) || null;
1095
- }
1096
- generateEmptyMethods(node: ClassDeclaration): void {
1097
- let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
1098
- let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
1099
- let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return out;\n}";
1100
-
1101
- if (DEBUG > 0) {
1102
- console.log(SERIALIZE_EMPTY);
1103
- console.log(INITIALIZE_EMPTY);
1104
- console.log(DESERIALIZE_EMPTY);
1105
- }
1106
-
1107
- const SERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_EMPTY, node);
1108
- const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
1109
- const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
1110
-
1111
- if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_METHOD_EMPTY);
1112
- if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD_EMPTY);
1113
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD_EMPTY);
1114
- }
1115
- // visitCallExpression(node: CallExpression, ref: Node): void {
1116
- // super.visitCallExpression(node, ref);
1117
- // if (!(node.expression.kind == NodeKind.PropertyAccess && (node.expression as PropertyAccessExpression).property.text == "stringifyTo") && !(node.expression.kind == NodeKind.Identifier && (node.expression as IdentifierExpression).text == "stringifyTo")) return;
1118
-
1119
- // const source = node.range.source;
1120
-
1121
- // if (ref.kind == NodeKind.Call) {
1122
- // const newNode = Node.createBinaryExpression(Token.Equals, node.args[1], node, node.range);
1123
-
1124
- // (<CallExpression>ref).args[(<CallExpression>ref).args.indexOf(node)] = newNode;
1125
- // } else {
1126
- // const newNode = Node.createExpressionStatement(Node.createBinaryExpression(Token.Equals, node.args[1], node, node.range));
1127
-
1128
- // const nodeIndex = source.statements.findIndex((n: Node) => {
1129
- // if (n == node) return true;
1130
- // if (n.kind == NodeKind.Expression && (<ExpressionStatement>n).expression == node) return true;
1131
- // return false;
1132
- // });
1133
-
1134
- // if (nodeIndex > 0) source.statements[nodeIndex] = newNode;
1135
- // }
1136
- // }
1137
- // visitBinaryExpression(node: BinaryExpression, ref?: Node | null): void {
1138
- // // if (node.right.kind == NodeKind.Call && (<CallExpression>node).)
1139
- // }
1140
- visitImportStatement(node: ImportStatement): void {
1141
- super.visitImportStatement(node);
1142
- this.imports.push(node);
1143
- }
1144
- visitSource(node: Source): void {
1145
- this.imports = [];
1146
- super.visitSource(node);
1147
- }
1148
- addImports(node: Source): void {
1149
- // console.log("Separator: " + path.sep)
1150
- // console.log("Platform: " + process.platform)
1151
- this.baseCWD = this.baseCWD.replaceAll("/", path.sep);
1152
-
1153
- const baseDir = path.resolve(fileURLToPath(import.meta.url), "..", "..", "..");
1154
- let fromPath = node.range.source.normalizedPath.replaceAll("/", path.sep);
1155
-
1156
- const isLib = path.dirname(baseDir).endsWith("node_modules");
1157
-
1158
- if (!isLib && !this.parser.sources.some((s) => s.normalizedPath.startsWith("assembly/index"))) {
1159
- const newPath = path.join(baseDir, "assembly", "index.ts")
1160
- this.parser.parseFile(readFileSync(newPath).toString(), newPath, false);
1161
- } else if (isLib && !this.parser.sources.some((s) => s.normalizedPath.startsWith("~lib/json-as/assembly/index"))) {
1162
- const newPath = "~lib/json-as/assembly/index.ts";
1163
- this.parser.parseFile(readFileSync(path.join(baseDir, "assembly", "index.ts")).toString(), newPath, false);
1164
- }
1165
-
1166
- // console.log("baseCWD", this.baseCWD);
1167
- // console.log("baseDir", baseDir);
1168
-
1169
- fromPath = fromPath.startsWith("~lib") ? fromPath.slice(5) : path.join(this.baseCWD, fromPath);
1170
-
1171
- // console.log("fromPath", fromPath);
1172
-
1173
- const bsImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "bs" || d.name.text == "bs"));
1174
- const jsonImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "JSON" || d.name.text == "JSON"));
1175
-
1176
- let baseRel = path.posix.join(...path.relative(path.dirname(fromPath), path.join(baseDir)).split(path.sep));
1177
-
1178
- if (baseRel.endsWith("json-as")) {
1179
- baseRel = "json-as" + baseRel.slice(baseRel.indexOf("json-as") + 7);
1180
- } else if (!baseRel.startsWith(".") && !baseRel.startsWith("/") && !baseRel.startsWith("json-as")) {
1181
- baseRel = "./" + baseRel;
1182
- }
1183
-
1184
- // console.log("relPath", baseRel);
1185
-
1186
- if (!bsImport) {
1187
- const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "lib", "as-bs"), node.range), node.range);
1188
- node.range.source.statements.unshift(replaceNode);
1189
- if (DEBUG > 0) console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1190
- }
1191
-
1192
- if (!jsonImport) {
1193
- const replaceNode = Node.createImportStatement(
1194
- [Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)],
1195
- Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "index"), node.range), // Ensure POSIX-style path for 'assembly'
1196
- node.range,
1197
- );
1198
- node.range.source.statements.unshift(replaceNode);
1199
- if (DEBUG > 0) console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1200
- }
1201
- }
1202
-
1203
- getStores(data: string, simd: boolean = false): string[] {
1204
- const out: string[] = [];
1205
- const sizes = strToNum(data, simd);
1206
- let offset = 0;
1207
- for (const [size, num] of sizes) {
1208
- if (size == "v128" && simd) {
1209
- // This could be put in its own file
1210
- let index = this.simdStatements.findIndex((v) => v.includes(num));
1211
- let name = "SIMD_" + (index == -1 ? this.simdStatements.length : index);
1212
- if (index && !this.simdStatements.includes(`const ${name} = ${num};`)) this.simdStatements.push(`const ${name} = ${num};`);
1213
- out.push("store<v128>(bs.offset, " + name + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 8));
1214
- offset += 16;
1215
- }
1216
- if (size == "u64") {
1217
- out.push("store<u64>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 4));
1218
- offset += 8;
1219
- } else if (size == "u32") {
1220
- out.push("store<u32>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 2));
1221
- offset += 4;
1222
- } else if (size == "u16") {
1223
- out.push("store<u16>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 1));
1224
- offset += 2;
1225
- }
1226
- }
1227
- out.push("bs.offset += " + offset + ";");
1228
- return out;
1229
- }
1230
- isValidType(type: string, node: ClassDeclaration): boolean {
1231
- 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)];
1232
-
1233
- const baseTypes = ["Array", "Map", "Set", "JSON.Box", "Box"];
1234
-
1235
- if (node && node.isGeneric && node.typeParameters) validTypes.push(...node.typeParameters.map((v) => v.name.text));
1236
- if (type.endsWith("| null")) {
1237
- if (isPrimitive(type.slice(0, type.indexOf("| null")))) return false;
1238
- return this.isValidType(type.slice(0, type.length - 7), node);
1239
- }
1240
- if (type.includes("<")) return baseTypes.includes(type.slice(0, type.indexOf("<"))) && this.isValidType(type.slice(type.indexOf("<") + 1, type.lastIndexOf(">")), node);
1241
- if (validTypes.includes(type)) return true;
1242
- return false;
1243
- }
1244
- }
1245
-
1246
- export default class Transformer extends Transform {
1247
- afterParse(parser: Parser): void {
1248
- const transformer = JSONTransform.SN;
1249
- const sources = parser.sources
1250
- .filter((source) => {
1251
- const p = source.internalPath;
1252
- if (p.startsWith("~lib/rt") || p.startsWith("~lib/performance") || p.startsWith("~lib/wasi_") || p.startsWith("~lib/shared/")) {
1253
- return false;
1254
- }
1255
- return !isStdlib(source);
1256
- })
1257
- .sort((a, b) => {
1258
- if (a.sourceKind >= 2 && b.sourceKind <= 1) {
1259
- return -1;
1260
- } else if (a.sourceKind <= 1 && b.sourceKind >= 2) {
1261
- return 1;
1262
- } else {
1263
- return 0;
1264
- }
1265
- })
1266
- .sort((a, b) => {
1267
- if (a.sourceKind === SourceKind.UserEntry) {
1268
- return 1;
1269
- } else {
1270
- return 0;
1271
- }
1272
- });
1273
-
1274
- transformer.baseCWD = path.join(process.cwd(), this.baseDir);
1275
- transformer.program = this.program;
1276
- transformer.parser = parser;
1277
- for (const source of sources) {
1278
- transformer.imports = [];
1279
- transformer.currentSource = source;
1280
- transformer.visit(source);
1281
-
1282
- if (transformer.simdStatements.length) {
1283
- for (const simd of transformer.simdStatements) source.statements.unshift(SimpleParser.parseTopLevelStatement(simd));
1284
- }
1285
- transformer.simdStatements = [];
1286
-
1287
- if (transformer.schemas.has(source.internalPath)) {
1288
- transformer.addImports(source);
1289
- }
1290
- if (source.normalizedPath == WRITE) {
1291
- writeFileSync(path.join(process.cwd(), this.baseDir, removeExtension(source.normalizedPath) + ".tmp.ts"), toString(source));
1292
- }
1293
- }
1294
- }
1295
- }
1296
-
1297
- function sortMembers(members: Property[]): Property[] {
1298
- return members.sort((a, b) => {
1299
- const aMove = a.flags.has(PropertyFlags.OmitIf) || a.flags.has(PropertyFlags.OmitNull);
1300
- const bMove = b.flags.has(PropertyFlags.OmitIf) || b.flags.has(PropertyFlags.OmitNull);
1301
-
1302
- if (aMove && !bMove) {
1303
- return -1;
1304
- } else if (!aMove && bMove) {
1305
- return 1;
1306
- } else {
1307
- return 0;
1308
- }
1309
- });
1310
- }
1311
-
1312
- function toU16(data: string, offset: number = 0): string {
1313
- return data.charCodeAt(offset + 0).toString();
1314
- }
1315
-
1316
- function toU32(data: string, offset: number = 0): string {
1317
- return ((data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0)).toString();
1318
- }
1319
-
1320
- function toU48(data: string, offset: number = 0): string {
1321
- return ((BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
1322
- }
1323
-
1324
- function toU64(data: string, offset: number = 0): string {
1325
- return ((BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
1326
- }
1327
-
1328
- function toMemCDecl(n: number, indent: string): string {
1329
- let out = "";
1330
- let offset = 0;
1331
- let index = 0;
1332
- while (n >= 8) {
1333
- out += `${indent}const codeS${(index += 8)} = load<u64>(keyStart, ${offset});\n`;
1334
- offset += 8;
1335
- n -= 8;
1336
- }
1337
-
1338
- while (n >= 4) {
1339
- out += `${indent}const codeS${(index += 4)} = load<u32>(keyStart, ${offset});\n`;
1340
- offset += 4;
1341
- n -= 4;
1342
- }
1343
-
1344
- if (n == 1) out += `${indent}const codeS${(index += 1)} = load<u16>(keyStart, ${offset});\n`;
1345
-
1346
- return out;
1347
- }
1348
-
1349
- function toMemCCheck(data: string): string {
1350
- let n = data.length << 1;
1351
- let out = "";
1352
- let offset = 0;
1353
- let index = 0;
1354
- while (n >= 8) {
1355
- out += ` && codeS${(index += 8)} == ${toU64(data, offset >> 1)}`;
1356
- offset += 8;
1357
- n -= 8;
1358
- }
1359
-
1360
- while (n >= 4) {
1361
- out += ` && codeS${(index += 4)} == ${toU32(data, offset >> 1)}`;
1362
- offset += 4;
1363
- n -= 4;
1364
- }
1365
-
1366
- if (n == 1) out += ` && codeS${(index += 1)} == ${toU16(data, offset >> 1)}`;
1367
-
1368
- return out.slice(4);
1369
- }
1370
-
1371
- function strToNum(data: string, simd: boolean = false, offset: number = 0): string[][] {
1372
- const out: string[][] = [];
1373
- let n = data.length;
1374
-
1375
- while (n >= 8 && simd) {
1376
- out.push(["v128", "i16x8(" + data.charCodeAt(offset + 0) + ", " + data.charCodeAt(offset + 1) + ", " + data.charCodeAt(offset + 2) + ", " + data.charCodeAt(offset + 3) + ", " + data.charCodeAt(offset + 4) + ", " + data.charCodeAt(offset + 5) + ", " + data.charCodeAt(offset + 6) + ", " + data.charCodeAt(offset + 7) + ")"]);
1377
- offset += 8;
1378
- n -= 8;
1379
- }
1380
-
1381
- while (n >= 4) {
1382
- const value = (BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0));
1383
- out.push(["u64", value.toString()]);
1384
- offset += 4;
1385
- n -= 4;
1386
- }
1387
-
1388
- while (n >= 2) {
1389
- const value = (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0);
1390
- out.push(["u32", value.toString()]);
1391
- offset += 2;
1392
- n -= 2;
1393
- }
1394
-
1395
- if (n === 1) {
1396
- const value = data.charCodeAt(offset + 0);
1397
- out.push(["u16", value.toString()]);
1398
- }
1399
-
1400
- return out;
1401
- }
1402
-
1403
- function throwError(message: string, range: Range): never {
1404
- const err = new Error();
1405
- err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
1406
- throw err;
1407
- }
1408
-
1409
- function indentInc(): void {
1410
- indent += " ";
1411
- }
1412
-
1413
- function indentDec(): void {
1414
- indent = indent.slice(0, Math.max(0, indent.length - 2));
1415
- }
1416
-
1417
- function sizeof(type: string): number {
1418
- if (type == "u8")
1419
- return 6; // -127
1420
- else if (type == "i8")
1421
- return 8; // 255
1422
- else if (type == "u16")
1423
- return 10; // 65536
1424
- else if (type == "i16")
1425
- return 12; // -32767
1426
- else if (type == "u32")
1427
- return 20; // 4294967295
1428
- else if (type == "i32")
1429
- return 22; // -2147483647
1430
- else if (type == "u64")
1431
- return 40; // 18446744073709551615
1432
- else if (type == "i64")
1433
- return 40; // -9223372036854775807
1434
- else if (type == "bool" || type == "boolean") return 10;
1435
- else return 0;
1436
- }
1437
-
1438
- function isPrimitive(type: string): boolean {
1439
- const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
1440
- return primitiveTypes.some((v) => type.startsWith(v));
1441
- }
1442
-
1443
- function isBoolean(type: string): boolean {
1444
- return type == "bool" || type == "boolean";
1445
- }
1446
-
1447
- function isString(type: string) {
1448
- return stripNull(type) == "string" || stripNull(type) == "String";
1449
- }
1450
-
1451
- function isArray(type: string): boolean {
1452
- return type.startsWith("Array<");
1453
- }
1454
-
1455
- function isEnum(type: string, source: Src, parser: Parser): boolean {
1456
- return source.getEnum(type) != null || source.getImportedEnum(type, parser) != null;
1457
- }
1458
-
1459
- export function stripNull(type: string): string {
1460
- if (type.endsWith(" | null")) {
1461
- return type.slice(0, type.length - 7);
1462
- } else if (type.startsWith("null | ")) {
1463
- return type.slice(7);
1464
- }
1465
- return type;
1466
- }
1467
-
1468
- function getComparison(data: string) {
1469
- switch (data.length << 1) {
1470
- case 2: {
1471
- return "code16 == " + data.charCodeAt(0);
1472
- }
1473
- case 4: {
1474
- return "code32 == " + toU32(data);
1475
- }
1476
- case 6: {
1477
- return "code48 == " + toU48(data);
1478
- }
1479
- case 8: {
1480
- return "code64 == " + toU64(data);
1481
- }
1482
- default: {
1483
- return toMemCCheck(data);
1484
- }
1485
- }
1486
- }