[PR #2765] [MERGED] fix(javascript): preserve container ownership for getter mutations #5374

Closed
opened 2026-10-31 01:06:08 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2765
Author: @To3akaRin
Created: 10/13/2026
Status: ✅ Merged
Merged: 10/13/2026
Merged by: @morluto

Base: main ← Head: codex/getter-container-receiver-mutations


📝 Commits (1)

  • 145619f fix(javascript): preserve container ownership for getter mutations

📊 Changes

5 files changed (+233 additions, -28 deletions)

View changed files

📝 docs/javascript-application-workflows.md (+7 -0)
📝 src/domain/javascript/javascriptSemanticAnalysis.getter_receivers.test.ts (+69 -1)
📝 src/domain/javascript/javascriptSemanticMemberMutations.ts (+42 -7)
📝 src/domain/javascript/javascriptSemanticObjectReferences.ts (+50 -12)
📝 tests/acceptance/applications/getterReceiverMutationsCli.test.ts (+65 -8)

📄 Description

Summary

Fixes #2654.

A write through an object getter inside an array, or an object assigned after declaration, could leave an exported return shape reporting the old literal. For example, arr[0].self.x = 2; return arr[0].x still reported literal 1. Preserve the receiver's containing path and allocation identity so that the result becomes conservatively unknown without invalidating unrelated values.

Problem and expected behavior

export function result() {
  const arr = [{ x: 1, get self() { return this; } }];
  arr[0].self.x = 2;
  return arr[0].x;
}

The getter returns the array element, so the write must invalidate its earlier x value. This is static analysis; the change does not claim to execute the getter or recover the new runtime value. The same rule applies to mixed object/array nesting, saved getter aliases, and let box; box = {...}.

Change and scope

  • Extend the existing receiver-owner projection to array elements and ordinary identifier assignments. Count holes as slots; after a spread, retain a minimum-index selector instead of using the AST position as an exact runtime index.
  • Carry the owning initializer with a recovered receiver reference. The mutation traversal follows that specific allocation and includes it in its cycle, coverage and leaf-cache identities. This prevents a reassigned receiver from reintroducing an unrelated older binding value.
  • Keep ordinary RHS references on the existing capture path: in box = { old: box, ... }, this denotes the new object while old still denotes the prior value.
  • Extend the existing semantic and public CLI/stdio MCP regressions and document the supported behavior. Prototype getters and getter-local this aliases are separate issues, outside this correction.

This is a routine fix within existing static-analysis boundaries; an advance maintainer scope decision is not applicable.

Contract and boundary impact

  • Semantic owner and earliest changed stage: getter receiver references and member-mutation propagation, before export-return-shape projection.
  • CLI and MCP/tool-catalog contract: no schema or command changes; corrected values propagate through the existing Evidence contract.
  • Provider, bridge, target-format, or platform compatibility: no new provider, dependency or format.
  • Evidence and provenance: affected return values become unknown; source identity and existing coverage/provenance remain intact.
  • Target selection, authority and cleanup: unchanged. Application source is parsed as inert text, not executed.
  • Generated metadata, package and installation impact: none; generated build and documentation artifacts are not committed.

Expected effect:

  • Read existing files or captured data.

No added target execution, injection, network access, mutation or protection-recovery capability.

Evidence and regression coverage

Before the production fix, six newly added semantic cases failed with literal instead of unknown on baseline c02fb0e. They cover array elements, holes, mixed containers, assignment, saved aliases and a saved receiver preceding alias reassignment.

The final semantic suite also checks known-prefix preservation after a spread, unrelated fields/elements, lexical shadowing, old-object preservation after reassignment, and the distinction between allocation ownership and RHS capture. Public CLI and stdio MCP tests parse the real analysis result and assert both export return status and root-field values, including the reassignment controls.

  • Observed, derived and inferred claims remain distinguishable.
  • Artifact identity and source provenance remain preserved.
  • Uncertain results remain explicit.

Validation performed

On the rebased branch over 3af8f84:

  • npm run test:local -- src/domain/javascript/javascriptSemanticAnalysis*.test.ts — 20 files, 573 tests passed.
  • npm run test:focused -- tests/acceptance/applications/getterReceiverMutationsCli.test.ts — 2 public CLI/stdio MCP tests passed; the launcher also builds the runtime and skill.
  • npm run check — passed, including typecheck, lint, formatting, knip, metadata and architecture guards.
  • npm run docs:check — passed, including 2 README consistency tests.
  • npm run verify:test-discovery — all 1,055 test files discovered once.
  • git diff --check — passed.

Local execution used macOS arm64, Node.js 24.19.0 and npm 11.17.0, with locked dependencies installed using npm 11.16.0. The pinned Node.js 24.18.0 could not be downloaded due TLS/connection failures, so that exact runtime was not exercised locally. CI remains responsible for the full deterministic suite and coverage; Linux/Windows and real-engine lanes were not run. This change does not use a native engine. No performance improvement is claimed.

Compatibility, safety, and release

No input/schema changes, migration, new environment variables or installation steps. The owning workflow documentation is updated; release metadata and generated outputs are unchanged.

Before merge

  • Concrete problem and linked issue.
  • Scope and authority resolved for the final diff.
  • One focused outcome and Conventional Commit title.
  • Regression and meaningful precision/lifecycle controls.
  • Owning documentation updated.
  • Representative public CLI/MCP behavior verified.
  • Final diff checked 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/2765 **Author:** [@To3akaRin](https://github.com/To3akaRin) **Created:** 10/13/2026 **Status:** ✅ Merged **Merged:** 10/13/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `codex/getter-container-receiver-mutations` --- ### 📝 Commits (1) - [`145619f`](https://github.com/morluto/rea/commit/145619fc4b42b1dc22f46c18b556fe3f59d953d5) fix(javascript): preserve container ownership for getter mutations ### 📊 Changes **5 files changed** (+233 additions, -28 deletions) <details> <summary>View changed files</summary> 📝 `docs/javascript-application-workflows.md` (+7 -0) 📝 `src/domain/javascript/javascriptSemanticAnalysis.getter_receivers.test.ts` (+69 -1) 📝 `src/domain/javascript/javascriptSemanticMemberMutations.ts` (+42 -7) 📝 `src/domain/javascript/javascriptSemanticObjectReferences.ts` (+50 -12) 📝 `tests/acceptance/applications/getterReceiverMutationsCli.test.ts` (+65 -8) </details> ### 📄 Description ## Summary Fixes #2654. A write through an object getter inside an array, or an object assigned after declaration, could leave an exported return shape reporting the old literal. For example, `arr[0].self.x = 2; return arr[0].x` still reported `literal 1`. Preserve the receiver's containing path and allocation identity so that the result becomes conservatively unknown without invalidating unrelated values. ## Problem and expected behavior ```js export function result() { const arr = [{ x: 1, get self() { return this; } }]; arr[0].self.x = 2; return arr[0].x; } ``` The getter returns the array element, so the write must invalidate its earlier `x` value. This is static analysis; the change does not claim to execute the getter or recover the new runtime value. The same rule applies to mixed object/array nesting, saved getter aliases, and `let box; box = {...}`. ## Change and scope - Extend the existing receiver-owner projection to array elements and ordinary identifier assignments. Count holes as slots; after a spread, retain a minimum-index selector instead of using the AST position as an exact runtime index. - Carry the owning initializer with a recovered receiver reference. The mutation traversal follows that specific allocation and includes it in its cycle, coverage and leaf-cache identities. This prevents a reassigned receiver from reintroducing an unrelated older binding value. - Keep ordinary RHS references on the existing capture path: in `box = { old: box, ... }`, `this` denotes the new object while `old` still denotes the prior value. - Extend the existing semantic and public CLI/stdio MCP regressions and document the supported behavior. Prototype getters and getter-local `this` aliases are separate issues, outside this correction. This is a routine fix within existing static-analysis boundaries; an advance maintainer scope decision is not applicable. ## Contract and boundary impact - Semantic owner and earliest changed stage: getter receiver references and member-mutation propagation, before export-return-shape projection. - CLI and MCP/tool-catalog contract: no schema or command changes; corrected values propagate through the existing Evidence contract. - Provider, bridge, target-format, or platform compatibility: no new provider, dependency or format. - Evidence and provenance: affected return values become unknown; source identity and existing coverage/provenance remain intact. - Target selection, authority and cleanup: unchanged. Application source is parsed as inert text, not executed. - Generated metadata, package and installation impact: none; generated build and documentation artifacts are not committed. Expected effect: - [x] Read existing files or captured data. No added target execution, injection, network access, mutation or protection-recovery capability. ## Evidence and regression coverage Before the production fix, six newly added semantic cases failed with `literal` instead of `unknown` on baseline `c02fb0e`. They cover array elements, holes, mixed containers, assignment, saved aliases and a saved receiver preceding alias reassignment. The final semantic suite also checks known-prefix preservation after a spread, unrelated fields/elements, lexical shadowing, old-object preservation after reassignment, and the distinction between allocation ownership and RHS capture. Public CLI and stdio MCP tests parse the real analysis result and assert both export return status and root-field values, including the reassignment controls. - [x] Observed, derived and inferred claims remain distinguishable. - [x] Artifact identity and source provenance remain preserved. - [x] Uncertain results remain explicit. ## Validation performed On the rebased branch over `3af8f84`: - `npm run test:local -- src/domain/javascript/javascriptSemanticAnalysis*.test.ts` — 20 files, 573 tests passed. - `npm run test:focused -- tests/acceptance/applications/getterReceiverMutationsCli.test.ts` — 2 public CLI/stdio MCP tests passed; the launcher also builds the runtime and skill. - `npm run check` — passed, including typecheck, lint, formatting, knip, metadata and architecture guards. - `npm run docs:check` — passed, including 2 README consistency tests. - `npm run verify:test-discovery` — all 1,055 test files discovered once. - `git diff --check` — passed. Local execution used macOS arm64, Node.js 24.19.0 and npm 11.17.0, with locked dependencies installed using npm 11.16.0. The pinned Node.js 24.18.0 could not be downloaded due TLS/connection failures, so that exact runtime was not exercised locally. CI remains responsible for the full deterministic suite and coverage; Linux/Windows and real-engine lanes were not run. This change does not use a native engine. No performance improvement is claimed. ## Compatibility, safety, and release No input/schema changes, migration, new environment variables or installation steps. The owning workflow documentation is updated; release metadata and generated outputs are unchanged. ## Before merge - [x] Concrete problem and linked issue. - [x] Scope and authority resolved for the final diff. - [x] One focused outcome and Conventional Commit title. - [x] Regression and meaningful precision/lifecycle controls. - [x] Owning documentation updated. - [x] Representative public CLI/MCP behavior verified. - [x] Final diff checked 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>
bsakaguchi 2026-10-31 01:06:08 +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#5374
No description provided.