Repository navigation
Conversation
newVariant(variant, { maxMemoryBytes }) instantiates the module with a WebAssembly.Memory whose
maximum is the cap. setMemoryLimit depends on QuickJS's allocation accounting, which undercounts
on Emscripten builds; the cap does not. At the cap, allocation fails inside the module and guest
code gets a catchable InternalError, the runtime disposes cleanly, and the heap never exceeds it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Layer: TypeScript wrapper (
newVariantoption). No C or build change.Review just this PR: it is standalone on
main, ~30 lines of source plus tests and a README note.Related: #275 (under-enforced
setMemoryLimit), #207 (memory accounting). Independent of the #248 stack.What
newVariant(variant, { maxMemoryBytes })instantiates the module with aWebAssembly.Memorywhosemaximumis the cap (the variants already build withIMPORTED_MEMORY=1, sowasmMemorycould always do this by hand; this just makes it a one-liner and tests it).setMemoryLimitgoes through QuickJS's own allocation accounting, which undercounts on Emscripten builds: with a 32 MiB limit a guest still grew the heap to 63 MiB. The cap does not depend on that accounting, and it also bounds host-side buffers and the 5 MiB wasm stack. It doesn't replace fixing the accounting (#207'smalloc_usable_sizedirection); it is the backstop.Test:
memory-cap.test.ts, on quickjs, quickjs-ng, and both asyncify builds (release). With a 64 MiB cap a guest allocating ~1 MiB strings: (1) gets a catchableInternalError; (2) peakmemory.buffer.byteLength(sampled from a host callback each iteration) never exceeds the cap; (3) the module still evaluates code and the runtime/context dispose without thelist_empty(gc_obj_list)assertion; (4) the same holds withsetMemoryLimit(1 GiB). Plus validation (<16 MiB, or combined withwasmMemory, rejected). All 14 fail without the change (heap peaked at 449 MB vs the 64 MiB cap).Verified on: full suite on this branch: 765 passed, 0 failed.
Not covered: debug (sanitizer) variants abort the whole module when the heap can't grow, so they are excluded and the option's docs say so; no leak-sanitizer check under exhaustion for the same reason. Assumes Emscripten's default 16 MiB initial memory, which no variant overrides (the tests would catch a change).
Behavior change: none unless the option is passed.
🤖 Generated with Claude Code