[PR #1351] [MERGED] fix(javascript): resolve exported callables through lexical bindings #2818

Closed
opened 2026-10-17 21:10:38 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1351
Author: @Y0UW1SH
Created: 10/9/2026
Status: ✅ Merged
Merged: 10/9/2026
Merged by: @morluto

Base: main ← Head: fix/javascript-exported-function-bindings


📝 Commits (5)

  • 5939356 fix(javascript): resolve exported callables through lexical bindings
  • b0e5be9 fix(javascript): preserve export scope and hoisted writes
  • 0e59898 test(javascript): consolidate export binding assertions
  • 3a9c1b1 fix(javascript): account for skipped initializers and loop binding writes
  • 085818d fix(javascript): preserve parameters copied into body variables

📊 Changes

6 files changed (+929 additions, -96 deletions)

View changed files

📝 src/domain/javascript/javascriptSemanticAnalysis.ts (+163 -7)
📝 src/domain/javascript/javascriptSemanticMemberMutations.ts (+4 -2)
📝 src/domain/javascript/javascriptSemanticProjection.ts (+115 -73)
📝 src/domain/javascript/javascriptSemanticReturns.ts (+23 -14)
📝 src/domain/javascript/javascriptSemanticState.ts (+6 -0)
➕ tests/acceptance/applications/exportedFunctionBindingsCli.test.ts (+618 -0)

📄 Description

Summary

Fix exported callable resolution so reassigned bindings cannot retain stale return shapes and private function names cannot attach to unrelated exports. Also resolve nested CommonJS exports through their actual lexical binding and account for writes before hoisted declarations. Reported directly during a source audit; no issue number was supplied.

Problem and expected behavior

Two versions that reassign an exported function to return count: 1 and count: 2 incorrectly compared as zero changes and zero unknowns. Callable IDs and display names bypassed binding checks. Root-scope lookup also associated nested CommonJS exports with unrelated outer bindings, and writes collected before declarations could be dropped or assigned to the wrong scope.

Uncertain, multiply assigned exports must report the existing unavailable/unknown result. Stable function exports and aliases must still compare their actual return shapes.

Change and scope

  • Resolve named export links through the lexical binding captured at the export site; remove callable display-name matching.
  • Retain direct callable IDs for exports without local bindings, including anonymous defaults and directly exported private expressions.
  • Collect declarations before resolving assignment, update, and loop writes, preserving hoisted targets and local shadowing.
  • Keep parameter expressions outside body declarations and evaluate computed method keys in their containing scope. Traverse binding patterns only when detecting parameter expressions.
  • Preserve the existing single-initializer and alias-cycle checks. Exact execution-order selection after multiple writes remains outside this static model.

Contract and boundary impact

  • Semantic owner and earliest changed stages: JavaScript lexical definition collection and module-to-callable resolution.
  • CLI/MCP schemas, inputs, and tool catalog are unchanged; corrected associations use existing selected or unavailable/unknown outcomes.
  • Artifact identity and source provenance are preserved. Production analysis remains inert; tests execute only source-owned fixtures.
  • No provider, dependency, authorization, package, installation, or generated metadata changes.

Evidence and regression coverage

  • Twenty-nine compiled CLI acceptance cases cover reassignment, private-name collisions, stable exports, hoisted writes, local shadowing, nested/block CommonJS exports, parameter defaults and closures, computed destructuring keys, and object/class computed method keys.
  • Node execution independently verifies the fixture exports and the real count: 1 versus count: 2 behavior.
  • Regressions failed before their respective fixes, including six follow-up lexical/hoisting cases and eight function-evaluation-context cases.
  • Reassigned or unrelated numeric exports expose left.status = right.status = "unavailable", summary.unknown = 1, and partial coverage. Stable callable comparisons retain the /count change.
  • Real stdio MCP output matches CLI output for private-name and nested CommonJS numeric collisions.

Validation performed

  • npm run test:local -- src/domain/javascript/*.test.ts: 557 passed across 36 files.
  • Final npm run test:focused -- tests/acceptance/applications/exportedFunctionBindingsCli.test.ts: all 29 compiled CLI/MCP regression cases passed.
  • npm run check: passed, including typecheck, lint, formatting, unused-code, metadata, and module-boundary checks.
  • npm run check:ci: passed, including duplication and TODO checks. Shared assertions reduce local duplicated lines to 2.49% under the 2.5% gate.
  • npm run verify:test-discovery: all 696 local test files discovered exactly once.
  • git diff --check: passed.
  • Independent read-only review and compiled-runtime probes: no remaining blocking findings; verified parameter ownership, capture ancestry, nested aliases, and computed-key scope restoration.

Compatibility and review

No schema migration or execution authority change. Real Hopper/Ghidra and browser verification was not performed because this changes static JavaScript binding resolution only. Full deterministic coverage remains with CI as directed by the repository's focused-check workflow.

  • Concrete bug and reason for no linked issue documented.
  • Regression coverage exercises observable CLI/MCP behavior and independent runtime fixture oracles.
  • Unsupported and uncertain outcomes remain visible.
  • No owning schema or generated metadata update required.
  • Final diff checked for unrelated changes, credentials, 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/1351 **Author:** [@Y0UW1SH](https://github.com/Y0UW1SH) **Created:** 10/9/2026 **Status:** ✅ Merged **Merged:** 10/9/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/javascript-exported-function-bindings` --- ### 📝 Commits (5) - [`5939356`](https://github.com/morluto/rea/commit/593935627387ad1be6346ae12d93b39e1ec8bea1) fix(javascript): resolve exported callables through lexical bindings - [`b0e5be9`](https://github.com/morluto/rea/commit/b0e5be9973bb65ebd8f5ba4e3d77f9aff582f04d) fix(javascript): preserve export scope and hoisted writes - [`0e59898`](https://github.com/morluto/rea/commit/0e59898a8342caac9e426354aa1919d6fafcf884) test(javascript): consolidate export binding assertions - [`3a9c1b1`](https://github.com/morluto/rea/commit/3a9c1b1c53e7bf29aad70d37a80e7f4e52cf650d) fix(javascript): account for skipped initializers and loop binding writes - [`085818d`](https://github.com/morluto/rea/commit/085818d2126a732499a68a41968c80c1e783375e) fix(javascript): preserve parameters copied into body variables ### 📊 Changes **6 files changed** (+929 additions, -96 deletions) <details> <summary>View changed files</summary> 📝 `src/domain/javascript/javascriptSemanticAnalysis.ts` (+163 -7) 📝 `src/domain/javascript/javascriptSemanticMemberMutations.ts` (+4 -2) 📝 `src/domain/javascript/javascriptSemanticProjection.ts` (+115 -73) 📝 `src/domain/javascript/javascriptSemanticReturns.ts` (+23 -14) 📝 `src/domain/javascript/javascriptSemanticState.ts` (+6 -0) ➕ `tests/acceptance/applications/exportedFunctionBindingsCli.test.ts` (+618 -0) </details> ### 📄 Description ## Summary Fix exported callable resolution so reassigned bindings cannot retain stale return shapes and private function names cannot attach to unrelated exports. Also resolve nested CommonJS exports through their actual lexical binding and account for writes before hoisted declarations. Reported directly during a source audit; no issue number was supplied. ## Problem and expected behavior Two versions that reassign an exported function to return `count: 1` and `count: 2` incorrectly compared as zero changes and zero unknowns. Callable IDs and display names bypassed binding checks. Root-scope lookup also associated nested CommonJS exports with unrelated outer bindings, and writes collected before declarations could be dropped or assigned to the wrong scope. Uncertain, multiply assigned exports must report the existing unavailable/unknown result. Stable function exports and aliases must still compare their actual return shapes. ## Change and scope - Resolve named export links through the lexical binding captured at the export site; remove callable display-name matching. - Retain direct callable IDs for exports without local bindings, including anonymous defaults and directly exported private expressions. - Collect declarations before resolving assignment, update, and loop writes, preserving hoisted targets and local shadowing. - Keep parameter expressions outside body declarations and evaluate computed method keys in their containing scope. Traverse binding patterns only when detecting parameter expressions. - Preserve the existing single-initializer and alias-cycle checks. Exact execution-order selection after multiple writes remains outside this static model. ## Contract and boundary impact - Semantic owner and earliest changed stages: JavaScript lexical definition collection and module-to-callable resolution. - CLI/MCP schemas, inputs, and tool catalog are unchanged; corrected associations use existing selected or unavailable/unknown outcomes. - Artifact identity and source provenance are preserved. Production analysis remains inert; tests execute only source-owned fixtures. - No provider, dependency, authorization, package, installation, or generated metadata changes. ## Evidence and regression coverage - Twenty-nine compiled CLI acceptance cases cover reassignment, private-name collisions, stable exports, hoisted writes, local shadowing, nested/block CommonJS exports, parameter defaults and closures, computed destructuring keys, and object/class computed method keys. - Node execution independently verifies the fixture exports and the real `count: 1` versus `count: 2` behavior. - Regressions failed before their respective fixes, including six follow-up lexical/hoisting cases and eight function-evaluation-context cases. - Reassigned or unrelated numeric exports expose `left.status = right.status = "unavailable"`, `summary.unknown = 1`, and partial coverage. Stable callable comparisons retain the `/count` change. - Real stdio MCP output matches CLI output for private-name and nested CommonJS numeric collisions. ## Validation performed - `npm run test:local -- src/domain/javascript/*.test.ts`: 557 passed across 36 files. - Final `npm run test:focused -- tests/acceptance/applications/exportedFunctionBindingsCli.test.ts`: all 29 compiled CLI/MCP regression cases passed. - `npm run check`: passed, including typecheck, lint, formatting, unused-code, metadata, and module-boundary checks. - `npm run check:ci`: passed, including duplication and TODO checks. Shared assertions reduce local duplicated lines to 2.49% under the 2.5% gate. - `npm run verify:test-discovery`: all 696 local test files discovered exactly once. - `git diff --check`: passed. - Independent read-only review and compiled-runtime probes: no remaining blocking findings; verified parameter ownership, capture ancestry, nested aliases, and computed-key scope restoration. ## Compatibility and review No schema migration or execution authority change. Real Hopper/Ghidra and browser verification was not performed because this changes static JavaScript binding resolution only. Full deterministic coverage remains with CI as directed by the repository's focused-check workflow. - [x] Concrete bug and reason for no linked issue documented. - [x] Regression coverage exercises observable CLI/MCP behavior and independent runtime fixture oracles. - [x] Unsupported and uncertain outcomes remain visible. - [x] No owning schema or generated metadata update required. - [x] Final diff checked for unrelated changes, credentials, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:10:38 +00:00
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#2818
No description provided.