json-as 1.3.7 → 1.3.8

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 (116) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +1 -1
  3. package/assembly/deserialize/index/arbitrary.ts +2 -2
  4. package/assembly/deserialize/index/array.ts +29 -14
  5. package/assembly/deserialize/index/bool.ts +1 -1
  6. package/assembly/deserialize/index/date.ts +1 -1
  7. package/assembly/deserialize/index/float.ts +40 -1
  8. package/assembly/deserialize/index/integer.ts +3 -3
  9. package/assembly/deserialize/index/map.ts +1 -1
  10. package/assembly/deserialize/index/object.ts +1 -1
  11. package/assembly/deserialize/index/raw.ts +1 -1
  12. package/assembly/deserialize/index/set.ts +1 -1
  13. package/assembly/deserialize/index/staticarray.ts +4 -1
  14. package/assembly/deserialize/index/string.ts +28 -3
  15. package/assembly/deserialize/index/struct.ts +1 -1
  16. package/assembly/deserialize/index/typedarray.ts +25 -15
  17. package/assembly/deserialize/index/unsigned.ts +3 -3
  18. package/assembly/deserialize/index.ts +1 -0
  19. package/assembly/deserialize/naive/array/bool.ts +68 -0
  20. package/assembly/deserialize/naive/array/float.ts +63 -0
  21. package/assembly/deserialize/{simple → naive}/array/generic.ts +1 -2
  22. package/assembly/deserialize/naive/array/integer.ts +86 -0
  23. package/assembly/deserialize/{simple → naive}/array/map.ts +0 -1
  24. package/assembly/deserialize/{simple → naive}/array/object.ts +0 -1
  25. package/assembly/deserialize/naive/array/string.ts +69 -0
  26. package/assembly/deserialize/{simple → naive}/array/struct.ts +0 -1
  27. package/assembly/deserialize/{simple → naive}/array.ts +6 -11
  28. package/assembly/deserialize/naive/float.ts +135 -0
  29. package/assembly/deserialize/{simple → naive}/integer.ts +2 -2
  30. package/assembly/deserialize/{simple → naive}/map.ts +12 -6
  31. package/assembly/deserialize/{simple → naive}/object.ts +4 -7
  32. package/assembly/deserialize/{simple → naive}/set.ts +12 -27
  33. package/assembly/deserialize/{simple → naive}/staticarray/array.ts +1 -1
  34. package/assembly/deserialize/{simple → naive}/staticarray/bool.ts +1 -1
  35. package/assembly/deserialize/{simple → naive}/staticarray/float.ts +1 -1
  36. package/assembly/deserialize/{simple → naive}/staticarray/integer.ts +1 -1
  37. package/assembly/deserialize/{simple → naive}/staticarray/struct.ts +1 -2
  38. package/assembly/deserialize/{simple → naive}/staticarray.ts +4 -4
  39. package/assembly/deserialize/naive/string.ts +199 -0
  40. package/assembly/deserialize/{simple → naive}/typedarray.ts +4 -4
  41. package/assembly/deserialize/{simple → naive}/unsigned.ts +2 -2
  42. package/assembly/deserialize/simd/array/integer.ts +19 -19
  43. package/assembly/deserialize/simd/float.ts +303 -0
  44. package/assembly/deserialize/simd/string.ts +233 -108
  45. package/assembly/deserialize/swar/array/arbitrary.ts +6 -2
  46. package/assembly/deserialize/swar/array/array.ts +14 -7
  47. package/assembly/deserialize/swar/array/bool.ts +8 -3
  48. package/assembly/deserialize/swar/array/box.ts +6 -2
  49. package/assembly/deserialize/swar/array/float.ts +282 -6
  50. package/assembly/deserialize/swar/array/generic.ts +6 -2
  51. package/assembly/deserialize/swar/array/integer.ts +81 -74
  52. package/assembly/deserialize/swar/array/map.ts +6 -2
  53. package/assembly/deserialize/swar/array/object.ts +24 -32
  54. package/assembly/deserialize/swar/array/raw.ts +6 -2
  55. package/assembly/deserialize/swar/array/shared.ts +32 -8
  56. package/assembly/deserialize/swar/array/string.ts +127 -10
  57. package/assembly/deserialize/swar/array/struct.ts +45 -11
  58. package/assembly/deserialize/swar/array.ts +2 -56
  59. package/assembly/deserialize/swar/float.ts +304 -0
  60. package/assembly/deserialize/swar/string.ts +119 -104
  61. package/assembly/deserialize/swar/typedarray.ts +224 -0
  62. package/assembly/index.ts +203 -293
  63. package/assembly/serialize/index/array.ts +1 -1
  64. package/assembly/serialize/index/bool.ts +1 -1
  65. package/assembly/serialize/index/date.ts +1 -1
  66. package/assembly/serialize/index/float.ts +1 -1
  67. package/assembly/serialize/index/integer.ts +1 -1
  68. package/assembly/serialize/index/map.ts +1 -1
  69. package/assembly/serialize/index/raw.ts +1 -1
  70. package/assembly/serialize/index/set.ts +1 -1
  71. package/assembly/serialize/index/staticarray.ts +1 -1
  72. package/assembly/serialize/index/string.ts +1 -1
  73. package/assembly/serialize/index/struct.ts +1 -1
  74. package/assembly/serialize/index/typedarray.ts +2 -11
  75. package/assembly/serialize/index.ts +1 -0
  76. package/assembly/serialize/{simple → naive}/array.ts +87 -0
  77. package/assembly/serialize/{simple → naive}/string.ts +1 -1
  78. package/assembly/serialize/swar/string.ts +0 -139
  79. package/assembly/util/dragonbox.ts +10 -3
  80. package/assembly/util/itoa-fast.ts +29 -18
  81. package/assembly/util/scanValueEnd.ts +78 -0
  82. package/assembly/util/scientific.ts +132 -0
  83. package/lib/as-bs.ts +14 -1
  84. package/package.json +14 -13
  85. package/transform/lib/index.d.ts +4 -0
  86. package/transform/lib/index.d.ts.map +1 -1
  87. package/transform/lib/index.js +153 -236
  88. package/transform/lib/index.js.map +1 -1
  89. package/assembly/deserialize/simple/arbitrary.ts +0 -30
  90. package/assembly/deserialize/simple/array/bool.ts +0 -48
  91. package/assembly/deserialize/simple/array/float.ts +0 -55
  92. package/assembly/deserialize/simple/array/integer.ts +0 -33
  93. package/assembly/deserialize/simple/array/string.ts +0 -29
  94. package/assembly/deserialize/simple/float.ts +0 -206
  95. package/assembly/deserialize/simple/string.ts +0 -45
  96. package/assembly/serialize/simple/arbitrary.ts +0 -79
  97. package/assembly/serialize/simple/object.ts +0 -42
  98. /package/assembly/deserialize/{simple → naive}/array/arbitrary.ts +0 -0
  99. /package/assembly/deserialize/{simple → naive}/array/array.ts +0 -0
  100. /package/assembly/deserialize/{simple → naive}/array/box.ts +0 -0
  101. /package/assembly/deserialize/{simple → naive}/array/raw.ts +0 -0
  102. /package/assembly/deserialize/{simple → naive}/bool.ts +0 -0
  103. /package/assembly/deserialize/{simple → naive}/date.ts +0 -0
  104. /package/assembly/deserialize/{simple → naive}/raw.ts +0 -0
  105. /package/assembly/deserialize/{simple → naive}/staticarray/string.ts +0 -0
  106. /package/assembly/deserialize/{simple → naive}/struct.ts +0 -0
  107. /package/assembly/serialize/{simple → naive}/bool.ts +0 -0
  108. /package/assembly/serialize/{simple → naive}/date.ts +0 -0
  109. /package/assembly/serialize/{simple → naive}/float.ts +0 -0
  110. /package/assembly/serialize/{simple → naive}/integer.ts +0 -0
  111. /package/assembly/serialize/{simple → naive}/map.ts +0 -0
  112. /package/assembly/serialize/{simple → naive}/raw.ts +0 -0
  113. /package/assembly/serialize/{simple → naive}/set.ts +0 -0
  114. /package/assembly/serialize/{simple → naive}/staticarray.ts +0 -0
  115. /package/assembly/serialize/{simple → naive}/struct.ts +0 -0
  116. /package/assembly/serialize/{simple → naive}/typedarray.ts +0 -0
