fix: prevent JS stack overflow from crashing the process#15
Draft
wytzepiet wants to merge 2 commits into
Draft
Conversation
…hing QuickJS's stack overflow check is a soft limit measured against the native thread stack. If max_stack_size reaches the thread stack, JS overflows the real stack first and the process aborts (SIGABRT) instead of throwing a catchable RangeError. JS runs on flutter_rust_bridge's tokio workers (2 MB stack, which fjs does not set), and `0` means "no limit" to QuickJS — both overflow the native stack. Clamp the requested budget to 3/4 of the thread stack, mapping 0 to that ceiling, so overflow stays a catchable RangeError. Tests cover that eval and pumped jobs reach the same depth, a bigger budget reaches deeper, and an over-large budget no longer crashes a worker thread. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
flutter_rust_bridge runs Rust on tokio workers whose stack defaults to 2 MB, which fjs cannot resize. That is far below a browser's ~8 MB JS stack, so deep-but-normal JS (e.g. a recursive UI render) overflows the native stack and aborts the process instead of throwing. Run every JS entry (eval, call, module eval, job pump) on fjs's own runtime whose threads have an 8 MB stack, via a small `with_js` helper and a global `js_executor`. QuickJS refreshes its overflow baseline on each entry, so spreading JS across these threads stays correct. Default the budget to 6 MB (3/4 of the thread stack) and keep the clamp relative to it, so deep UIs render while overflow stays a catchable RangeError. The sync runtime, which runs on the caller's thread, keeps its conservative ceiling. No API changes and no new bridged methods; `execute_pending_job`'s signature is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <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.
Problem
QuickJS's stack overflow check is a soft limit: it only fires once JS grows past
max_stack_size, and it does not know the real native thread stack. JS runs on flutter_rust_bridge's tokio workers, whose stack defaults to 2 MB. So:max_stack_sizeis set near or above the thread stack (or0, which QuickJS treats as "no limit"), JS overflows the native stack first and the whole process aborts (SIGABRT) instead of throwing a catchableRangeError.Fix
max_stack_sizebelow the thread stack, mapping0to that ceiling, so overflow is always a catchableRangeError, never a crash.No public API changes, no new bridged methods, no codegen.
execute_pending_job's signature is unchanged.Tests
Host-side tests (no device): eval and pumped jobs reach the same depth and both throw a catchable error; a bigger budget reaches deeper on both paths; the default budget is generous; an over-large budget is clamped instead of crashing a worker thread.
🤖 Generated with Claude Code