json-as 1.1.21 โ†’ 1.1.23

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.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-11-06 - 1.1.23
4
+
5
+ - fix: Map keys should follow proper typing and quote rules [#161](https://github.com/JairusSW/json-as/issues/161)
6
+
7
+ ## 2025-09-01 - 1.1.22
8
+
9
+ - fix: Type aliases should work across files [#154](https://github.com/JairusSW/json-as/issues/154)
10
+
3
11
  ## 2025-08-14 - 1.1.21
4
12
 
5
13
  - fix: JSON.parse on classes with enums [#155](https://github.com/JairusSW/json-as/issues/155)
package/README.md CHANGED
@@ -378,19 +378,6 @@ These benchmarks compare this library to JavaScript's native `JSON.stringify` an
378
378
  | Medium Object | 494 bytes | 2,395,210 ops/s | 1,381,693 ops/s | 1,183 MB/s | 682.5 MB/s |
379
379
  | Large Object | 3374 bytes | 222,222 ops/s | 117,233 ops/s | 749.7 MB/s | 395.5 MB/s |
380
380
 
381
- **๐Ÿ“Œ Insights**
382
-
383
- - JSON-AS consistently outperforms JavaScript's native implementation.
384
-
385
- - **Serialization Speed:**
386
-
387
- - JSON-AS achieves speeds up to `2,133 MB/s`, significantly faster than JavaScript's peak of `1,416 MB/s`.
388
- - Large objects see the biggest improvement, with JSON-AS at `2,074 MB/s` vs. JavaScriptโ€™s `749.7 MB/s`.
389
-
390
- - **Deserialization Speed:**
391
- - JSON-AS reaches `1,986 MB/s`, while JavaScript caps at `1,592 MB/s`.
392
- - Small and medium objects see the most significant performance boost overall.
393
-
394
381
  ### ๐Ÿ“ˆ Comparison to v0.9.x version
395
382
 
396
383
  **Table 1** - _v1.0.0_
@@ -413,12 +400,45 @@ These benchmarks compare this library to JavaScript's native `JSON.stringify` an
413
400
  | Medium Object | 494 bytes | 522,193 ops/s | 508,582 ops/s | 258.0 MB/s | 251.2 MB/s |
414
401
  | Large Object | 3374 bytes | 51,229 ops/s | 65,585 ops/s | 172.8 MB/s | 221.3 MB/s |
415
402
 
416
- **๐Ÿ“Œ Insights:**
403
+ ### Running benchmarks locally
404
+
405
+ Benchmarks are run directly on top of v8 for more tailored control
406
+
407
+ 1. Download JSVU off of npm
408
+
409
+ ```bash
410
+ npm install jsvu -g
411
+ ```
412
+
413
+ 2. Modify your dotfiles to add `~/.jsvu/bin` to `PATH`
414
+
415
+ ```bash
416
+ export PATH="${HOME}/.jsvu/bin:${PATH}"
417
+ ```
418
+
419
+ 3. Clone the repository
417
420
 
418
- - Massive performance improvements in JSON-AS `v1.0.0`:
419
- - Serialization is **2-12x faster** (e.g., Large Object: `2,074 MB/s` vs. `172.8 MB/s`).
420
- - Deserialization is **2-3x faster** (e.g., Large Object: `1,348 MB/s` vs. `221.3 MB/s`).
421
- - Vector3 Object serialization improved from `416 MB/s` to `1,357 MB/s`--a **3x benefit** through new code generation techniques.
421
+ ```bash
422
+ git clone https://github.com/JairusSW/json-as
423
+ ```
424
+
425
+ 4. Install dependencies
426
+
427
+ ```bash
428
+ npm i
429
+ ```
430
+
431
+ 5. Run benchmarks for either AssemblyScript or JavaScript
432
+
433
+ ```bash
434
+ ./run-bench.as.sh
435
+ ```
436
+
437
+ or
438
+
439
+ ```bash
440
+ ./run-bench.js.sh
441
+ ```
422
442
 
423
443
  ## ๐Ÿ”ญ What's Next
424
444
 
@@ -1,7 +1,12 @@
1
1
  import { JSON } from "../..";
2
2
  import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T, COLON } from "../../custom/chars";
3
3
  import { isSpace } from "../../util";
4
- import { ptrToStr } from "../../util/ptrToStr";
4
+
5
+ // @ts-ignore: Decorator is valid here
6
+ @inline function normalizeQuotes<T>(start: usize, end: usize): T {
7
+ if (isString<T>()) return JSON.__deserialize<T>(start - 2, end + 2);
8
+ return JSON.__deserialize<T>(start, end);
9
+ }
5
10
 
6
11
  export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
7
12
  const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
@@ -51,7 +56,7 @@ export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd:
51
56
  if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
52
57
  // console.log("Value (string): " + ptrToStr(lastIndex, srcStart + 2));
53
58
  // @ts-ignore: type
54
- out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, srcStart + 2));
59
+ out.set(normalizeQuotes<indexof<T>>(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, srcStart + 2));
55
60
  // while (isSpace(load<u16>(srcStart))) srcStart += 2;
