json-as 0.9.18 → 0.9.20

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.
package/CHANGELOG CHANGED
@@ -26,6 +26,8 @@ v0.9.15 - Support JSON.Raw blocks
26
26
  v0.9.16 - JSON.Raw should be completely untouched
27
27
  v0.9.17 - A schema's parent's fields should be included properly
28
28
  v0.9.18 - Should be able to use @alias and @omit*** or JSON.Raw
29
+ v0.9.19 - Fix arguments in @omitif declarations not working properly
30
+ v0.9.20 - Strings were being received with quotes attached via the toString functionality. Removed that.
29
31
 
30
32
  [UNRELEASED] v1.0.0
31
33
  - Allow nullable primitives
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  __| || __|| || | | ___ | _ || __|
4
4
  | | ||__ || | || | | ||___|| ||__ |
5
5
  |_____||_____||_____||_|___| |__|__||_____|
6
- v0.9.18
6
+ v0.9.20
7
7
  </pre>
8
8
  </h5>
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.9.18",
3
+ "version": "0.9.20",
4
4
  "description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
5
5
  "types": "assembly/index.ts",
6
6
  "author": "Jairus Tanaka",
@@ -30,6 +30,7 @@
30
30
  },
31
31
  "devDependencies": {
32
32
  "@assemblyscript/wasi-shim": "^0.1.0",
33
+ "@types/node": "^20.14.12",
33
34
  "as-bench": "^0.0.0-alpha",
34
35
  "as-console": "^7.0.0",
35
36
  "as-test": "0.3.1",
@@ -1,514 +1,534 @@
1
- import {
2
- FieldDeclaration,
3
- StringLiteralExpression,
4
- } from "assemblyscript/dist/assemblyscript.js";
1
+ import { FieldDeclaration, IdentifierExpression, StringLiteralExpression, IntegerLiteralExpression, FloatLiteralExpression, NullExpression, TrueExpression, FalseExpression, } from "assemblyscript/dist/assemblyscript.js";
5
2
  import { toString, isStdlib } from "visitor-as/dist/utils.js";
6
3
  import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
7
4
  import { Transform } from "assemblyscript/dist/transform.js";
8
5
  class JSONTransform extends BaseVisitor {
9
- constructor() {
10
- super(...arguments);
11
- this.schemasList = [];
12
- this.sources = new Set();
13
- }
14
- visitMethodDeclaration() {}
15
- visitClassDeclaration(node) {
16
- if (!node.decorators?.length) return;
17
- let found = false;
18
- for (const decorator of node.decorators) {
19
- const name = decorator.name.text;
20
- if (name === "json" || name === "serializable") {
21
- found = true;
22
- break;
23
- }
6
+ constructor() {
7
+ super(...arguments);
8
+ this.schemasList = [];
9
+ this.sources = new Set();
24
10
  }
25
- if (!found) return;
26
- const schema = new SchemaData();
27
- schema.node = node;
28
- schema.name = node.name.text;
29
- const members = [
30
- ...node.members.filter(
31
- (v) => v.kind === 54 /* NodeKind.FieldDeclaration */,
32
- ),
33
- ];
34
- if (node.extendsType) {
35
- schema.parent = this.schemasList.find(
36
- (v) => v.name == node.extendsType?.name.identifier.text,
37
- );
38
- if (schema.parent?.members) {
39
- for (let i = schema.parent.members.length - 1; i >= 0; i--) {
40
- const replace = schema.members.find(
41
- (v) => v.name == schema.parent?.members[i]?.name,
42
- );
43
- if (!replace) {
44
- members.unshift(schema.parent?.members[i].node);
45
- }
11
+ visitMethodDeclaration() { }
12
+ visitClassDeclaration(node) {
13
+ if (!node.decorators?.length)
14
+ return;
15
+ let found = false;
16
+ for (const decorator of node.decorators) {
17
+ const name = decorator.name.text;
18
+ if (name === "json" || name === "serializable") {
19
+ found = true;
20
+ break;
21
+ }
46
22
  }
47
- }
48
- }
49
- if (!members.length) {
50
- let SERIALIZE_RAW_EMPTY = '__SERIALIZE(): string {\n return "{}";\n}';
51
- //let SERIALIZE_PRETTY_EMPTY = "__SERIALIZE_PRETTY(): string {\n return \"{}\";\n}";
52
- let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
53
- let DESERIALIZE_EMPTY =
54
- "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
55
- if (process.env["JSON_DEBUG"]) {
56
- console.log(SERIALIZE_RAW_EMPTY);
57
- //console.log(SERIALIZE_PRETTY_EMPTY);
58
- console.log(INITIALIZE_EMPTY);
59
- console.log(DESERIALIZE_EMPTY);
60
- }
61
- const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(
62
- SERIALIZE_RAW_EMPTY,
63
- node,
64
- );
65
- //const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
66
- const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
67
- INITIALIZE_EMPTY,
68
- node,
69
- );
70
- const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
71
- DESERIALIZE_EMPTY,
72
- node,
73
- );
74
- if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
75
- node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
76
- if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
77
- node.members.push(INITIALIZE_METHOD_EMPTY);
78
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
79
- node.members.push(DESERIALIZE_METHOD_EMPTY);
80
- this.schemasList.push(schema);
81
- }
82
- for (const member of members) {
83
- const name = member.name;
84
- if (!(member instanceof FieldDeclaration)) continue;
85
- if (!member.type) {
86
- throw new Error(
87
- "Fields must be strongly typed! Found " +
88
- toString(member) +
89
- " at " +
90
- node.range.source.normalizedPath,
91
- );
92
- }
93
- const type = toString(member.type);
94
- if (type.startsWith("(") && type.includes("=>")) continue;
95
- const value = member.initializer ? toString(member.initializer) : null;
96
- if (member.flags == 32 /* CommonFlags.Static */) continue;
97
- if (member.flags === 512 /* CommonFlags.Private */) continue;
98
- if (member.flags === 1024 /* CommonFlags.Protected */) continue;
99
- const mem = new Property();
100
- mem.name = name.text;
101
- mem.type = type;
102
- mem.value = value;
103
- mem.node = member;
104
- if (type == "JSON.Raw") {
105
- mem.flags.set(PropertyFlags.JSON_Raw, []);
106
- }
107
- if (member.decorators) {
108
- for (const decorator of member.decorators) {
109
- const decoratorName = decorator.name.text;
110
- const args = getArgs(decorator.args);
111
- switch (decoratorName) {
112
- case "alias": {
113
- if (!args.length)
114
- throw new Error(
115
- "Expected 1 argument but got zero at @alias in " +
116
- node.range.source.normalizedPath,
117
- );
118
- mem.alias = args[0];
119
- mem.flags.set(PropertyFlags.Alias, args);
120
- break;
121
- }
122
- case "omit": {
123
- mem.flags.set(PropertyFlags.Omit, args);
124
- break;
125
- }
126
- case "omitif": {
127
- if (!decorator.args?.length)
128
- throw new Error(
129
- "Expected 1 argument but got zero at @omitif in " +
130
- node.range.source.normalizedPath,
131
- );
132
- mem.flags.set(PropertyFlags.OmitIf, args);
133
- break;
134
- }
135
- case "omitnull": {
136
- mem.flags.set(PropertyFlags.OmitNull, args);
137
- break;
138
- }
139
- }
23
+ if (!found)
24
+ return;
25
+ const schema = new SchemaData();
26
+ schema.node = node;
27
+ schema.name = node.name.text;
28
+ const members = [
29
+ ...node.members.filter((v) => v.kind === 54 /* NodeKind.FieldDeclaration */),
30
+ ];
31
+ if (node.extendsType) {
32
+ schema.parent = this.schemasList.find((v) => v.name == node.extendsType?.name.identifier.text);
33
+ if (schema.parent?.members) {
34
+ for (let i = schema.parent.members.length - 1; i >= 0; i--) {
35
+ const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
36
+ if (!replace) {
37
+ members.unshift(schema.parent?.members[i].node);
38
+ }
39
+ }
40
+ }
140
41
  }
141
- }
142
- mem.generate();
143
- if (this.schemasList.find((v) => v.name == type)) {
144
- mem.initialize =
145
- "this." +
146
- name.text +
147
- " = changetype<nonnull<" +
148
- mem.type +
149
- ">>(__new(offsetof<nonnull<" +
150
- mem.type +
151
- ">>(), idof<nonnull<" +
152
- mem.type +
153
- ">>()));\n changetype<nonnull<" +
154
- mem.type +
155
- ">>(this." +
156
- name.text +
157
- ").__INITIALIZE()";
158
- } else if (mem.value) {
159
- mem.initialize = "this." + name.text + " = " + mem.value;
160
- } else if (type === "Map") {
161
- mem.initialize = "this." + name.text + " = new " + mem.type + "()";
162
- } else if (type === "string") {
163
- mem.initialize = "this." + name.text + ' = ""';
164
- } else if (type === "Array") {
165
- mem.initialize =
166
- "this." + name.text + " = instantiate<" + mem.type + ">()";
167
- } else if (type === "bool" || type === "boolean") {
168
- mem.initialize = "this." + name.text + " = false";
169
- } else if (type === "JSON.Raw") {
170
- mem.initialize = "this." + name.text + ' = ""';
171
- } else if (
172
- type === "u8" ||
173
- type === "u16" ||
174
- type === "u32" ||
175
- type === "u64" ||
176
- type === "i8" ||
177
- type === "i16" ||
178
- type === "i32" ||
179
- type === "i64"
180
- ) {
181
- mem.initialize = "this." + name.text + " = 0";
182
- } else if (type === "f32" || type === "f64") {
183
- mem.initialize = "this." + name.text + " = 0.0";
184
- }
185
- schema.members.push(mem);
186
- }
187
- let SERIALIZE_RAW = "__SERIALIZE(): string {\n let out = `{";
188
- let SERIALIZE_PRETTY = "__SERIALIZE_PRETTY(): string {\n let out = `{";
189
- let INITIALIZE = "__INITIALIZE(): this {\n";
190
- let DESERIALIZE =
191
- "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n const len = key_end - key_start;\n";
192
- let indent = " ";
193
- if (!schema.members.length) return;
194
- found = false;
195
- if (
196
- schema.members[0]?.flags.has(PropertyFlags.OmitNull) ||
197
- schema.members[0]?.flags.has(PropertyFlags.OmitIf)
198
- ) {
199
- SERIALIZE_RAW += schema.members[0]?.serialize;
200
- SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
201
- } else {
202
- SERIALIZE_RAW += schema.members[0]?.serialize + ",";
203
- SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize + ",\\n";
204
- found = true;
205
- }
206
- if (schema.members[0]?.initialize)
207
- INITIALIZE += " " + schema.members[0]?.initialize + ";\n";
208
- for (let i = 1; i < schema.members.length; i++) {
209
- const member = schema.members[i];
210
- if (member.initialize) INITIALIZE += " " + member.initialize + ";\n";
211
- if (
212
- member.flags.has(PropertyFlags.OmitNull) ||
213
- member.flags.has(PropertyFlags.OmitIf)
214
- ) {
215
- SERIALIZE_RAW += member.serialize;
216
- SERIALIZE_PRETTY += member.serialize;
217
- } else {
218
- SERIALIZE_RAW += member.serialize + ",";
219
- SERIALIZE_PRETTY += indent + member.serialize + ",\\n";
220
- found = true;
221
- }
222
- }
223
- if (found) {
224
- SERIALIZE_RAW +=
225
- "`;\n store<u16>(changetype<usize>(out) + ((out.length - 1) << 1), 125);\n return out;\n}";
226
- SERIALIZE_PRETTY +=
227
- "`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
228
- } else {
229
- SERIALIZE_RAW += "`;\n};";
230
- SERIALIZE_PRETTY += "`;\n};";
231
- }
232
- INITIALIZE += " return this;\n}";
233
- const sortedMembers = [];
234
- const _sorted = schema.members.sort(
235
- (a, b) => a.name.length - b.name.length,
236
- );
237
- let len = 0;
238
- let offset = 0;
239
- sortedMembers.push([_sorted[0]]);
240
- len = _sorted[0]?.name.length;
241
- for (let i = 1; i < _sorted.length; i++) {
242
- const member = _sorted[i];
243
- if (member.alias?.length || member.name.length > len) {
244
- sortedMembers.push([member]);
245
- len = member.alias?.length || member.name.length;
246
- offset++;
247
- } else {
248
- sortedMembers[offset].push(member);
249
- }
250
- }
251
- let first = true;
252
- for (const memberSet of sortedMembers) {
253
- const firstMember = memberSet[0];
254
- const name = encodeKey(firstMember.alias || firstMember.name);
255
- if (name.length === 1) {
256
- if (first) {
257
- DESERIALIZE +=
258
- " if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
259
- first = false;
260
- } else {
261
- DESERIALIZE +=
262
- "else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
42
+ if (!members.length) {
43
+ let SERIALIZE_RAW_EMPTY = '__SERIALIZE(): string {\n return "{}";\n}';
44
+ //let SERIALIZE_PRETTY_EMPTY = "__SERIALIZE_PRETTY(): string {\n return \"{}\";\n}";
45
+ let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
46
+ let DESERIALIZE_EMPTY = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
47
+ if (process.env["JSON_DEBUG"]) {
48
+ console.log(SERIALIZE_RAW_EMPTY);
49
+ //console.log(SERIALIZE_PRETTY_EMPTY);
50
+ console.log(INITIALIZE_EMPTY);
51
+ console.log(DESERIALIZE_EMPTY);
52
+ }
53
+ const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node);
54
+ //const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
55
+ const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
56
+ const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
57
+ if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
58
+ node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
59
+ if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
60
+ node.members.push(INITIALIZE_METHOD_EMPTY);
61
+ if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
62
+ node.members.push(DESERIALIZE_METHOD_EMPTY);
63
+ this.schemasList.push(schema);
263
64
  }
264
- } else if (name.length === 2) {
265
- if (first) {
266
- DESERIALIZE +=
267
- " if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
268
- first = false;
269
- } else {
270
- DESERIALIZE +=
271
- "else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
65
+ for (const member of members) {
66
+ const name = member.name;
67
+ if (!(member instanceof FieldDeclaration))
68
+ continue;
69
+ if (!member.type) {
70
+ throw new Error("Fields must be strongly typed! Found " +
71
+ toString(member) +
72
+ " at " +
73
+ node.range.source.normalizedPath);
74
+ }
75
+ const type = toString(member.type);
76
+ if (type.startsWith("(") && type.includes("=>"))
77
+ continue;
78
+ const value = member.initializer ? toString(member.initializer) : null;
79
+ if (member.flags == 32 /* CommonFlags.Static */)
80
+ continue;
81
+ if (member.flags === 512 /* CommonFlags.Private */)
82
+ continue;
83
+ if (member.flags === 1024 /* CommonFlags.Protected */)
84
+ continue;
85
+ const mem = new Property();
86
+ mem.name = name.text;
87
+ mem.type = type;
88
+ mem.value = value;
89
+ mem.node = member;
90
+ if (type == "JSON.Raw") {
91
+ mem.flags.set(PropertyFlags.JSON_Raw, []);
92
+ }
93
+ if (member.decorators) {
94
+ for (const decorator of member.decorators) {
95
+ const decoratorName = decorator.name.text;
96
+ const args = getArgs(decorator.args);
97
+ switch (decoratorName) {
98
+ case "alias": {
99
+ if (!args.length)
100
+ throw new Error("Expected 1 argument but got zero at @alias in " +
101
+ node.range.source.normalizedPath);
102
+ mem.alias = args[0];
103
+ mem.flags.set(PropertyFlags.Alias, args);
104
+ break;
105
+ }
106
+ case "omit": {
107
+ mem.flags.set(PropertyFlags.Omit, args);
108
+ break;
109
+ }
110
+ case "omitif": {
111
+ if (!decorator.args?.length)
112
+ throw new Error("Expected 1 argument but got zero at @omitif in " +
113
+ node.range.source.normalizedPath);
114
+ mem.flags.set(PropertyFlags.OmitIf, args);
115
+ break;
116
+ }
117
+ case "omitnull": {
118
+ mem.flags.set(PropertyFlags.OmitNull, args);
119
+ break;
120
+ }
121
+ }
122
+ }
123
+ }
124
+ mem.generate();
125
+ if (this.schemasList.find((v) => v.name == type)) {
126
+ mem.initialize =
127
+ "this." +
128
+ name.text +
129
+ " = changetype<nonnull<" +
130
+ mem.type +
131
+ ">>(__new(offsetof<nonnull<" +
132
+ mem.type +
133
+ ">>(), idof<nonnull<" +
134
+ mem.type +
135
+ ">>()));\n changetype<nonnull<" +
136
+ mem.type +
137
+ ">>(this." +
138
+ name.text +
139
+ ").__INITIALIZE()";
140
+ }
141
+ else if (mem.value) {
142
+ mem.initialize = "this." + name.text + " = " + mem.value;
143
+ }
144
+ else if (type === "Map") {
145
+ mem.initialize = "this." + name.text + " = new " + mem.type + "()";
146
+ }
147
+ else if (type === "string") {
148
+ mem.initialize = "this." + name.text + ' = ""';
149
+ }
150
+ else if (type === "Array") {
151
+ mem.initialize =
152
+ "this." + name.text + " = instantiate<" + mem.type + ">()";
153
+ }
154
+ else if (type === "bool" || type === "boolean") {
155
+ mem.initialize = "this." + name.text + " = false";
156
+ }
157
+ else if (type === "JSON.Raw") {
158
+ mem.initialize = "this." + name.text + ' = ""';
159
+ }
160
+ else if (type === "u8" ||
161
+ type === "u16" ||
162
+ type === "u32" ||
163
+ type === "u64" ||
164
+ type === "i8" ||
165
+ type === "i16" ||
166
+ type === "i32" ||
167
+ type === "i64") {
168
+ mem.initialize = "this." + name.text + " = 0";
169
+ }
170
+ else if (type === "f32" || type === "f64") {
171
+ mem.initialize = "this." + name.text + " = 0.0";
172
+ }
173
+ schema.members.push(mem);
272
174
  }
273
- } else if (name.length === 4) {
274
- if (first) {
275
- DESERIALIZE +=
276
- " if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
277
- first = false;
278
- } else {
279
- DESERIALIZE +=
280
- "else if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
175
+ let SERIALIZE_RAW = "__SERIALIZE(): string {\n let out = `{";
176
+ let SERIALIZE_PRETTY = "__SERIALIZE_PRETTY(): string {\n let out = `{";
177
+ let INITIALIZE = "__INITIALIZE(): this {\n";
178
+ let DESERIALIZE = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n const len = key_end - key_start;\n";
179
+ let indent = " ";
180
+ if (!schema.members.length)
181
+ return;
182
+ found = false;
183
+ if (schema.members[0]?.flags.has(PropertyFlags.OmitNull) ||
184
+ schema.members[0]?.flags.has(PropertyFlags.OmitIf)) {
185
+ SERIALIZE_RAW += schema.members[0]?.serialize;
186
+ SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
281
187
  }
282
- } else {
283
- if (first) {
284
- DESERIALIZE += " if (" + name.length + " === len) {\n";
285
- first = false;
286
- } else {
287
- DESERIALIZE += "else if (" + name.length + " === len) {\n";
188
+ else {
189
+ SERIALIZE_RAW += schema.members[0]?.serialize + ",";
190
+ SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize + ",\\n";
191
+ found = true;
288
192
  }
289
- }
290
- let f = true;
291
- for (let i = 0; i < memberSet.length; i++) {
292
- const member = memberSet[i];
293
- if (!member.deserialize) continue;
294
- const name = encodeKey(member.alias || member.name);
295
- if (name.length === 1) {
296
- DESERIALIZE += ` case ${name.charCodeAt(0)}: {\n ${member.deserialize}\n return true;\n }\n`;
297
- } else if (name.length === 2) {
298
- DESERIALIZE += ` case ${charCodeAt32(name, 0)}: {\n ${member.deserialize}\n return true;\n }\n`;
299
- } else if (name.length === 4) {
300
- if (f) {
301
- f = false;
302
- DESERIALIZE += ` if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
303
- } else {
304
- DESERIALIZE =
305
- DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
306
- `else if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
307
- }
308
- } else {
309
- if (f) {
310
- f = false;
311
- DESERIALIZE += ` if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
312
- } else {
313
- DESERIALIZE =
314
- DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
315
- ` else if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
316
- }
193
+ if (schema.members[0]?.initialize)
194
+ INITIALIZE += " " + schema.members[0]?.initialize + ";\n";
195
+ for (let i = 1; i < schema.members.length; i++) {
196
+ const member = schema.members[i];
197
+ if (member.initialize)
198
+ INITIALIZE += " " + member.initialize + ";\n";
199
+ if (member.flags.has(PropertyFlags.OmitNull) ||
200
+ member.flags.has(PropertyFlags.OmitIf)) {
201
+ SERIALIZE_RAW += member.serialize;
202
+ SERIALIZE_PRETTY += member.serialize;
203
+ }
204
+ else {
205
+ SERIALIZE_RAW += member.serialize + ",";
206
+ SERIALIZE_PRETTY += indent + member.serialize + ",\\n";
207
+ found = true;
208
+ }
317
209
  }
318
- }
319
- if (name.length < 3) {
320
- DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
321
- } else if (name.length == 4) {
322
- DESERIALIZE =
323
- DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
324
- ` else {\n return false;\n }\n`;
325
- } else {
326
- DESERIALIZE =
327
- DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
328
- ` else {\n return false;\n }\n`;
329
- }
330
- DESERIALIZE += " } ";
331
- }
332
- DESERIALIZE += "\n return false;\n}";
333
- //console.log(sortedMembers);
334
- if (process.env["JSON_DEBUG"]) {
335
- console.log(SERIALIZE_RAW);
336
- //console.log(SERIALIZE_PRETTY);
337
- console.log(INITIALIZE);
338
- console.log(DESERIALIZE);
210
+ if (found) {
211
+ SERIALIZE_RAW +=
212
+ "`;\n store<u16>(changetype<usize>(out) + ((out.length - 1) << 1), 125);\n return out;\n}";
213
+ SERIALIZE_PRETTY +=
214
+ "`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
215
+ }
216
+ else {
217
+ SERIALIZE_RAW += "`;\n};";
218
+ SERIALIZE_PRETTY += "`;\n};";
219
+ }
220
+ INITIALIZE += " return this;\n}";
221
+ const sortedMembers = [];
222
+ const _sorted = schema.members.sort((a, b) => a.name.length - b.name.length);
223
+ let len = 0;
224
+ let offset = 0;
225
+ sortedMembers.push([_sorted[0]]);
226
+ len = _sorted[0]?.name.length;
227
+ for (let i = 1; i < _sorted.length; i++) {
228
+ const member = _sorted[i];
229
+ if (member.alias?.length || member.name.length > len) {
230
+ sortedMembers.push([member]);
231
+ len = member.alias?.length || member.name.length;
232
+ offset++;
233
+ }
234
+ else {
235
+ sortedMembers[offset].push(member);
236
+ }
237
+ }
238
+ let first = true;
239
+ for (const memberSet of sortedMembers) {
240
+ const firstMember = memberSet[0];
241
+ const name = encodeKey(firstMember.alias || firstMember.name);
242
+ if (name.length === 1) {
243
+ if (first) {
244
+ DESERIALIZE +=
245
+ " if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
246
+ first = false;
247
+ }
248
+ else {
249
+ DESERIALIZE +=
250
+ "else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
251
+ }
252
+ }
253
+ else if (name.length === 2) {
254
+ if (first) {
255
+ DESERIALIZE +=
256
+ " if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
257
+ first = false;
258
+ }
259
+ else {
260
+ DESERIALIZE +=
261
+ "else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
262
+ }
263
+ }
264
+ else if (name.length === 4) {
265
+ if (first) {
266
+ DESERIALIZE +=
267
+ " if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
268
+ first = false;
269
+ }
270
+ else {
271
+ DESERIALIZE +=
272
+ "else if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
273
+ }
274
+ }
275
+ else {
276
+ if (first) {
277
+ DESERIALIZE += " if (" + name.length + " === len) {\n";
278
+ first = false;
279
+ }
280
+ else {
281
+ DESERIALIZE += "else if (" + name.length + " === len) {\n";
282
+ }
283
+ }
284
+ let f = true;
285
+ for (let i = 0; i < memberSet.length; i++) {
286
+ const member = memberSet[i];
287
+ if (!member.deserialize)
288
+ continue;
289
+ const name = encodeKey(member.alias || member.name);
290
+ if (name.length === 1) {
291
+ DESERIALIZE += ` case ${name.charCodeAt(0)}: {\n ${member.deserialize}\n return true;\n }\n`;
292
+ }
293
+ else if (name.length === 2) {
294
+ DESERIALIZE += ` case ${charCodeAt32(name, 0)}: {\n ${member.deserialize}\n return true;\n }\n`;
295
+ }
296
+ else if (name.length === 4) {
297
+ if (f) {
298
+ f = false;
299
+ DESERIALIZE += ` if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
300
+ }
301
+ else {
302
+ DESERIALIZE =
303
+ DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
304
+ `else if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
305
+ }
306
+ }
307
+ else {
308
+ if (f) {
309
+ f = false;
310
+ DESERIALIZE += ` if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
311
+ }
312
+ else {
313
+ DESERIALIZE =
314
+ DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
315
+ ` else if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
316
+ }
317
+ }
318
+ }
319
+ if (name.length < 3) {
320
+ DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
321
+ }
322
+ else if (name.length == 4) {
323
+ DESERIALIZE =
324
+ DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
325
+ ` else {\n return false;\n }\n`;
326
+ }
327
+ else {
328
+ DESERIALIZE =
329
+ DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
330
+ ` else {\n return false;\n }\n`;
331
+ }
332
+ DESERIALIZE += " } ";
333
+ }
334
+ DESERIALIZE += "\n return false;\n}";
335
+ //console.log(sortedMembers);
336
+ if (process.env["JSON_DEBUG"]) {
337
+ console.log(SERIALIZE_RAW);
338
+ //console.log(SERIALIZE_PRETTY);
339
+ console.log(INITIALIZE);
340
+ console.log(DESERIALIZE);
341
+ }
342
+ const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(SERIALIZE_RAW, node);
343
+ //const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
344
+ const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
345
+ const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
346
+ if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
347
+ node.members.push(SERIALIZE_RAW_METHOD);
348
+ if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
349
+ node.members.push(INITIALIZE_METHOD);
350
+ if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
351
+ node.members.push(DESERIALIZE_METHOD);
352
+ this.schemasList.push(schema);
339
353
  }
340
- const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(
341
- SERIALIZE_RAW,
342
- node,
343
- );
344
- //const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
345
- const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
346
- const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
347
- if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
348
- node.members.push(SERIALIZE_RAW_METHOD);
349
- if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
350
- node.members.push(INITIALIZE_METHOD);
351
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
352
- node.members.push(DESERIALIZE_METHOD);
353
- this.schemasList.push(schema);
354
- }
355
- visitSource(node) {
356
- super.visitSource(node);
357
- // Only add the import statement to sources that have JSON decorated classes.
358
- if (!this.sources.has(node)) {
359
- return;
354
+ visitSource(node) {
355
+ super.visitSource(node);
356
+ // Only add the import statement to sources that have JSON decorated classes.
357
+ if (!this.sources.has(node)) {
358
+ return;
359
+ }
360
360
  }
361
- }
362
361
  }
363
362
  export default class Transformer extends Transform {
364
- // Trigger the transform after parse.
365
- afterParse(parser) {
366
- // Create new transform
367
- const transformer = new JSONTransform();
368
- // Sort the sources so that user scripts are visited last
369
- const sources = parser.sources
370
- .filter((source) => !isStdlib(source))
371
- .sort((_a, _b) => {
372
- const a = _a.internalPath;
373
- const b = _b.internalPath;
374
- if (a[0] === "~" && b[0] !== "~") {
375
- return -1;
376
- } else if (a[0] !== "~" && b[0] === "~") {
377
- return 1;
378
- } else {
379
- return 0;
363
+ // Trigger the transform after parse.
364
+ afterParse(parser) {
365
+ // Create new transform
366
+ const transformer = new JSONTransform();
367
+ // Sort the sources so that user scripts are visited last
368
+ const sources = parser.sources
369
+ .filter((source) => !isStdlib(source))
370
+ .sort((_a, _b) => {
371
+ const a = _a.internalPath;
372
+ const b = _b.internalPath;
373
+ if (a[0] === "~" && b[0] !== "~") {
374
+ return -1;
375
+ }
376
+ else if (a[0] !== "~" && b[0] === "~") {
377
+ return 1;
378
+ }
379
+ else {
380
+ return 0;
381
+ }
382
+ });
383
+ // Loop over every source
384
+ for (const source of sources) {
385
+ // Ignore all lib and std. Visit everything else.
386
+ if (!isStdlib(source)) {
387
+ transformer.visit(source);
388
+ }
389
+ }
390
+ // Check that every parent and child class is hooked up correctly
391
+ const schemas = transformer.schemasList;
392
+ for (const schema of schemas) {
393
+ if (schema.parent) {
394
+ const parent = schemas.find((v) => v.name === schema.parent?.name);
395
+ if (!parent)
396
+ throw new Error(`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator! Add the decorator and rebuild.`);
397
+ }
380
398
  }
381
- });
382
- // Loop over every source
383
- for (const source of sources) {
384
- // Ignore all lib and std. Visit everything else.
385
- if (!isStdlib(source)) {
386
- transformer.visit(source);
387
- }
388
- }
389
- // Check that every parent and child class is hooked up correctly
390
- const schemas = transformer.schemasList;
391
- for (const schema of schemas) {
392
- if (schema.parent) {
393
- const parent = schemas.find((v) => v.name === schema.parent?.name);
394
- if (!parent)
395
- throw new Error(
396
- `Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator! Add the decorator and rebuild.`,
397
- );
398
- }
399
399
  }
400
- }
401
400
  }
402
401
  var PropertyFlags;
403
402
  (function (PropertyFlags) {
404
- PropertyFlags[(PropertyFlags["Omit"] = 0)] = "Omit";
405
- PropertyFlags[(PropertyFlags["OmitNull"] = 1)] = "OmitNull";
406
- PropertyFlags[(PropertyFlags["OmitIf"] = 2)] = "OmitIf";
407
- PropertyFlags[(PropertyFlags["Alias"] = 3)] = "Alias";
408
- PropertyFlags[(PropertyFlags["JSON_Raw"] = 4)] = "JSON_Raw";
403
+ PropertyFlags[PropertyFlags["Omit"] = 0] = "Omit";
404
+ PropertyFlags[PropertyFlags["OmitNull"] = 1] = "OmitNull";
405
+ PropertyFlags[PropertyFlags["OmitIf"] = 2] = "OmitIf";
406
+ PropertyFlags[PropertyFlags["Alias"] = 3] = "Alias";
407
+ PropertyFlags[PropertyFlags["JSON_Raw"] = 4] = "JSON_Raw";
409
408
  })(PropertyFlags || (PropertyFlags = {}));
410
409
  class Property {
411
- constructor() {
412
- this.name = "";
413
- this.alias = null;
414
- this.type = "";
415
- this.value = null;
416
- this.flags = new Map();
417
- this.args = [];
418
- this.serialize = null;
419
- this.deserialize = null;
420
- this.initialize = null;
421
- this.right_s = "";
422
- this.right_d = "";
423
- }
424
- generate() {
425
- const name = this.name;
426
- const escapedName = escapeString(JSON.stringify(this.alias || this.name));
427
- const type = this.type;
428
- if (this.flags.has(PropertyFlags.Omit)) return;
429
- if (this.flags.has(PropertyFlags.JSON_Raw)) {
430
- this.right_s = "this." + name;
431
- this.right_d = "data.substring(value_start, value_end);";
432
- } else {
433
- this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")";
434
- this.right_d =
435
- "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end))";
410
+ constructor() {
411
+ this.name = "";
412
+ this.alias = null;
413
+ this.type = "";
414
+ this.value = null;
415
+ this.flags = new Map();
416
+ this.serialize = null;
417
+ this.deserialize = null;
418
+ this.initialize = null;
419
+ this.right_s = "";
420
+ this.right_d = "";
436
421
  }
437
- if (this.flags.has(PropertyFlags.OmitIf)) {
438
- const condition = this.args[0];
439
- this.serialize =
440
- "${" +
441
- condition +
442
- ' ? "" : \'' +
443
- escapedName +
444
- ":' + " +
445
- this.right_s +
446
- ' + ","}';
447
- this.deserialize = "this." + name + " = " + this.right_d + ";";
448
- } else if (this.flags.has(PropertyFlags.OmitNull)) {
449
- this.serialize =
450
- "${changetype<usize>(this." +
451
- name +
452
- ") == <usize>0" +
453
- ' ? "" : \'' +
454
- escapedName +
455
- ":' + " +
456
- this.right_s +
457
- ' + ","}';
458
- this.deserialize = "this." + name + " = " + this.right_d + ";";
459
- } else {
460
- this.serialize = escapedName + ":${" + this.right_s + "}";
461
- this.deserialize = "this." + name + " = " + this.right_d + ";";
422
+ generate() {
423
+ const name = this.name;
424
+ const escapedName = escapeString(JSON.stringify(this.alias || this.name));
425
+ const type = this.type;
426
+ if (this.flags.has(PropertyFlags.Omit))
427
+ return;
428
+ if (this.flags.has(PropertyFlags.JSON_Raw)) {
429
+ this.right_s = "this." + name;
430
+ this.right_d = "data.substring(value_start, value_end);";
431
+ }
432
+ else {
433
+ this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")";
434
+ this.right_d =
435
+ "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end))";
436
+ }
437
+ if (this.flags.has(PropertyFlags.OmitIf)) {
438
+ const condition = this.flags.get(PropertyFlags.OmitIf)[0];
439
+ if (!condition)
440
+ throw new Error("Could not find condition when using decorator @omitif! Provide at least one condition");
441
+ this.serialize =
442
+ "${" +
443
+ condition +
444
+ ' ? "" : \'' +
445
+ escapedName +
446
+ ":' + " +
447
+ this.right_s +
448
+ ' + ","}';
449
+ this.deserialize = "this." + name + " = " + this.right_d + ";";
450
+ }
451
+ else if (this.flags.has(PropertyFlags.OmitNull)) {
452
+ this.serialize =
453
+ "${changetype<usize>(this." +
454
+ name +
455
+ ") == <usize>0" +
456
+ ' ? "" : \'' +
457
+ escapedName +
458
+ ":' + " +
459
+ this.right_s +
460
+ ' + ","}';
461
+ this.deserialize = "this." + name + " = " + this.right_d + ";";
462
+ }
463
+ else {
464
+ this.serialize = escapedName + ":${" + this.right_s + "}";
465
+ this.deserialize = "this." + name + " = " + this.right_d + ";";
466
+ }
462
467
  }
463
- }
464
468
  }
465
469
  class SchemaData {
466
- constructor() {
467
- this.name = "";
468
- this.members = [];
469
- this.parent = null;
470
- }
470
+ constructor() {
471
+ this.name = "";
472
+ this.members = [];
473
+ this.parent = null;
474
+ }
471
475
  }
472
476
  function charCodeAt32(data, offset) {
473
- return (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset);
477
+ return (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset);
474
478
  }
475
479
  function charCodeAt64(data, offset) {
476
- if (offset + 3 >= data.length) {
477
- throw new Error(
478
- "The string must have at least 4 characters from the specified offset.",
479
- );
480
- }
481
- const firstCharCode = BigInt(data.charCodeAt(offset));
482
- const secondCharCode = BigInt(data.charCodeAt(offset + 1));
483
- const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
484
- const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
485
- const u64Value =
486
- (fourthCharCode << 48n) |
487
- (thirdCharCode << 32n) |
488
- (secondCharCode << 16n) |
489
- firstCharCode;
490
- return u64Value;
480
+ if (offset + 3 >= data.length) {
481
+ throw new Error("The string must have at least 4 characters from the specified offset.");
482
+ }
483
+ const firstCharCode = BigInt(data.charCodeAt(offset));
484
+ const secondCharCode = BigInt(data.charCodeAt(offset + 1));
485
+ const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
486
+ const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
487
+ const u64Value = (fourthCharCode << 48n) |
488
+ (thirdCharCode << 32n) |
489
+ (secondCharCode << 16n) |
490
+ firstCharCode;
491
+ return u64Value;
491
492
  }
492
493
  function encodeKey(key) {
493
- const data = JSON.stringify(key);
494
- return data.slice(1, data.length - 1);
494
+ const data = JSON.stringify(key);
495
+ return data.slice(1, data.length - 1);
495
496
  }
496
497
  function escapeString(data) {
497
- return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
498
+ return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
498
499
  }
499
500
  function escapeSlash(data) {
500
- return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
501
+ return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
501
502
  }
502
503
  function escapeQuote(data) {
503
- return data.replace(/\"/g, '\\"');
504
+ return data.replace(/\"/g, '\\"');
504
505
  }
505
506
  function getArgs(args) {
506
- if (!args) return [];
507
- let out = [];
508
- for (const arg of args) {
509
- if (arg instanceof StringLiteralExpression) {
510
- out.push(arg.value);
507
+ if (!args)
508
+ return [];
509
+ let out = [];
510
+ for (const arg of args) {
511
+ if (arg instanceof StringLiteralExpression) {
512
+ out.push(arg.value);
513
+ }
514
+ else if (arg instanceof IntegerLiteralExpression) {
515
+ out.push(i64_to_string(arg.value));
516
+ }
517
+ else if (arg instanceof FloatLiteralExpression) {
518
+ out.push(arg.value.toString());
519
+ }
520
+ else if (arg instanceof NullExpression) {
521
+ out.push(arg.text);
522
+ }
523
+ else if (arg instanceof TrueExpression) {
524
+ out.push(arg.text);
525
+ }
526
+ else if (arg instanceof FalseExpression) {
527
+ out.push(arg.text);
528
+ }
529
+ else if (arg instanceof IdentifierExpression) {
530
+ out.push(arg.text);
531
+ }
511
532
  }
512
- }
513
- return out;
533
+ return out;
514
534
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@json-as/transform",
3
- "version": "0.9.18",
3
+ "version": "0.9.20",
4
4
  "description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
5
5
  "main": "./lib/index.js",
6
6
  "author": "Jairus Tanaka",
@@ -2,12 +2,17 @@ import {
2
2
  ClassDeclaration,
3
3
  FieldDeclaration,
4
4
  IdentifierExpression,
5
- StringLiteralExpression,
6
5
  Parser,
7
6
  Source,
8
7
  NodeKind,
9
8
  Expression,
10
9
  CommonFlags,
10
+ StringLiteralExpression,
11
+ IntegerLiteralExpression,
12
+ FloatLiteralExpression,
13
+ NullExpression,
14
+ TrueExpression,
15
+ FalseExpression,
11
16
  } from "assemblyscript/dist/assemblyscript.js";
12
17
 
13
18
  import { toString, isStdlib } from "visitor-as/dist/utils.js";
@@ -467,7 +472,6 @@ class Property {
467
472
  PropertyFlags,
468
473
  string[]
469
474
  >();
470
- public args: string[] | null = [];
471
475
 
472
476
  public serialize: string | null = null;
473
477
  public deserialize: string | null = null;
@@ -494,7 +498,11 @@ class Property {
494
498
  }
495
499
 
496
500
  if (this.flags.has(PropertyFlags.OmitIf)) {
497
- const condition = this.args![0];
501
+ const condition = this.flags.get(PropertyFlags.OmitIf)![0];
502
+ if (!condition)
503
+ throw new Error(
504
+ "Could not find condition when using decorator @omitif! Provide at least one condition",
505
+ );
498
506
  this.serialize =
499
507
  "${" +
500
508
  condition +
@@ -577,6 +585,18 @@ function getArgs(args: Expression[] | null): string[] {
577
585
  for (const arg of args) {
578
586
  if (arg instanceof StringLiteralExpression) {
579
587
  out.push(arg.value);
588
+ } else if (arg instanceof IntegerLiteralExpression) {
589
+ out.push(i64_to_string(arg.value));
590
+ } else if (arg instanceof FloatLiteralExpression) {
591
+ out.push(arg.value.toString());
592
+ } else if (arg instanceof NullExpression) {
593
+ out.push(arg.text);
594
+ } else if (arg instanceof TrueExpression) {
595
+ out.push(arg.text);
596
+ } else if (arg instanceof FalseExpression) {
597
+ out.push(arg.text);
598
+ } else if (arg instanceof IdentifierExpression) {
599
+ out.push(arg.text);
580
600
  }
581
601
  }
582
602
  return out;