package/assembly/index.ts CHANGED
@@ -2,21 +2,43 @@
2
2
 
3
3
  import { bs } from "../lib/as-bs";
4
4
  import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
5
- import { serializeArray } from "./serialize/index/array";
6
- import { serializeMap } from "./serialize/index/map";
7
- import { serializeDate } from "./serialize/index/date";
8
- import { deserializeBoolean } from "./deserialize/index/bool";
9
- import { deserializeArray } from "./deserialize/index/array";
10
- import { deserializeFloat } from "./deserialize/index/float";
11
- import { deserializeMap } from "./deserialize/index/map";
12
- import { deserializeDate } from "./deserialize/index/date";
13
- import { deserializeInteger } from "./deserialize/index/integer";
14
- import { deserializeUnsigned } from "./deserialize/index/unsigned";
15
- import { serializeArbitrary } from "./serialize/index/arbitrary";
16
- import { serializeSet } from "./serialize/index/set";
17
- import { deserializeSet } from "./deserialize/index/set";
18
- import { serializeStaticArray } from "./serialize/index/staticarray";
19
- import { deserializeStaticArray } from "./deserialize/index/staticarray";
5
+ import {
6
+ serializeArray,
7
+ serializeMap,
8
+ serializeDate,
9
+ serializeArbitrary,
10
+ serializeSet,
11
+ serializeStaticArray,
12
+ serializeBool,
13
+ serializeInteger,
14
+ serializeFloat,
15
+ serializeFloat32,
16
+ serializeFloat64,
17
+ serializeStruct,
18
+ serializeObject,
19
+ serializeRaw,
20
+ serializeString,
21
+ serializeArrayBufferUnsafe,
22
+ serializeDynamic,
23
+ serializeTypedArray,
24
+ } from "./serialize";
25
+ import {
26
+ deserializeBoolean,
27
+ deserializeArray,
28
+ deserializeFloat,
29
+ deserializeMap,
30
+ deserializeDate,
31
+ deserializeInteger,
32
+ deserializeUnsigned,
33
+ deserializeSet,
34
+ deserializeStaticArray,
35
+ deserializeArbitrary,
36
+ deserializeObject,
37
+ deserializeRaw,
38
+ deserializeString,
39
+ deserializeArrayBuffer,
40
+ deserializeTypedArray,
41
+ } from "./deserialize";
20
42
  import {
21
43
  BRACE_LEFT,
22
44
  BRACE_RIGHT,
@@ -30,36 +52,12 @@ import {
30
52
  FALSE_WORD_U64,
31
53
  } from "./custom/chars";
32
54
  import { itoa_buffered } from "util/number";
33
- import { serializeBool } from "./serialize/index/bool";
34
- import { serializeInteger } from "./serialize/index/integer";
35
- import {
36
- serializeFloat,
37
- serializeFloat32,
38
- serializeFloat64,
39
- } from "./serialize/index/float";
40
55
  import {
41
56
  dragonbox_f32_buffered,
42
57
  dragonbox_f64_buffered,
43
58
  } from "./util/dragonbox";
44
- import { serializeStruct } from "./serialize/index/struct";
45
59
  import { ptrToStr } from "./util/ptrToStr";
46
60
  import { atoi, bytes, scanStringEnd } from "./util";
47
- import { deserializeArbitrary } from "./deserialize/index/arbitrary";
48
- import { serializeObject } from "./serialize/index/object";
49
- import { deserializeObject } from "./deserialize/index/object";
50
- import { serializeRaw } from "./serialize/index/raw";
51
- import { deserializeRaw } from "./deserialize/index/raw";
52
- import { deserializeString } from "./deserialize/index/string";
53
- import { serializeString } from "./serialize/index/string";
54
- import {
55
- deserializeArrayBuffer,
56
- deserializeTypedArray,
57
- } from "./deserialize/index/typedarray";
58
- import {
59
- serializeArrayBufferUnsafe,
60
- serializeDynamic,
61
- serializeTypedArray,
62
- } from "./serialize/index/typedarray";
63
61
 
64
62
  /**
65
63
  * Offset of the 'storage' property in the JSON.Value class.
@@ -179,79 +177,9 @@ export namespace JSON {
179
177
  );
180
178
  store<u16>(changetype<usize>(out), QUOTE, 50);
181
179
  return changetype<string>(out);
182
- } else if (data instanceof Array) {
183
- // @ts-expect-error
184
- inline.always(serializeArray(changetype<nonnull<T>>(data)));
185
- return bs.out<string>();
186
- } else if (data instanceof StaticArray) {
187
- // @ts-expect-error
188
- inline.always(serializeStaticArray(changetype<nonnull<T>>(data)));
189
- return bs.out<string>();
190
- } else if (data instanceof Int8Array) {
191
- inline.always(serializeTypedArray<Int8Array>(data));
192
- return bs.out<string>();
193
- } else if (data instanceof Uint8Array) {
194
- inline.always(serializeTypedArray<Uint8Array>(data));
195
- return bs.out<string>();
196
- } else if (data instanceof Uint8ClampedArray) {
197
- inline.always(serializeTypedArray<Uint8ClampedArray>(data));
198
- return bs.out<string>();
199
- } else if (data instanceof Int16Array) {
200
- inline.always(serializeTypedArray<Int16Array>(data));
201
- return bs.out<string>();
202
- } else if (data instanceof Uint16Array) {
203
- inline.always(serializeTypedArray<Uint16Array>(data));
204
- return bs.out<string>();
205
- } else if (data instanceof Int32Array) {
206
- inline.always(serializeTypedArray<Int32Array>(data));
207
- return bs.out<string>();
208
- } else if (data instanceof Uint32Array) {
209
- inline.always(serializeTypedArray<Uint32Array>(data));
210
- return bs.out<string>();
211
- } else if (data instanceof Int64Array) {
212
- inline.always(serializeTypedArray<Int64Array>(data));
213
- return bs.out<string>();
214
- } else if (data instanceof Uint64Array) {
215
- inline.always(serializeTypedArray<Uint64Array>(data));
216
- return bs.out<string>();
217
- } else if (data instanceof Float32Array) {
218
- inline.always(serializeTypedArray<Float32Array>(data));
219
- return bs.out<string>();
220
- } else if (data instanceof Float64Array) {
221
- inline.always(serializeTypedArray<Float64Array>(data));
222
- return bs.out<string>();
223
- } else if (data instanceof ArrayBuffer) {
224
- const dataStart = changetype<usize>(data);
225
- serializeArrayBufferUnsafe(
226
- dataStart,
227
- changetype<OBJECT>(dataStart - TOTAL_OVERHEAD).rtSize,
228
- );
229
- return bs.out<string>();
230
- } else if (data instanceof Set) {
231
- // @ts-expect-error
232
- inline.always(serializeSet(changetype<nonnull<T>>(data)));
233
- return bs.out<string>();
234
- } else if (data instanceof Map) {
235
- // @ts-expect-error
236
- inline.always(serializeMap(changetype<nonnull<T>>(data)));
237
- return bs.out<string>();
238
- } else if (data instanceof JSON.Raw) {
239
- serializeRaw(data);
240
- return bs.out<string>();
241
- } else if (data instanceof JSON.Value) {
242
- inline.always(serializeArbitrary(data));
243
- return bs.out<string>();
244
- } else if (data instanceof JSON.Obj) {
245
- inline.always(serializeObject(data));
246
- return bs.out<string>();
247
- } else if (data instanceof JSON.Box) {
248
- return JSON.stringify(data.value);
249
180
  } else {
250
- throw new Error(
251
- `Could not serialize data of type '${nameof<T>()}'. ` +
252
- `If this is a custom class, add the @json decorator: @json class ${nameof<T>()} { ... }. ` +
253
- `Supported types: primitives, string, Array, StaticArray, TypedArray, ArrayBuffer, Map, Date, and @json decorated classes.`,
254
- );
181
+ serializeReference<T>(data);
182
+ return bs.out<string>();
255
183
  }
256
184
  }
257
185
 
@@ -265,8 +193,16 @@ export namespace JSON {
265
193
  */
266
194
  // @ts-expect-error: inline
267
195
  @inline export function parse<T>(data: string): T {
268
- const dataSize = bytes(data);
269
- const dataPtr = changetype<usize>(data);
196
+ let dataPtr = changetype<usize>(data);
197
+ const dataEnd = dataPtr + bytes(data);
198
+ // Entry point skips leading whitespace: every deserialize handler may then
199
+ // assume srcStart points at the first non-whitespace char. Handlers must
200
+ // NOT re-skip leading whitespace themselves. (Trailing whitespace is left
201
+ // intact — scalars stop at the value end, composites self-trim, and
202
+ // JSON.Raw intentionally preserves trailing bytes.)
203
+ while (dataPtr < dataEnd && JSON.Util.isSpace(load<u16>(dataPtr)))
204
+ dataPtr += 2;
205
+ const dataSize = dataEnd - dataPtr;
270
206
  if (isBoolean<T>()) {
271
207
  return deserializeBoolean(dataPtr, dataPtr + dataSize) as T;
272
208
  } else if (isInteger<T>()) {
@@ -301,12 +237,20 @@ export namespace JSON {
301
237
  // @ts-expect-error: Defined by transform
302
238
  if (isDefined(type.__DESERIALIZE_FAST)) {
303
239
  // @ts-expect-error: Defined by transform
240
+ const fastEnd = out.__DESERIALIZE_FAST(
241
+ dataPtr,
242
+ dataPtr + dataSize,
243
+ out,
244
+ );
245
+ // A non-zero return means the fast path matched; accept it when only
246
+ // trailing whitespace remains (pretty-printed input ends with a
247
+ // newline, so the cursor stops just past `}` rather than at srcEnd).
304
248
  if (
305
- out.__DESERIALIZE_FAST(dataPtr, dataPtr + dataSize, out) ==
306
- dataPtr + dataSize
249
+ fastEnd != 0 &&
250
+ JSON.Util.skipWhitespace(fastEnd, dataPtr + dataSize) ==
251
+ dataPtr + dataSize
307
252
  )
308
253
  return out;
309
- // @ts-expect-error: Defined by transform
310
254
  }
311
255
  if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
312
256
  // @ts-expect-error: Defined by transform
@@ -331,67 +275,19 @@ export namespace JSON {
331
275
  changetype<usize>(instantiate<T>()),
332
276
  ),
333
277
  );
334
- } else if (type instanceof Int8Array) {
335
- return deserializeTypedArray<nonnull<T>>(
336
- dataPtr,
337
- dataPtr + dataSize,
338
- 0,
339
- ) as T;
340
- } else if (type instanceof Uint8Array) {
341
- return deserializeTypedArray<nonnull<T>>(
342
- dataPtr,
343
- dataPtr + dataSize,
344
- 0,
345
- ) as T;
346
- } else if (type instanceof Uint8ClampedArray) {
347
- return deserializeTypedArray<nonnull<T>>(
348
- dataPtr,
349
- dataPtr + dataSize,
350
- 0,
351
- ) as T;
352
- } else if (type instanceof Int16Array) {
353
- return deserializeTypedArray<nonnull<T>>(
354
- dataPtr,
355
- dataPtr + dataSize,
356
- 0,
357
- ) as T;
358
- } else if (type instanceof Uint16Array) {
359
- return deserializeTypedArray<nonnull<T>>(
360
- dataPtr,
361
- dataPtr + dataSize,
362
- 0,
363
- ) as T;
364
- } else if (type instanceof Int32Array) {
365
- return deserializeTypedArray<nonnull<T>>(
366
- dataPtr,
367
- dataPtr + dataSize,
368
- 0,
369
- ) as T;
370
- } else if (type instanceof Uint32Array) {
371
- return deserializeTypedArray<nonnull<T>>(
372
- dataPtr,
373
- dataPtr + dataSize,
374
- 0,
375
- ) as T;
376
- } else if (type instanceof Int64Array) {
377
- return deserializeTypedArray<nonnull<T>>(
378
- dataPtr,
379
- dataPtr + dataSize,
380
- 0,
381
- ) as T;
382
- } else if (type instanceof Uint64Array) {
383
- return deserializeTypedArray<nonnull<T>>(
384
- dataPtr,
385
- dataPtr + dataSize,
386
- 0,
387
- ) as T;
388
- } else if (type instanceof Float32Array) {
389
- return deserializeTypedArray<nonnull<T>>(
390
- dataPtr,
391
- dataPtr + dataSize,
392
- 0,
393
- ) as T;
394
- } else if (type instanceof Float64Array) {
278
+ } else if (
279
+ type instanceof Int8Array ||
280
+ type instanceof Uint8Array ||
281
+ type instanceof Uint8ClampedArray ||
282
+ type instanceof Int16Array ||
283
+ type instanceof Uint16Array ||
284
+ type instanceof Int32Array ||
285
+ type instanceof Uint32Array ||
286
+ type instanceof Int64Array ||
287
+ type instanceof Uint64Array ||
288
+ type instanceof Float32Array ||
289
+ type instanceof Float64Array
290
+ ) {
395
291
  return deserializeTypedArray<nonnull<T>>(
396
292
  dataPtr,
397
293
  dataPtr + dataSize,
@@ -635,17 +531,20 @@ export namespace JSON {
635
531
  // @ts-expect-error: supplied by transform
636
532
  if (isDefined(value.__SERIALIZE) && isManaged<T>(value))
637
533
  return u16(idof<T>()) + JSON.Types.Struct;
638
- if (value instanceof Int8Array) return JSON.Types.TypedArray;
639
- if (value instanceof Uint8Array) return JSON.Types.TypedArray;
640
- if (value instanceof Uint8ClampedArray) return JSON.Types.TypedArray;
641
- if (value instanceof Int16Array) return JSON.Types.TypedArray;
642
- if (value instanceof Uint16Array) return JSON.Types.TypedArray;
643
- if (value instanceof Int32Array) return JSON.Types.TypedArray;
644
- if (value instanceof Uint32Array) return JSON.Types.TypedArray;
645
- if (value instanceof Int64Array) return JSON.Types.TypedArray;
646
- if (value instanceof Uint64Array) return JSON.Types.TypedArray;
647
- if (value instanceof Float32Array) return JSON.Types.TypedArray;
648
- if (value instanceof Float64Array) return JSON.Types.TypedArray;
534
+ if (
535
+ value instanceof Int8Array ||
536
+ value instanceof Uint8Array ||
537
+ value instanceof Uint8ClampedArray ||
538
+ value instanceof Int16Array ||
539
+ value instanceof Uint16Array ||
540
+ value instanceof Int32Array ||
541
+ value instanceof Uint32Array ||
542
+ value instanceof Int64Array ||
543
+ value instanceof Uint64Array ||
544
+ value instanceof Float32Array ||
545
+ value instanceof Float64Array
546
+ )
547
+ return JSON.Types.TypedArray;
649
548
  if (value instanceof ArrayBuffer) return JSON.Types.ArrayBuffer;
650
549
  if (value instanceof Map) return JSON.Types.Map;
651
550
  if (value instanceof JSON.Raw) return JSON.Types.Raw;
@@ -686,29 +585,20 @@ export namespace JSON {
686
585
  changetype<usize>(value),
687
586
  STORAGE,
688
587
  );
689
- } else if (value instanceof Int8Array)
690
- store<T>(changetype<usize>(this), value, STORAGE);
691
- else if (value instanceof Uint8Array)
692
- store<T>(changetype<usize>(this), value, STORAGE);
693
- else if (value instanceof Uint8ClampedArray)
694
- store<T>(changetype<usize>(this), value, STORAGE);
695
- else if (value instanceof Int16Array)
696
- store<T>(changetype<usize>(this), value, STORAGE);
697
- else if (value instanceof Uint16Array)
698
- store<T>(changetype<usize>(this), value, STORAGE);
699
- else if (value instanceof Int32Array)
700
- store<T>(changetype<usize>(this), value, STORAGE);
701
- else if (value instanceof Uint32Array)
702
- store<T>(changetype<usize>(this), value, STORAGE);
703
- else if (value instanceof Int64Array)
704
- store<T>(changetype<usize>(this), value, STORAGE);
705
- else if (value instanceof Uint64Array)
706
- store<T>(changetype<usize>(this), value, STORAGE);
707
- else if (value instanceof Float32Array)
708
- store<T>(changetype<usize>(this), value, STORAGE);
709
- else if (value instanceof Float64Array)
710
- store<T>(changetype<usize>(this), value, STORAGE);
711
- else if (value instanceof ArrayBuffer)
588
+ } else if (
589
+ value instanceof Int8Array ||
590
+ value instanceof Uint8Array ||
591
+ value instanceof Uint8ClampedArray ||
592
+ value instanceof Int16Array ||
593
+ value instanceof Uint16Array ||
594
+ value instanceof Int32Array ||
595
+ value instanceof Uint32Array ||
596
+ value instanceof Int64Array ||
597
+ value instanceof Uint64Array ||
598
+ value instanceof Float32Array ||
599
+ value instanceof Float64Array ||
600
+ value instanceof ArrayBuffer
601
+ )
712
602
  store<T>(changetype<usize>(this), value, STORAGE);
713
603
  else if (value instanceof Map) {
714
604
  if (idof<T>() !== idof<Map<string, JSON.Value>>()) {
@@ -1012,7 +902,7 @@ export namespace JSON {
1012
902
  * @param data - T
1013
903
  * @returns void
1014
904
  */
1015
- export function __serialize<T>(data: T): void {
905
+ function __serialize<T>(data: T): void {
1016
906
  if (isBoolean<T>()) {
1017
907
  serializeBool(data as bool);
1018
908
  } else if (isInteger<T>() && nameof<T>() == "usize" && data == 0) {
@@ -1044,60 +934,8 @@ export namespace JSON {
1044
934
  } else if (data instanceof Date) {
1045
935
  // @ts-expect-error
1046
936
  inline.always(serializeDate(changetype<nonnull<T>>(data)));
1047
- } else if (data instanceof Array) {
1048
- // @ts-expect-error
1049
- serializeArray(changetype<nonnull<T>>(data));
1050
- } else if (data instanceof StaticArray) {
1051
- // @ts-expect-error
1052
- serializeStaticArray(changetype<nonnull<T>>(data));
1053
- } else if (data instanceof Int8Array) {
1054
- serializeTypedArray<Int8Array>(data);
1055
- } else if (data instanceof Uint8Array) {
1056
- serializeTypedArray<Uint8Array>(data);
1057
- } else if (data instanceof Uint8ClampedArray) {
1058
- serializeTypedArray<Uint8ClampedArray>(data);
1059
- } else if (data instanceof Int16Array) {
1060
- serializeTypedArray<Int16Array>(data);
1061
- } else if (data instanceof Uint16Array) {
1062
- serializeTypedArray<Uint16Array>(data);
1063
- } else if (data instanceof Int32Array) {
1064
- serializeTypedArray<Int32Array>(data);
1065
- } else if (data instanceof Uint32Array) {
1066
- serializeTypedArray<Uint32Array>(data);
1067
- } else if (data instanceof Int64Array) {
1068
- serializeTypedArray<Int64Array>(data);
1069
- } else if (data instanceof Uint64Array) {
1070
- serializeTypedArray<Uint64Array>(data);
1071
- } else if (data instanceof Float32Array) {
1072
- serializeTypedArray<Float32Array>(data);
1073
- } else if (data instanceof Float64Array) {
1074
- serializeTypedArray<Float64Array>(data);
1075
- } else if (data instanceof ArrayBuffer) {
1076
- const dataStart = changetype<usize>(data);
1077
- serializeArrayBufferUnsafe(
1078
- dataStart,
1079
- changetype<OBJECT>(dataStart - TOTAL_OVERHEAD).rtSize,
1080
- );
1081
- } else if (data instanceof Set) {
1082
- // @ts-expect-error
1083
- serializeSet(changetype<nonnull<T>>(data));
1084
- } else if (data instanceof Map) {
1085
- // @ts-expect-error
1086
- serializeMap(changetype<nonnull<T>>(data));
1087
- } else if (data instanceof JSON.Raw) {
1088
- serializeRaw(data);
1089
- } else if (data instanceof JSON.Value) {
1090
- serializeArbitrary(data);
1091
- } else if (data instanceof JSON.Obj) {
1092
- serializeObject(data);
1093
- } else if (data instanceof JSON.Box) {
1094
- __serialize(data.value);
1095
937
  } else {
1096
- throw new Error(
1097
- `Could not serialize data of type '${nameof<T>()}'. ` +
1098
- `If this is a custom class, add the @json decorator: @json class ${nameof<T>()} { ... }. ` +
1099
- `Supported types: primitives, string, Array, StaticArray, TypedArray, ArrayBuffer, Map, Date, and @json decorated classes.`,
1100
- );
938
+ serializeReference<T>(data);
1101
939
  }
1102
940
  }
1103
941
 
@@ -1109,11 +947,12 @@ export namespace JSON {
1109
947
  * @param dst - usize
1110
948
  * @returns void
1111
949
  */
1112
- export function __deserialize<T>(
1113
- srcStart: usize,
1114
- srcEnd: usize,
1115
- dst: usize = 0,
1116
- ): T {
950
+ function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
951
+ // Skip leading whitespace once here so every handler below may assume
952
+ // srcStart is at the first non-whitespace char. (Trailing whitespace is
953
+ // left intact — composites self-trim and JSON.Raw preserves it.)
954
+ while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart)))
955
+ srcStart += 2;
1117
956
  if (isBoolean<T>()) {
1118
957
  // @ts-expect-error: type
1119
958
  return deserializeBoolean(srcStart, srcEnd);
@@ -1154,7 +993,12 @@ export namespace JSON {
1154
993
  // @ts-expect-error: Defined by transform
1155
994
  if (isDefined(type.__DESERIALIZE_FAST)) {
1156
995
  // @ts-expect-error: Defined by transform
1157
- if (out.__DESERIALIZE_FAST(srcStart, srcEnd, out) == srcEnd)
996
+ const fastEnd = out.__DESERIALIZE_FAST(srcStart, srcEnd, out);
997
+ // Accept the fast path when only trailing whitespace remains.
998
+ if (
999
+ fastEnd != 0 &&
1000
+ JSON.Util.skipWhitespace(fastEnd, srcEnd) == srcEnd
1001
+ )
1158
1002
  return out;
1159
1003
  }
1160
1004
  // @ts-expect-error: Defined by transform
@@ -1173,27 +1017,19 @@ export namespace JSON {
1173
1017
  } else if (type instanceof Array) {
1174
1018
  // @ts-expect-error: type
1175
1019
  return deserializeArray<T>(srcStart, srcEnd, dst);
1176
- } else if (type instanceof Int8Array) {
1177
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1178
- } else if (type instanceof Uint8Array) {
1179
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1180
- } else if (type instanceof Uint8ClampedArray) {
1181
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1182
- } else if (type instanceof Int16Array) {
1183
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1184
- } else if (type instanceof Uint16Array) {
1185
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1186
- } else if (type instanceof Int32Array) {
1187
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1188
- } else if (type instanceof Uint32Array) {
1189
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1190
- } else if (type instanceof Int64Array) {
1191
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1192
- } else if (type instanceof Uint64Array) {
1193
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1194
- } else if (type instanceof Float32Array) {
1195
- return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1196
- } else if (type instanceof Float64Array) {
1020
+ } else if (
1021
+ type instanceof Int8Array ||
1022
+ type instanceof Uint8Array ||
1023
+ type instanceof Uint8ClampedArray ||
1024
+ type instanceof Int16Array ||
1025
+ type instanceof Uint16Array ||
1026
+ type instanceof Int32Array ||
1027
+ type instanceof Uint32Array ||
1028
+ type instanceof Int64Array ||
1029
+ type instanceof Uint64Array ||
1030
+ type instanceof Float32Array ||
1031
+ type instanceof Float64Array
1032
+ ) {
1197
1033
  return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
1198
1034
  } else if (type instanceof ArrayBuffer) {
1199
1035
  return deserializeArrayBuffer(srcStart, srcEnd, dst) as T;
@@ -1239,6 +1075,15 @@ export namespace JSON {
1239
1075
  @inline export function isSpace(code: u16): boolean {
1240
1076
  return code == 0x20 || code - 9 <= 4;
1241
1077
  }
1078
+ /** Advance past JSON whitespace (space, tab, LF, VT, FF, CR). */
1079
+ // @ts-expect-error: decorator
1080
+ @inline export function skipWhitespace(
1081
+ srcStart: usize,
1082
+ srcEnd: usize,
1083
+ ): usize {
1084
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
1085
+ return srcStart;
1086
+ }
1242
1087
  // @ts-expect-error: decorator
1243
1088
  @inline export function scanValueEnd(
1244
1089
  srcStart: usize,
@@ -1302,7 +1147,7 @@ export namespace JSON {
1302
1147
  * Methods for use when using JSON methods inside another JSON method or custom serializer/deserializer
1303
1148
  * Transform will automatically convert JSON.x calls to JSON.internal.x when in a custom (de)serializer
1304
1149
  */
1305
- export namespace internal {
1150
+ namespace internal {
1306
1151
  /**
1307
1152
  * Serializes JSON data. Don't use this directly, use `JSON.stringify` instead.
1308
1153
  * @param data - T
@@ -1342,6 +1187,71 @@ export namespace JSON {
1342
1187
  }
1343
1188
  }
1344
1189
 
1190
+ /**
1191
+ * Shared reference-type serialization chain used by both {@link JSON.stringify}
1192
+ * and {@link JSON.__serialize}. Writes directly to the active buffer. Primitive
1193
+ * and `Date` fast paths are handled by the callers (which have buffer-reuse
1194
+ * optimizations); everything else routes here so the dispatch chain lives once.
1195
+ */
1196
+ // @ts-expect-error: @inline is a valid decorator
1197
+ @inline function serializeReference<T>(data: T): void {
1198
+ if (data instanceof Array) {
1199
+ // @ts-expect-error
1200
+ serializeArray(changetype<nonnull<T>>(data));
1201
+ } else if (data instanceof StaticArray) {
1202
+ // @ts-expect-error
1203
+ serializeStaticArray(changetype<nonnull<T>>(data));
1204
+ } else if (data instanceof Int8Array) {
1205
+ serializeTypedArray<Int8Array>(data);
1206
+ } else if (data instanceof Uint8Array) {
1207
+ serializeTypedArray<Uint8Array>(data);
1208
+ } else if (data instanceof Uint8ClampedArray) {
1209
+ serializeTypedArray<Uint8ClampedArray>(data);
1210
+ } else if (data instanceof Int16Array) {
1211
+ serializeTypedArray<Int16Array>(data);
1212
+ } else if (data instanceof Uint16Array) {
1213
+ serializeTypedArray<Uint16Array>(data);
1214
+ } else if (data instanceof Int32Array) {
1215
+ serializeTypedArray<Int32Array>(data);
1216
+ } else if (data instanceof Uint32Array) {
1217
+ serializeTypedArray<Uint32Array>(data);
1218
+ } else if (data instanceof Int64Array) {
1219
+ serializeTypedArray<Int64Array>(data);
1220
+ } else if (data instanceof Uint64Array) {
1221
+ serializeTypedArray<Uint64Array>(data);
1222
+ } else if (data instanceof Float32Array) {
1223
+ serializeTypedArray<Float32Array>(data);
1224
+ } else if (data instanceof Float64Array) {
1225
+ serializeTypedArray<Float64Array>(data);
1226
+ } else if (data instanceof ArrayBuffer) {
1227
+ const dataStart = changetype<usize>(data);
1228
+ serializeArrayBufferUnsafe(
1229
+ dataStart,
1230
+ changetype<OBJECT>(dataStart - TOTAL_OVERHEAD).rtSize,
1231
+ );
1232
+ } else if (data instanceof Set) {
1233
+ // @ts-expect-error
1234
+ serializeSet(changetype<nonnull<T>>(data));
1235
+ } else if (data instanceof Map) {
1236
+ // @ts-expect-error
1237
+ serializeMap(changetype<nonnull<T>>(data));
1238
+ } else if (data instanceof JSON.Raw) {
1239
+ serializeRaw(data);
1240
+ } else if (data instanceof JSON.Value) {
1241
+ serializeArbitrary(data);
1242
+ } else if (data instanceof JSON.Obj) {
1243
+ serializeObject(data);
1244
+ } else if (data instanceof JSON.Box) {
1245
+ JSON.__serialize(data.value);
1246
+ } else {
1247
+ throw new Error(
1248
+ `Could not serialize data of type '${nameof<T>()}'. ` +
1249
+ `If this is a custom class, add the @json decorator: @json class ${nameof<T>()} { ... }. ` +
1250
+ `Supported types: primitives, string, Array, StaticArray, TypedArray, ArrayBuffer, Map, Date, and @json decorated classes.`,
1251
+ );
1252
+ }
1253
+ }
1254
+
1345
1255
  export enum JSONMode {
1346
1256
  SWAR = 0,
1347
1257
  SIMD = 1,
@@ -1 +1 @@
1
- export { serializeArray } from "../simple/array";
1
+ export { serializeArray } from "../naive/array";
@@ -1 +1 @@
1
- export { serializeBool } from "../simple/bool";
1
+ export { serializeBool } from "../naive/bool";
@@ -1 +1 @@
1
- export { serializeDate } from "../simple/date";
1
+ export { serializeDate } from "../naive/date";
@@ -2,4 +2,4 @@ export {
2
2
  serializeFloat,
3
3
  serializeFloat32,
4
4
  serializeFloat64,
5
- } from "../simple/float";
5
+ } from "../naive/float";
@@ -1 +1 @@
1
- export { serializeInteger } from "../simple/integer";
1
+ export { serializeInteger } from "../naive/integer";
@@ -1 +1 @@
1
- export { serializeMap } from "../simple/map";
1
+ export { serializeMap } from "../naive/map";
@@ -1 +1 @@
1
- export { serializeRaw } from "../simple/raw";
1
+ export { serializeRaw } from "../naive/raw";
@@ -1 +1 @@
1
- export { serializeSet } from "../simple/set";
1
+ export { serializeSet } from "../naive/set";
@@ -1 +1 @@
1
- export { serializeStaticArray } from "../simple/staticarray";
1
+ export { serializeStaticArray } from "../naive/staticarray";
@@ -1,5 +1,5 @@
1
1
  import { JSONMode } from "../..";
2
- import { serializeString as serializeString_NAIVE } from "../simple/string";
2
+ import { serializeString_NAIVE } from "../naive/string";
3
3
  import { serializeString_SIMD } from "../simd/string";
4
4
  import { serializeString_SWAR } from "../swar/string";
5
5
 
@@ -1 +1 @@
1
- export { serializeStruct } from "../simple/struct";
1
+ export { serializeStruct } from "../naive/struct";