56
61
  srcStart += 4;
57
62
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
@@ -68,7 +73,7 @@ export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd:
68
73
  if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
69
74
  // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
70
75
  // @ts-ignore: type
71
- out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
76
+ out.set(normalizeQuotes<indexof<T>>(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
72
77
  // while (isSpace(load<u16>((srcStart += 2)))) {
73
78
  // /* empty */
74
79
  // }
@@ -92,7 +97,7 @@ export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd:
92
97
  if (--depth == 0) {
93
98
  // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
94
99
  // @ts-ignore: type
95
- out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
100
+ out.set(normalizeQuotes<indexof<T>>(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
96
101
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
97
102
  keyStart = 0;
98
103
  // while (isSpace(load<u16>(srcStart))) {
@@ -113,7 +118,7 @@ export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd:
113
118
  if (--depth == 0) {
114
119
  // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
115
120
  // @ts-ignore: type
116
- out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
121
+ out.set(normalizeQuotes<indexof<T>>(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
117
122
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
118
123
  keyStart = 0;
119
124
  // while (isSpace(load<u16>((srcStart += 2)))) {
@@ -128,7 +133,7 @@ export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd:
128
133
  if (load<u64>(srcStart) == 28429475166421108) {
129
134
  // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
130
135
  // @ts-ignore: type
131
- out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)));
136
+ out.set(normalizeQuotes<indexof<T>>(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)));
132
137
  // while (isSpace(load<u16>((srcStart += 2)))) {
133
138
  // /* empty */
134
139
  // }
@@ -140,7 +145,7 @@ export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd:
140
145
  if (load<u64>(srcStart, 2) == 28429466576093281) {
141
146
  // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
142
147
  // @ts-ignore: type
143
- out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 10)));
148
+ out.set(normalizeQuotes<indexof<T>>(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 10)));
144
149
  // while (isSpace(load<u16>((srcStart += 2)))) {
145
150
  // /* empty */
146
151
  // }
@@ -152,7 +157,7 @@ export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd:
152
157
  if (load<u64>(srcStart) == 30399761348886638) {
153
158
  // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
154
159
  // @ts-ignore: type
155
- out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)));
160
+ out.set(normalizeQuotes<indexof<T>>(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)));
156
161
  // while (isSpace(load<u16>((srcStart += 2)))) {
157
162
  /* empty */
158
163
  // }
