[PR #6146] fix(javascript): bound member-mutation traversal and add max-heap-mb to compare-application-versions (#6127) #7161

Open
opened 2026-11-01 21:45:50 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/6146
Author: @bhedanikhilkumar-code
Created: 10/21/2026
Status: 🔄 Open

Base: main ← Head: fix/issue-6127-javascript-worker-memory


📝 Commits (1)

  • 2489e6c fix(javascript): bound member-mutation traversal and add max-heap-mb to compare-application-versions (#6127)

📊 Changes

10 files changed (+258 additions, -12 deletions)

View changed files

📝 scripts/rea.mjs (+49 -0)
📝 src/application/Utf8JsonInput.ts (+1 -1)
📝 src/application/javascript/JavaScriptApplicationWorkflowService.ts (+3 -0)
📝 src/cli/applicationCommands.ts (+32 -6)
📝 src/contracts/javascript/applicationWorkflowInputContracts.ts (+1 -0)
📝 src/domain/javascript/javascriptApplicationVersionComparison.test.ts (+12 -0)
📝 src/domain/javascript/javascriptApplicationVersionComparisonSchemas.ts (+5 -0)
📝 src/domain/javascript/javascriptSemanticAnalysis.member_mutations.test.ts (+46 -0)
📝 src/domain/javascript/javascriptSemanticMemberMutations.ts (+103 -5)
📝 src/domain/javascript/javascriptSemanticResourceLimits.ts (+6 -0)

📄 Description

Summary

Fixes #6127

Bounds worklist expansion, total steps, and fixpoint rounds during semantic member-mutation indexing to prevent worker heap exhaustion on minified Turbopack bootstrap and vendor chunks, and adds --max-heap-mb support to compare-application-versions with CLI self-respawn when higher heap capacity is requested.

Problem and expected behavior

  1. JavaScript Worker OOM on 233 KB file (#6127): On bundled/minified chunks (such as Next.js/Turbopack bootstrap scripts), wide conditional branch diamonds, escaped method results, and iterable reference fixpoint evaluations previously had no worklist bounds or iteration ceilings in collectSemanticMemberMutationsSteps. This led to exponential/runaway object allocation, Set/Map cache thrashing, and exhaustion of a 6 GiB worker heap on a 233 KB file. The expected behavior is that resource-constrained analyses bound worklist exploration and return partial coverage with resourceLimits: ["alias-selections"].
  2. Missing --max-heap-mb on compare-application-versions (#6127): When comparing large version graphs (~230 MB evidence files), admitJsonAssembly requires available V8 heap headroom against projected graph memory. At the default ~4 GiB CLI heap, it threw AnalysisResourceConstraintError (resource_constraint). Users were forced to manually configure NODE_OPTIONS=--max-old-space-size.

Change and scope

  • Semantic Member Mutation Bounds (src/domain/javascript/):
    • Added SEMANTIC_MEMBER_MUTATION_WORKLIST_LIMIT = 512, SEMANTIC_MEMBER_MUTATION_TOTAL_STEPS_LIMIT = 32_768, and SEMANTIC_MEMBER_MUTATION_FIXPOINT_ROUNDS_LIMIT = 16 in javascriptSemanticResourceLimits.ts.
    • In collectSemanticMemberMutationsSteps (javascriptSemanticMemberMutations.ts):
      • Bounded pending worklist iteration to SEMANTIC_MEMBER_MUTATION_WORKLIST_LIMIT.
      • Bounded cumulative mutation steps across the phase to SEMANTIC_MEMBER_MUTATION_TOTAL_STEPS_LIMIT.
      • Bounded the pendingReferences / iterableReferences / deferredMapReceivers while loop to SEMANTIC_MEMBER_MUTATION_FIXPOINT_ROUNDS_LIMIT.
      • Added caching with a WeakMap<IterableReference, string> to avoid re-evaluating unchanged iterable references across loop rounds.
      • When any bound is hit, records "alias-selections" into state.valueResourceLimits, marking coverage as partial with resourceLimits: ["alias-selections"].
  • compare-application-versions CLI & Contract (src/cli/, src/domain/, src/contracts/, scripts/):
    • Added max_heap_mb to compareApplicationVersionsInputSchema and compareApplicationVersionsRequestSchema.
    • Added options: z.object({ maxHeapMb: javaScriptAnalysisResourceControlsSchema.shape.max_heap_mb }) to compareApplicationVersions CLI registration in applicationCommands.ts.
    • Preserved caller-selected max_heap_mb in createApplicationVersionComparisonEvidence parameters.
    • Added CLI self-respawn in scripts/rea.mjs: when --max-heap-mb is passed and exceeds current V8 heap_size_limit, respawns Node with --max-old-space-size=${requestedMaxHeapMb}.
    • Updated JSON_INPUT_RESOURCE_REMEDIATION in Utf8JsonInput.ts to advise using --max-heap-mb when comparing large version graphs.

Follow the contribution scope: Ordinary fix and operational CLI option within existing boundaries; maintainer scope decision is not applicable.

Contract and boundary impact

  • Semantic owner and earliest changed stage: src/domain/javascript/javascriptSemanticMemberMutations.ts and src/domain/javascript/javascriptApplicationVersionComparisonSchemas.ts.
  • Contribution scope fit and linked maintainer decision: not applicable (within existing CLI/domain boundaries).
  • CLI and MCP/tool-catalog contract: compare-application-versions now accepts --max-heap-mb <megabytes> CLI option; request schemas and input schemas accept optional max_heap_mb.
  • Provider, bridge, target-format, or platform compatibility: Cross-platform Node.js; handles V8 heap limit respawn transparently on CLI.
  • Evidence, artifact, provenance, or reconstruction contract: Preserves max_heap_mb in comparison Evidence parameters when supplied; bounds member mutation analysis cleanly through resourceLimits: ["alias-selections"].
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): none.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: none.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated:
    • src/domain/javascript/javascriptSemanticAnalysis.member_mutations.test.ts: Added test bounds worklist expansion on exponential alias diamonds (#6127) verifying alias-selections resource limit is flagged under wide branch diamonds.
    • src/domain/javascript/javascriptApplicationVersionComparison.test.ts: Added test accepts max_heap_mb in comparison input (#6127) verifying compareApplicationVersionsInputSchema accepts max_heap_mb.
  • Base reproduction or other evidence: Verified that under wide alias expansions, worklist bounds halt unbounded expansion and emit coverage.resourceLimits: ["alias-selections"].
  • User-visible CLI/MCP output: rea compare-application-versions <inputJson> --max-heap-mb <mb> executes with allocated heap headroom without failing with resource_constraint.
  • Remaining proof gaps: none.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm run check:fast — passed (typecheck and lint clean across repo)
  • npm run test:local -- src/domain/javascript/javascriptSemanticAnalysis.member_mutations.test.ts src/domain/javascript/javascriptApplicationVersionComparison.test.ts — 201 passed
  • npm run test:local -- tests/conformance/readmeConsistency.test.ts — 5 passed

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Additive and backward-compatible.
  • Real Hopper/Ghidra, browser, or OS coverage: Node.js on Linux, macOS, and Windows.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: Bounding unbounded iterations protects worker stability and prevents DoS through pathological AST alias diamonds.

Author readiness

Human owner: @bhedanikhilkumar-code

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/6146 **Author:** [@bhedanikhilkumar-code](https://github.com/bhedanikhilkumar-code) **Created:** 10/21/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/issue-6127-javascript-worker-memory` --- ### 📝 Commits (1) - [`2489e6c`](https://github.com/morluto/rea/commit/2489e6c6ba5d9fc145240d487d125a5c833c9e00) fix(javascript): bound member-mutation traversal and add max-heap-mb to compare-application-versions (#6127) ### 📊 Changes **10 files changed** (+258 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `scripts/rea.mjs` (+49 -0) 📝 `src/application/Utf8JsonInput.ts` (+1 -1) 📝 `src/application/javascript/JavaScriptApplicationWorkflowService.ts` (+3 -0) 📝 `src/cli/applicationCommands.ts` (+32 -6) 📝 `src/contracts/javascript/applicationWorkflowInputContracts.ts` (+1 -0) 📝 `src/domain/javascript/javascriptApplicationVersionComparison.test.ts` (+12 -0) 📝 `src/domain/javascript/javascriptApplicationVersionComparisonSchemas.ts` (+5 -0) 📝 `src/domain/javascript/javascriptSemanticAnalysis.member_mutations.test.ts` (+46 -0) 📝 `src/domain/javascript/javascriptSemanticMemberMutations.ts` (+103 -5) 📝 `src/domain/javascript/javascriptSemanticResourceLimits.ts` (+6 -0) </details> ### 📄 Description ## Summary Fixes #6127 Bounds worklist expansion, total steps, and fixpoint rounds during semantic member-mutation indexing to prevent worker heap exhaustion on minified Turbopack bootstrap and vendor chunks, and adds `--max-heap-mb` support to `compare-application-versions` with CLI self-respawn when higher heap capacity is requested. ## Problem and expected behavior 1. **JavaScript Worker OOM on 233 KB file (#6127):** On bundled/minified chunks (such as Next.js/Turbopack bootstrap scripts), wide conditional branch diamonds, escaped method results, and iterable reference fixpoint evaluations previously had no worklist bounds or iteration ceilings in `collectSemanticMemberMutationsSteps`. This led to exponential/runaway object allocation, Set/Map cache thrashing, and exhaustion of a 6 GiB worker heap on a 233 KB file. The expected behavior is that resource-constrained analyses bound worklist exploration and return partial coverage with `resourceLimits: ["alias-selections"]`. 2. **Missing `--max-heap-mb` on `compare-application-versions` (#6127):** When comparing large version graphs (~230 MB evidence files), `admitJsonAssembly` requires available V8 heap headroom against projected graph memory. At the default ~4 GiB CLI heap, it threw `AnalysisResourceConstraintError` (`resource_constraint`). Users were forced to manually configure `NODE_OPTIONS=--max-old-space-size`. ## Change and scope - **Semantic Member Mutation Bounds (`src/domain/javascript/`):** - Added `SEMANTIC_MEMBER_MUTATION_WORKLIST_LIMIT = 512`, `SEMANTIC_MEMBER_MUTATION_TOTAL_STEPS_LIMIT = 32_768`, and `SEMANTIC_MEMBER_MUTATION_FIXPOINT_ROUNDS_LIMIT = 16` in `javascriptSemanticResourceLimits.ts`. - In `collectSemanticMemberMutationsSteps` (`javascriptSemanticMemberMutations.ts`): - Bounded `pending` worklist iteration to `SEMANTIC_MEMBER_MUTATION_WORKLIST_LIMIT`. - Bounded cumulative mutation steps across the phase to `SEMANTIC_MEMBER_MUTATION_TOTAL_STEPS_LIMIT`. - Bounded the `pendingReferences` / `iterableReferences` / `deferredMapReceivers` `while` loop to `SEMANTIC_MEMBER_MUTATION_FIXPOINT_ROUNDS_LIMIT`. - Added caching with a `WeakMap<IterableReference, string>` to avoid re-evaluating unchanged iterable references across loop rounds. - When any bound is hit, records `"alias-selections"` into `state.valueResourceLimits`, marking coverage as partial with `resourceLimits: ["alias-selections"]`. - **`compare-application-versions` CLI & Contract (`src/cli/`, `src/domain/`, `src/contracts/`, `scripts/`):** - Added `max_heap_mb` to `compareApplicationVersionsInputSchema` and `compareApplicationVersionsRequestSchema`. - Added `options: z.object({ maxHeapMb: javaScriptAnalysisResourceControlsSchema.shape.max_heap_mb })` to `compareApplicationVersions` CLI registration in `applicationCommands.ts`. - Preserved caller-selected `max_heap_mb` in `createApplicationVersionComparisonEvidence` parameters. - Added CLI self-respawn in `scripts/rea.mjs`: when `--max-heap-mb` is passed and exceeds current V8 `heap_size_limit`, respawns Node with `--max-old-space-size=${requestedMaxHeapMb}`. - Updated `JSON_INPUT_RESOURCE_REMEDIATION` in `Utf8JsonInput.ts` to advise using `--max-heap-mb` when comparing large version graphs. Follow the contribution scope: Ordinary fix and operational CLI option within existing boundaries; maintainer scope decision is not applicable. ## Contract and boundary impact - Semantic owner and earliest changed stage: `src/domain/javascript/javascriptSemanticMemberMutations.ts` and `src/domain/javascript/javascriptApplicationVersionComparisonSchemas.ts`. - Contribution scope fit and linked maintainer decision: not applicable (within existing CLI/domain boundaries). - CLI and MCP/tool-catalog contract: `compare-application-versions` now accepts `--max-heap-mb <megabytes>` CLI option; request schemas and input schemas accept optional `max_heap_mb`. - Provider, bridge, target-format, or platform compatibility: Cross-platform Node.js; handles V8 heap limit respawn transparently on CLI. - Evidence, artifact, provenance, or reconstruction contract: Preserves `max_heap_mb` in comparison Evidence parameters when supplied; bounds member mutation analysis cleanly through `resourceLimits: ["alias-selections"]`. - Target selection, authority, upstream behavior, and cleanup details (if applicable): none. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: none. Expected effects: - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated: - `src/domain/javascript/javascriptSemanticAnalysis.member_mutations.test.ts`: Added test `bounds worklist expansion on exponential alias diamonds (#6127)` verifying `alias-selections` resource limit is flagged under wide branch diamonds. - `src/domain/javascript/javascriptApplicationVersionComparison.test.ts`: Added test `accepts max_heap_mb in comparison input (#6127)` verifying `compareApplicationVersionsInputSchema` accepts `max_heap_mb`. - Base reproduction or other evidence: Verified that under wide alias expansions, worklist bounds halt unbounded expansion and emit `coverage.resourceLimits: ["alias-selections"]`. - User-visible CLI/MCP output: `rea compare-application-versions <inputJson> --max-heap-mb <mb>` executes with allocated heap headroom without failing with `resource_constraint`. - Remaining proof gaps: none. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm run check:fast` — passed (typecheck and lint clean across repo) - `npm run test:local -- src/domain/javascript/javascriptSemanticAnalysis.member_mutations.test.ts src/domain/javascript/javascriptApplicationVersionComparison.test.ts` — 201 passed - `npm run test:local -- tests/conformance/readmeConsistency.test.ts` — 5 passed ## Compatibility, safety, and release - Breaking changes or migration steps: none. Additive and backward-compatible. - Real Hopper/Ghidra, browser, or OS coverage: Node.js on Linux, macOS, and Windows. - Package or release metadata impact: none. - Security, privacy, process, or containment review: Bounding unbounded iterations protects worker stability and prevents DoS through pathological AST alias diamonds. ## Author readiness Human owner: @bhedanikhilkumar-code - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#7161
No description provided.