json-as 1.3.5 → 1.3.6

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,6 +1,9 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 2026-05-14 - 1.3.6
4
+
5
+ - fix: prevent cross-lane borrow propagation in `detect_escapable_u64_swar_safe` and `detect_escapable_u64_swar_unsafe` by ORing `0x0100_0100_0100_0100` into each 16-bit lane before the SWAR subtraction steps, eliminating corrupted output (`\u00\0\0`) when a NUL or other control character precedes a printable character in SWAR string serialization
6
+ - tooling: fix `bun run bench -- <suite>` argument forwarding so the suite name reaches `run-bench.as.sh` (and `run-bench.js.sh` for non-custom suites) instead of only being passed to `charts:build`
4
7
 
5
8
  ## 2026-05-08 - 1.3.5
6
9
 
@@ -1,6 +1,7 @@
1
1
  import { bs } from "../../../lib/as-bs";
2
2
  import { itoa_buffered } from "util/number";
3
3
 
4
+
4
5
  @inline
5
6
  export function serializeIntegerUnsafe<T extends number>(data: T): void {
6
7
  const bytesWritten = itoa_buffered(bs.offset, data) << 1;
@@ -305,7 +305,10 @@ export function serializeString_SWAR_ExperimentalTableEscapes(src: string): void
305
305
  @inline export function detect_escapable_u64_swar_safe(block: u64): u64 {
306
306
  const hi = block & 0xff00_ff00_ff00_ff00;
307
307
  const lo = block & 0x00ff_00ff_00ff_00ff;
308
- const ascii_mask = ((lo - 0x0020_0020_0020_0020) | ((lo ^ 0x0022_0022_0022_0022) - 0x0001_0001_0001_0001) | ((lo ^ 0x005c_005c_005c_005c) - 0x0001_0001_0001_0001)) & (0x0080_0080_0080_0080 & ~lo);
308
+ // Setting bit 8 of each 16-bit lane (high byte LSB) prevents borrow from a
309
+ // low byte underflow from propagating across lane boundaries into the next lane.
310
+ const loSafe = lo | 0x0100_0100_0100_0100;
311
+ const ascii_mask = ((loSafe - 0x0020_0020_0020_0020) | ((loSafe ^ 0x0022_0022_0022_0022) - 0x0001_0001_0001_0001) | ((loSafe ^ 0x005c_005c_005c_005c) - 0x0001_0001_0001_0001)) & (0x0080_0080_0080_0080 & ~lo);
309
312
  if (hi == 0) return ascii_mask;
310
313
  const hi_mask = ((block - 0x0100_0100_0100_0100) & ~block & 0x8000_8000_8000_8000) ^ 0x8000_8000_8000_8000;
311
314
  return (ascii_mask & (~hi_mask >> 8)) | hi_mask;
@@ -314,10 +317,11 @@ export function serializeString_SWAR_ExperimentalTableEscapes(src: string): void
314
317
  // @ts-expect-error: @inline is a valid decorator
315
318
  @inline export function detect_escapable_u64_swar_unsafe(block: u64): u64 {
316
319
  const lo = block & 0x00ff_00ff_00ff_00ff;
320
+ const loSafe = lo | 0x0100_0100_0100_0100;
317
321
  const ascii_mask =
318
- ((lo - 0x0020_0020_0020_0020) | // lt 0x20
319
- ((lo ^ 0x0022_0022_0022_0022) - 0x0001_0001_0001_0001) | // eq 0x22
320
- ((lo ^ 0x005c_005c_005c_005c) - 0x0001_0001_0001_0001)) & // eq 0x5C
322
+ ((loSafe - 0x0020_0020_0020_0020) | // lt 0x20
323
+ ((loSafe ^ 0x0022_0022_0022_0022) - 0x0001_0001_0001_0001) | // eq 0x22
324
+ ((loSafe ^ 0x005c_005c_005c_005c) - 0x0001_0001_0001_0001)) & // eq 0x5C
321
325
  (0x0080_0080_0080_0080 & ~lo); // replace each lane with 0x80
322
326
  const hi = block & 0xff00_ff00_ff00_ff00; // add possible non-ascii code units
323
327
  return ascii_mask | hi;
@@ -1,24 +1,4 @@
1
1
  {
2
2
  "extends": "assemblyscript/std/assembly.json",
3
- "include": ["./**/*.ts"],
4
- "compilerOptions": {
5
- "allowImportingTsExtensions": true,
6
- "experimentalDecorators": true,
7
- "emitDecoratorMetadata": true,
8
-
9
- "strict": true,
10
- "noImplicitAny": true,
11
- "strictNullChecks": false,
12
- "strictFunctionTypes": true,
13
- "strictBindCallApply": true,
14
- "strictPropertyInitialization": false,
15
- "noImplicitThis": true,
16
- "alwaysStrict": true,
17
-
18
- "noUnusedLocals": false,
19
- "noUnusedParameters": false,
20
- "noImplicitReturns": true,
21
- "noFallthroughCasesInSwitch": true,
22
- "noUncheckedIndexedAccess": false
23
- }
3
+ "include": ["./**/*.ts"]
24
4
  }
package/lib/as-bs.ts CHANGED
@@ -330,14 +330,14 @@ export namespace sc {
330
330
  // @ts-expect-error: JSON_CACHE may not be defined. If so, it will default to false.
331
331
  export const CACHE_ENABLED: bool = isDefined(JSON_CACHE) ? JSON_CACHE : false;
332
332
  // @ts-expect-error: JSON_CACHE_SIZE may not be defined. If so, it will default to 1MB.
333
- export const CACHE_BYTES: usize = isDefined(JSON_CACHE_SIZE) ? <usize>JSON_CACHE_SIZE : (1 << 20);
333
+ export const CACHE_BYTES: usize = isDefined(JSON_CACHE_SIZE) ? <usize>JSON_CACHE_SIZE : 1 << 20;
334
334
  /** Minimum serialized length to cache - smaller outputs aren't worth caching */
335
335
  export const MIN_CACHE_LEN: usize = 128;
336
336
  /** Size of the circular arena buffer for cached strings */
337
337
  export const ARENA_SIZE: usize = CACHE_BYTES >= MIN_CACHE_LEN ? CACHE_BYTES : MIN_CACHE_LEN;
338
338
 
339
339
  /** Number of cache slots (power of 2 for efficient masking). Set to 0 when caching disabled. */
340
- const CACHE_SIZE_BASE: i32 = CACHE_ENABLED ? i32((ARENA_SIZE >> 10) >= 1 ? (ARENA_SIZE >> 10) : 1) : 0;
340
+ const CACHE_SIZE_BASE: i32 = CACHE_ENABLED ? i32(ARENA_SIZE >> 10 >= 1 ? ARENA_SIZE >> 10 : 1) : 0;
341
341
  export const CACHE_SIZE: usize = CACHE_ENABLED ? <usize>(1 << (32 - clz<i32>(CACHE_SIZE_BASE - 1))) : 0;
342
342
  /** Bitmask for fast modulo operation on cache index */
343
343
  export const CACHE_MASK: usize = CACHE_SIZE > 0 ? CACHE_SIZE - 1 : 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "1.3.5",
3
+ "version": "1.3.6",
4
4
  "author": "Jairus Tanaka",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,12 +12,13 @@
12
12
  "@assemblyscript/wasi-shim": "^0.1.0",
13
13
  "@eslint/js": "^10.0.1",
14
14
  "@types/node": "^25.6.2",
15
- "as-test": "1.0.16",
15
+ "as-test": "^1.1.6",
16
16
  "assemblyscript": "^0.28.17",
17
17
  "assemblyscript-prettier": "^3.0.4",
18
18
  "chartjs-node-canvas": "^5.0.0",
19
19
  "chartjs-plugin-datalabels": "^2.2.0",
20
20
  "eslint": "^10.3.0",
21
+ "husky": "^9.1.7",
21
22
  "prettier": "3.8.3",
22
23
  "serve": "^14.2.6",
23
24
  "tinybench": "^6.0.1",
@@ -88,7 +89,7 @@
88
89
  "test:fuzz": "ast test --fuzz --parallel",
89
90
  "test:ci": "ast test --parallel --clean",
90
91
  "test:coverage": "ast test --enable coverage",
91
- "bench": "npm run bench:as && npm run bench:js && npm run charts:build",
92
+ "bench": "bash -c 'bash ./scripts/run-bench.as.sh \"$@\" && { arg=\"${1:-}\"; if [ -z \"$arg\" ] || [ \"${arg#custom/}\" = \"$arg\" ]; then bash ./scripts/run-bench.js.sh \"$@\"; fi; } && bash ./scripts/build-charts.sh' --",
92
93
  "bench:as": "bash ./scripts/run-bench.as.sh",
93
94
  "bench:js": "bash ./scripts/run-bench.js.sh",
94
95
  "charts": "bun run charts:build && bun run charts:serve",
@@ -105,12 +106,16 @@
105
106
  "format": "prettier -w .",
106
107
  "lint": "eslint . --no-warn-ignored",
107
108
  "lint:fix": "eslint . --fix --no-warn-ignored",
109
+ "commitmsg:verify": "bash ./scripts/commit-msg.sh",
110
+ "precommit:verify": "bash ./scripts/pre-commit.sh",
111
+ "prepush:verify": "bash ./scripts/pre-push.sh",
108
112
  "typecheck": "tsc -p ./transform --noEmit",
109
113
  "clean": "rm -rf build/ transform/lib/",
110
114
  "prebuild": "npm run clean",
111
115
  "build": "npm run build:transform",
112
116
  "pretest": "npm run build:transform",
113
- "check": "npm run typecheck && npm run lint"
117
+ "check": "npm run typecheck && npm run lint",
118
+ "prepare": "husky"
114
119
  },
115
120
  "type": "module",
116
121
  "types": "assembly/index.ts"