package/assembly/index.ts CHANGED
@@ -617,7 +617,7 @@ export namespace JSON {
617
617
  if (isDefined(type.__DESERIALIZE)) {
618
618
  const out = changetype<nonnull<T>>(dst || __new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
619
619
  // @ts-ignore: Defined by transform
620
- if (isNullable<T>() && isDefined(type.__INITIALIZE)) out.__INITIALIZE();
620
+ if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
621
621
  // @ts-ignore: Defined by transform
622
622
  return out.__DESERIALIZE(srcStart, srcEnd, out);
623
623
  } else if (type instanceof Map) {
@@ -22,20 +22,43 @@ export function serializeMap<T extends Map<any, any>>(src: T): void {
22
22
  bs.offset += 2;
23
23
 
24
24
  for (let i = 0; i < srcEnd; i++) {
25
- JSON.__serialize(unchecked(keys[i]));
26
- bs.growSize(2);
27
- store<u16>(bs.offset, COLON);
28
- bs.offset += 2;
25
+ // @ts-ignore: Valid
26
+ if (!isString<indexof<T>>()) {
27
+ bs.growSize(6);
28
+ store<u16>(bs.offset, 34);
29
+ bs.offset += 2;
30
+ JSON.__serialize(unchecked(keys[i]));
31
+ store<u16>(bs.offset, 34);
32
+ store<u16>(bs.offset, COLON, 2);
33
+ bs.offset += 4;
34
+ } else {
35
+ JSON.__serialize(unchecked(keys[i]));
36
+ bs.growSize(2);
37
+ store<u16>(bs.offset, COLON);
38
+ bs.offset += 2;
39
+ }
29
40
  JSON.__serialize(unchecked(values[i]));
30
41
  bs.growSize(2);
31
42
  store<u16>(bs.offset, COMMA);
32
43
  bs.offset += 2;
33
44
  }
34
45
 
35
- JSON.__serialize(unchecked(keys[srcEnd]));
36
- bs.growSize(2);
37
- store<u16>(bs.offset, COLON);
38
- bs.offset += 2;
46
+ // @ts-ignore: Valid
47
+ if (!isString<indexof<T>>()) {
48
+ bs.growSize(6);
49
+ store<u16>(bs.offset, 34);
50
+ bs.offset += 2;
51
+ JSON.__serialize(unchecked(keys[srcEnd]));
52
+ store<u16>(bs.offset, 34);
53
+ store<u16>(bs.offset, COLON, 2);
54
+ bs.offset += 4;
55
+ } else {
56
+ JSON.__serialize(unchecked(keys[srcEnd]));
57
+ bs.growSize(2);
58
+ store<u16>(bs.offset, COLON);
59
+ bs.offset += 2;
60
+ }
61
+
39
62
  JSON.__serialize(unchecked(values[srcEnd]));
40
63
  // bs.growSize(2);
41
64
  store<u16>(bs.offset, BRACE_RIGHT);
@@ -1,16 +1,288 @@
1
+ import { bs } from "../lib/as-bs";
1
2
  import { JSON } from ".";
2
- const o = new JSON.Obj();
3
- o.set("schema", "http://json-schema.org/draft-07/schema#");
4
- o.set("additionalProperties", false);
5
- o.set("properties", new JSON.Obj());
6
- o.get("properties")!.as<JSON.Obj>().set("duration", new JSON.Obj());
7
- o.get("properties")!.as<JSON.Obj>().get("duration")!.as<JSON.Obj>().set("default", 10);
8
- o.get("properties")!.as<JSON.Obj>().get("duration")!.as<JSON.Obj>().set("description", "Duration of the operation in seconds");
9
- o.get("properties")!.as<JSON.Obj>().get("duration")!.as<JSON.Obj>().set("type", "number");
10
- o.get("properties")!.as<JSON.Obj>().set("steps", new JSON.Obj());
11
- o.get("properties")!.as<JSON.Obj>().get("steps")!.as<JSON.Obj>().set("default", 5);
12
- o.get("properties")!.as<JSON.Obj>().get("steps")!.as<JSON.Obj>().set("description", "Number of steps in the operation");
13
- o.get("properties")!.as<JSON.Obj>().get("steps")!.as<JSON.Obj>().set("type", "number");
14
- o.set("type", "object");
15
- console.log(o.toString());
16
- console.log((o.toString().length << 1).toString() + " == 596");
3
+
4
+ @json
5
+ class Example {
6
+ constructor(
7
+ public a: string,
8
+ public b: string,
9
+ public c: string,
10
+ public d: string,
11
+ public e: boolean,
12
+ ) {}
13
+ __SERIALIZE(ptr: usize): void {
14
+ bs.proposeSize(62);
15
+ store<u64>(bs.offset, 9570565822218363, 0);
16
+ store<u16>(bs.offset, 58, 8);
17
+ bs.offset += 10;
18
+ JSON.__serialize<string>(load<string>(ptr, offsetof<this>("a")));
19
+ store<u64>(bs.offset, 9570570117185580, 0);
20
+ store<u16>(bs.offset, 58, 8);
21
+ bs.offset += 10;
22
+ JSON.__serialize<string>(load<string>(ptr, offsetof<this>("b")));
23
+ store<u64>(bs.offset, 9570574412152876, 0);
24
+ store<u16>(bs.offset, 58, 8);
25
+ bs.offset += 10;
26
+ JSON.__serialize<string>(load<string>(ptr, offsetof<this>("c")));
27
+ store<u64>(bs.offset, 9570578707120172, 0);
28
+ store<u16>(bs.offset, 58, 8);
29
+ bs.offset += 10;
30
+ JSON.__serialize<string>(load<string>(ptr, offsetof<this>("d")));
31
+ store<u64>(bs.offset, 9570583002087468, 0);
32
+ store<u16>(bs.offset, 58, 8);
33
+ bs.offset += 10;
34
+ JSON.__serialize<boolean>(load<boolean>(ptr, offsetof<this>("e")));
35
+ store<u16>(bs.offset, 125, 0);
36
+ bs.offset += 2;
37
+ }
38
+
39
+ @inline
40
+ __INITIALIZE(): this {
41
+ store<string>(changetype<usize>(this), "", offsetof<this>("a"));
42
+ store<string>(changetype<usize>(this), "", offsetof<this>("b"));
43
+ store<string>(changetype<usize>(this), "", offsetof<this>("c"));
44
+ store<string>(changetype<usize>(this), "", offsetof<this>("d"));
45
+ return this;
46
+ }
47
+ __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {
48
+ let keyStart: usize = 0;
49
+ let keyEnd: usize = 0;
50
+ let isKey = false;
51
+ let depth: i32 = 0;
52
+ let lastIndex: usize = 0;
53
+ while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;
54
+ while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
55
+ if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");
56
+ if (load<u16>(srcStart) != 123) throw new Error("Expected '{' at start of object at position " + (srcEnd - srcStart).toString());
57
+ if (load<u16>(srcEnd - 2) != 125) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
58
+ srcStart += 2;
59
+ while (srcStart < srcEnd) {
60
+ let code = load<u16>(srcStart);
61
+ while (JSON.Util.isSpace(code)) code = load<u16>((srcStart += 2));
62
+ if (keyStart == 0) {
63
+ if (code == 34 && load<u16>(srcStart - 2) !== 92) {
64
+ if (isKey) {
65
+ keyStart = lastIndex;
66
+ keyEnd = srcStart;
67
+ console.log("Key: " + JSON.Util.ptrToStr(keyStart, keyEnd));
68
+ while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}
69
+ if (code !== 58) throw new Error("Expected ':' after key at position " + (srcEnd - srcStart).toString());
70
+ isKey = false;
71
+ } else {
72
+ isKey = true;
73
+ lastIndex = srcStart + 2;
74
+ }
75
+ }
76
+ srcStart += 2;
77
+ } else {
78
+ if (code == 34) {
79
+ lastIndex = srcStart;
80
+ srcStart += 2;
81
+ while (srcStart < srcEnd) {
82
+ const code = load<u16>(srcStart);
83
+ if (code == 34 && load<u16>(srcStart - 2) !== 92) {
84
+ console.log("Value (string, 1): " + JSON.Util.ptrToStr(lastIndex, srcStart + 2));
85
+ switch (<u32>keyEnd - <u32>keyStart) {
86
+ case 2: {
87
+ const code16 = load<u16>(keyStart);
88
+ if (code16 == 97) {
89
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart + 2), offsetof<this>("a"));
90
+ srcStart += 4;
91
+ keyStart = 0;
92
+ break;
93
+ } else if (code16 == 98) {
94
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart + 2), offsetof<this>("b"));
95
+ srcStart += 4;
96
+ keyStart = 0;
97
+ break;
98
+ } else if (code16 == 99) {
99
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart + 2), offsetof<this>("c"));
100
+ srcStart += 4;
101
+ keyStart = 0;
102
+ break;
103
+ } else if (code16 == 100) {
104
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart + 2), offsetof<this>("d"));
105
+ srcStart += 4;
106
+ keyStart = 0;
107
+ break;
108
+ } else {
109
+ srcStart += 4;
110
+ keyStart = 0;
111
+ break;
112
+ }
113
+ }
114
+
115
+ default: {
116
+ srcStart += 4;
117
+ keyStart = 0;
118
+ break;
119
+ }
120
+ }
121
+ break;
122
+ }
123
+ srcStart += 2;
124
+ }
125
+ } else if (code - 48 <= 9 || code == 45) {
126
+ lastIndex = srcStart;
127
+ srcStart += 2;
128
+ while (srcStart < srcEnd) {
129
+ const code = load<u16>(srcStart);
130
+ if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {
131
+ console.log("Value (number, 2): " + JSON.Util.ptrToStr(lastIndex, srcStart));
132
+ srcStart += 2;
133
+ keyStart = 0;
134
+ break;
135
+ }
136
+ srcStart += 2;
137
+ }
138
+ } else if (code == 123) {
139
+ lastIndex = srcStart;
140
+ depth++;
141
+ srcStart += 2;
142
+ while (srcStart < srcEnd) {
143
+ const code = load<u16>(srcStart);
144
+ if (code == 34) {
145
+ srcStart += 2;
146
+ while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;
147
+ } else if (code == 125) {
148
+ if (--depth == 0) {
149
+ srcStart += 2;
150
+ console.log("Value (object, 3): " + JSON.Util.ptrToStr(lastIndex, srcStart));
151
+ switch (<u32>keyEnd - <u32>keyStart) {
152
+ case 2: {
153
+ const code16 = load<u16>(keyStart);
154
+ if (code16 == 97) {
155
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart), offsetof<this>("a"));
156
+ keyStart = 0;
157
+ break;
158
+ } else if (code16 == 98) {
159
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart), offsetof<this>("b"));
160
+ keyStart = 0;
161
+ break;
162
+ } else if (code16 == 99) {
163
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart), offsetof<this>("c"));
164
+ keyStart = 0;
165
+ break;
166
+ } else if (code16 == 100) {
167
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart), offsetof<this>("d"));
168
+ keyStart = 0;
169
+ break;
170
+ } else if (code16 == 101) {
171
+ store<boolean>(changetype<usize>(out), JSON.__deserialize<boolean>(lastIndex, srcStart), offsetof<this>("e"));
172
+ keyStart = 0;
173
+ break;
174
+ } else {
175
+ keyStart = 0;
176
+ break;
177
+ }
178
+ }
179
+
180
+ default: {
181
+ keyStart = 0;
182
+ break;
183
+ }
184
+ }
185
+ break;
186
+ }
187
+ } else if (code == 123) depth++;
188
+ srcStart += 2;
189
+ }
190
+ } else if (code == 91) {
191
+ lastIndex = srcStart;
192
+ depth++;
193
+ srcStart += 2;
194
+ while (srcStart < srcEnd) {
195
+ const code = load<u16>(srcStart);
196
+ if (code == 34) {
197
+ srcStart += 2;
198
+ while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;
199
+ } else if (code == 93) {
200
+ if (--depth == 0) {
201
+ srcStart += 2;
202
+ console.log("Value (object, 4): " + JSON.Util.ptrToStr(lastIndex, srcStart));
203
+ keyStart = 0;
204
+ break;
205
+ }
206
+ } else if (code == 91) depth++;
207
+ srcStart += 2;
208
+ }
209
+ } else if (code == 116) {
210
+ if (load<u64>(srcStart) == 28429475166421108) {
211
+ srcStart += 8;
212
+ console.log("Value (bool, 5): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));
213
+ switch (<u32>keyEnd - <u32>keyStart) {
214
+ case 2: {
215
+ const code16 = load<u16>(keyStart);
216
+ if (code16 == 101) {
217
+ store<boolean>(changetype<usize>(out), true, offsetof<this>("e"));
218
+ srcStart += 2;
219
+ keyStart = 0;
220
+ break;
221
+ } else {
222
+ srcStart += 2;
223
+ keyStart = 0;
224
+ break;
225
+ }
226
+ }
227
+
228
+ default: {
229
+ srcStart += 2;
230
+ keyStart = 0;
231
+ }
232
+ }
233
+ } else {
234
+ throw new Error("Expected to find 'true' but found '" + JSON.Util.ptrToStr(lastIndex, srcStart) + "' instead at position " + (srcEnd - srcStart).toString());
235
+ }
236
+ } else if (code == 102) {
237
+ if (load<u64>(srcStart, 2) == 28429466576093281) {
238
+ srcStart += 10;
239
+ console.log("Value (bool, 6): " + JSON.Util.ptrToStr(lastIndex, srcStart - 10));
240
+ switch (<u32>keyEnd - <u32>keyStart) {
241
+ case 2: {
242
+ const code16 = load<u16>(keyStart);
243
+ if (code16 == 101) {
244
+ store<boolean>(changetype<usize>(out), false, offsetof<this>("e"));
245
+ srcStart += 2;
246
+ keyStart = 0;
247
+ break;
248
+ } else {
249
+ srcStart += 2;
250
+ keyStart = 0;
251
+ break;
252
+ }
253
+ }
254
+
255
+ default: {
256
+ srcStart += 2;
257
+ keyStart = 0;
258
+ }
259
+ }
260
+ } else {
261
+ throw new Error("Expected to find 'false' but found '" + JSON.Util.ptrToStr(lastIndex, srcStart) + "' instead at position " + (srcEnd - srcStart).toString());
262
+ }
263
+ } else if (code == 110) {
264
+ if (load<u64>(srcStart) == 30399761348886638) {
265
+ srcStart += 8;
266
+ console.log("Value (null, 7): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));
267
+ srcStart += 2;
268
+ keyStart = 0;
269
+ }
270
+ } else {
271
+ srcStart += 2;
272
+ keyStart = 0;
273
+ }
274
+ }
275
+ }
276
+ return out;
277
+ }
278
+ }
279
+ const good = `{"a":"a","b":"b","e":true,"c":"c","d":"d"}`;
280
+ const good2 = `{"a":"a","b":"b","c":"c","d":"d","e":false}`;
281
+ const bad = `{"a":"a","b":"b","e":false,"c":"c","d":"d"}`;
282
+ const parsedGood = JSON.parse<Example>(good);
283
+ console.log("a: " + JSON.stringify(parsedGood));
284
+ const parsedGood2 = JSON.parse<Example>(good2);
285
+ console.log("b: " + JSON.stringify(parsedGood2));
286
+ const parsedBad = JSON.parse<Example>(bad);
287
+ console.log("c: " + JSON.stringify(parsedBad));
288
+ console.log(load<u64>(changetype<usize>("alse")).toString());
package/assembly/test.ts CHANGED
@@ -2,43 +2,24 @@ import { JSON } from ".";
2
2
 
