Skip to content

Commit 6168e4d

Browse files
committed
release:v1.3.1
1 parent 3e7debb commit 6168e4d

3 files changed

Lines changed: 40 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Changelog
22

3-
## 2026-03-25 - 1.3.1
3+
## Unreleased
44

55
- feat: allow `JSON.Value` to store and re-serialize built-in typed arrays and `ArrayBuffer`
66
- feat: support `JSON.stringify<ArrayBuffer>(...)` directly without a dedicated helper
@@ -17,7 +17,9 @@
1717
- fix: rewrite nested `JSON.parse(...)` calls inside custom serializers and deserializers to `JSON.internal.parse(...)`, matching the existing internal stringify rewrite and documented behavior
1818
- docs: clarify that custom serializers and deserializers must always produce and consume valid JSON
1919
- docs: document how subclassing built-in container types behaves, including when `@json` custom overrides take effect
20+
- fix: stop naive string deserialization scratch allocations from growing across repeated large payload parses by using local `ensureSize(...)` scratch capacity instead of serialization-style proposed growth
2021
- tests: expand custom serializer/deserializer coverage for nullable fields, multiple custom fields, escaped content, whitespace, and repeated round-trips
22+
- tests: add a repeated large string-heavy struct parse regression that exercises the naive deserialization scratch path
2123
- tests: add override coverage for plain and custom subclasses of `Array`, `Map`, `Set`, and typed arrays
2224
- tests: add `JSON.Value` regressions for undecorated and decorated typed-array subclasses
2325
- tests: add regression coverage for generated `@json` subclasses inheriting stdlib typed-array fields

assembly/__tests__/struct.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,39 @@ describe("Extended regression coverage - nested and escaped payloads", () => {
196196
expect(JSON.stringify(JSON.parse<i32[][]>("[[1],[2,3],[]]"))).toBe("[[1],[2,3],[]]");
197197
expect(JSON.stringify(JSON.parse<string>('"line\\nbreak"'))).toBe('"line\\nbreak"');
198198
});
199+
200+
describe("Should keep naive string scratch space bounded across repeated large struct parses", () => {
201+
const payload = buildStringHeavyPayload();
202+
203+
for (let i = 0; i < 256; i++) {
204+
const parsed = JSON.parse<StringHeavyPayload>(payload);
205+
expect(parsed.title.length).toBe(704);
206+
expect(parsed.repo.length).toBe(608);
207+
expect(parsed.summary.length).toBe(704);
208+
expect(parsed.footer.length).toBe(384);
209+
}
210+
});
211+
212+
function repeatChunk(chunk: string, count: i32): string {
213+
let out = "";
214+
for (let i = 0; i < count; i++) out += chunk;
215+
return out;
216+
}
217+
218+
function buildStringHeavyPayload(): string {
219+
const title = repeatChunk("alpha-beta-", 64);
220+
const repo = repeatChunk("octocat/repository/", 32);
221+
const summary = repeatChunk("payload-segment-", 44);
222+
const footer = repeatChunk("final-block-", 32);
223+
224+
return '{"title":"' + title + '","repo":"' + repo + '","summary":"' + summary + '","footer":"' + footer + '"}';
225+
}
226+
227+
228+
@json
229+
class StringHeavyPayload {
230+
title: string = "";
231+
repo: string = "";
232+
summary: string = "";
233+
footer: string = "";
234+
}

assembly/deserialize/simple/string.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { hex4_to_u16_swar } from "../../util/swar";
3131
srcStart += 2;
3232
srcEnd -= 2;
3333
const outStart = bs.offset - bs.buffer;
34-
bs.proposeSize(u32(srcEnd - srcStart));
34+
bs.ensureSize(u32(srcEnd - srcStart));
3535

3636
while (srcStart < srcEnd) {
3737
const block = load<u16>(srcStart);

0 commit comments

Comments
 (0)