3
3
 
4
4
  @json
5
- class Vec3 {
6
- x: f32 = 0.0;
7
- y: f32 = 0.0;
8
- z: f32 = 0.0;
5
+ class Example {
6
+ constructor(
7
+ public a: string,
8
+ public b: string,
9
+ public c: string,
10
+ public d: string,
11
+ public e: boolean,
12
+ ) {}
9
13
  }
10
14
 
11
-
12
- @json
13
- class Player {
14
-
15
- @alias("first name")
16
- firstName!: string | null;
17
- lastName!: string;
18
- lastActive!: i32[];
19
- // Drop in a code block, function, or expression that evaluates to a boolean
20
- @omitif((self: Player) => self.age < 18)
21
- age!: i32;
22
-
23
- pos!: Vec3 | null;
24
- isVerified!: boolean;
25
- }
26
-
27
- const player: Player = {
28
- firstName: "Jairus",
29
- lastName: "Tanaka",
30
- lastActive: [3, 9, 2025],
31
- age: 18,
32
- pos: {
33
- x: 3.4,
34
- y: 1.2,
35
- z: 8.3,
36
- },
37
- isVerified: true,
38
- };
39
-
40
- const serialized = JSON.stringify<Player>(player);
41
- const deserialized = JSON.parse<Player>(serialized);
42
-
43
- console.log("Serialized " + serialized);
44
- console.log("Deserialized " + JSON.stringify(deserialized));
15
+ const good = `{"a":"a","b":"b","e":true,"c":"c","d":"d"}`;
16
+ const good2 = `{"a":"a","b":"b","c":"c","d":"d","e":false}`;
17
+ const bad = `{"a":"a","b":"b","e":false,"c":"c","d":"d"}`;
18
+ const parsedGood = JSON.parse<Example>(good);
19
+ console.log("a: " + JSON.stringify(parsedGood));
20
+ const parsedGood2 = JSON.parse<Example>(good2);
21
+ console.log("b: " + JSON.stringify(parsedGood2));
22
+ const parsedBad = JSON.parse<Example>(bad);
23
+ console.log("c: " + JSON.stringify(parsedBad));
24
+
25
+ console.log(load<u64>(changetype<usize>("alse")).toString());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "1.1.21",
3
+ "version": "1.1.23",
4
4
  "author": "Jairus Tanaka",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,7 +13,7 @@
13
13
  "assemblyscript": "^0.28.4",
14
14
  "assemblyscript-prettier": "^3.0.1",
15
15
  "prettier": "^3.6.2",
16
- "tinybench": "^4.1.0",
16
+ "tinybench": "^5.0.1",
17
17
  "typescript": "^5.9.2"
18
18
  },
19
19
  "bugs": {
@@ -57,7 +57,8 @@
57
57
  "test": "bash ./run-tests.sh",
58
58
  "bench:as": "bash ./run-bench.as.sh",
59
59
  "bench:js": "bash ./run-bench.js.sh",
60
- "build:test": "rm -rf ./build/ && JSON_DEBUG=1 JSON_WRITE=assembly/test.ts asc assembly/test.ts --transform ./transform -o ./build/test.wasm --textFile ./build/test.wat --enable simd --debug --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json",
60
+ "build:test": "rm -rf ./build/ && JSON_DEBUG=2 JSON_WRITE=assembly/test.ts asc assembly/test.ts --transform ./transform -o ./build/test.wasm --textFile ./build/test.wat --enable simd --debug --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json",
61
+ "build:tmp:test": "rm -rf ./build/ && JSON_DEBUG=1 asc assembly/test.tmp.ts -o ./build/test.wasm --textFile ./build/test.wat --enable simd --debug --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json",
61
62
  "build:test:wine": "JSON_DEBUG=1 JSON_WRITE=assembly/test.ts NODE_SKIP_PLATFORM_CHECK=1 wine ~/.win-bin/node/node.exe ./node_modules/assemblyscript/bin/asc.js assembly/test.ts --transform ./transform -o ./build/test.wasm --textFile ./build/test.wat --debug --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json",
62
63
  "test:wasmtime": "wasmtime ./build/test.wasm",
63
64
  "test:wasmer": "wasmer ./build/test.wasm",