[PR #2465] fix(javascript): preserve intrinsic invocation read identity #5248

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2465
Author: @aznikline
Created: 10/13/2026
Status: 🔄 Open

Base: main ← Head: split/intrinsic-boundaries


📝 Commits (10+)

  • 85ad41e fix(javascript): preserve intrinsic invocation read identity
  • 8d5e11e test(javascript): contrast aliased intrinsic invocation semantics
  • 3c75efc fix(javascript): preserve invocation receivers and evaluation boundaries
  • facc354 fix(javascript): retain write identity and operand evaluation order
  • ef8eb3a fix(javascript): preserve destructuring and bound invocation boundaries
  • e1253be fix(javascript): preserve explicit receivers of bound invocation members
  • b9632f5 fix(comparison): recheck historical calls-only changes (#2223)
  • d341d2e fix(ci): isolate Linux Hopper process fixture inventory
  • e88b956 fix(javascript): preserve intrinsic invocation identity
  • 9ca6e62 fix(ci): repair committed artifacts blocking typecheck and lint

📊 Changes

13 files changed (+2403 additions, -150 deletions)

View changed files

📝 docs/javascript-artifact-reconstruction.md (+7 -1)
➕ src/domain/javascript/electronIntrinsicCapture.test.ts (+1162 -0)
📝 src/domain/javascript/electronModuleInterop.test.ts (+34 -0)
📝 src/domain/javascript/javascriptElectronMemberWrites.ts (+218 -67)
📝 src/domain/javascript/javascriptIntrinsicInvocation.ts (+321 -29)
📝 src/domain/javascript/javascriptModuleInterop.ts (+601 -40)
📝 src/domain/javascript/javascriptSemanticAmbientWrites.test.ts (+12 -0)
📝 src/domain/javascript/javascriptSemanticAnalysis.ts (+21 -3)
📝 src/domain/javascript/javascriptSemanticMutationInitializers.ts (+2 -1)
📝 src/domain/javascript/javascriptSemanticTraversal.ts (+12 -3)
📝 tests/acceptance/applications/electronModuleInteropCli.test.ts (+7 -1)
📝 tests/boundary/mcp/fridaLifecycleMcp.test.ts (+5 -4)
📝 tests/boundary/mcp/toolInputAdmission.test.ts (+1 -1)

📄 Description

Summary

Preserve intrinsic-invocation identity across aliased member reads, bound
callables, and destructured writes. Identifier-aliased reads of intrinsic
invocation members (e.g. const change = Object.defineProperty.call; change(...)) were left effect-free after #1912's receiver tracking: the
member path resolved but derived no callable. This change keeps such calls'
effects unknown (opaque) — argument expressions still evaluate — rather
than effect-free or a confirmed write.

Semantics, verified against a real engine (Node v26): a bare alias
invocation throws TypeError, but its argument expressions still evaluate.

Covers, on top of the shared captured-member identity model:

  • identifier-aliased .call/.apply/.bind reads resolved conservatively
  • bound invocation members with explicit receivers; alias initializers such
    as invoke = change.call resolve the captured member's canonical
    Function.prototype.<member> identity for both reads and writes
  • call-site re-reads of outer invocation members (invoke.call,
    invoke.apply) validated against writes at the callee's evaluation
    offset; nested Function.prototype.<member>.<member> reads checked at
    canonical depth
  • unknown bound-argument lists stay unknown instead of merging into an
    empty prefix
  • evaluation-order writes: destructuring RHS before pattern, per-leaf
    effect timing, sequence-expression callee tails
  • destructured write targets resolve object identity at the enclosing
    write site (statement context) while each leaf keeps its own effect
    timing; for-in sites positioned like for-of; transparent wrappers
    (as casts, assertions) defer a default target's write until after the
    default runs
  • captured-member aliases are followed transitively (copy = invoke,
    (0, change.call) sequence tails) and only canonicalize when the owner
    is a provable callable whose own slot was unwritten at capture —
    "recognized but replaced" resolves opaque, never effect-free or a
    confirmed write
  • captured members resolve as direct Reflect.apply targets
    (Reflect.apply(invoke, change, [...]))
  • merged upstream origin(root, kind, writeSite) signature and [null]
    unknown-child member-mutation encoding

Test plan

  • electronIntrinsicCapture.test.ts: 78/78 — semantic-contrast cases
    including alias writes to captured members, replaced outer-member
    reads, argument-side effects, sequence callees/tails, copied aliases,
    owner-slot replacement (opaque), bare calls of replaced captured
    members (opaque), destructured call/apply/bind captures
    (incl. slot checks at destructuring time), nested captured owners,
    explicit-receiver member calls, direct Reflect.apply targets, and
    wrapped destructuring defaults
  • javascriptSemanticAmbientWrites.test.ts: 10/10 — destructured
    writes through reassigned vs still-global aliases (Worker specifier)
  • src/domain/javascript suite: 71 files, 1778/1778
  • check:fast green; oxfmt --check clean on touched files
  • Required CI lanes on f3765f117 (run 38679888243): CI required +
    Portable tests pass; newer heads pending
  • Provisioned CI lane: check:pr full suite

Notes

  • No "proven regression" claim: base behavior retained no effect for
    aliased calls, keeping downstream intrinsic identity and producing
    unsound findings; the base/head contrast is recorded in the research
    notes (not part of this diff).

Generated with Devin

Author readiness

Human owner:

  • 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.

🔄 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/2465 **Author:** [@aznikline](https://github.com/aznikline) **Created:** 10/13/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `split/intrinsic-boundaries` --- ### 📝 Commits (10+) - [`85ad41e`](https://github.com/morluto/rea/commit/85ad41e55de2aee43fbc775f1492672185f5cd65) fix(javascript): preserve intrinsic invocation read identity - [`8d5e11e`](https://github.com/morluto/rea/commit/8d5e11efcdc3e346f78d9dc3901693de7a4b3445) test(javascript): contrast aliased intrinsic invocation semantics - [`3c75efc`](https://github.com/morluto/rea/commit/3c75efc03421655f9f245e2b08459dcc2189d914) fix(javascript): preserve invocation receivers and evaluation boundaries - [`facc354`](https://github.com/morluto/rea/commit/facc35478f6237f0c4835a419047c5a8a9133675) fix(javascript): retain write identity and operand evaluation order - [`ef8eb3a`](https://github.com/morluto/rea/commit/ef8eb3ab19880d0a3bc49692fbb0953f8ec3afa2) fix(javascript): preserve destructuring and bound invocation boundaries - [`e1253be`](https://github.com/morluto/rea/commit/e1253bede96db88850a0f6237cb77803bba06c59) fix(javascript): preserve explicit receivers of bound invocation members - [`b9632f5`](https://github.com/morluto/rea/commit/b9632f540b6988046d2aa667d6d7053e448c545a) fix(comparison): recheck historical calls-only changes (#2223) - [`d341d2e`](https://github.com/morluto/rea/commit/d341d2eae25c1a106251a516fb72e0536ccc8c37) fix(ci): isolate Linux Hopper process fixture inventory - [`e88b956`](https://github.com/morluto/rea/commit/e88b9560845807f5803f86d500071a34116bfd1c) fix(javascript): preserve intrinsic invocation identity - [`9ca6e62`](https://github.com/morluto/rea/commit/9ca6e629772d8c01c9b9ee7fc8c88f6b9d34ea05) fix(ci): repair committed artifacts blocking typecheck and lint ### 📊 Changes **13 files changed** (+2403 additions, -150 deletions) <details> <summary>View changed files</summary> 📝 `docs/javascript-artifact-reconstruction.md` (+7 -1) ➕ `src/domain/javascript/electronIntrinsicCapture.test.ts` (+1162 -0) 📝 `src/domain/javascript/electronModuleInterop.test.ts` (+34 -0) 📝 `src/domain/javascript/javascriptElectronMemberWrites.ts` (+218 -67) 📝 `src/domain/javascript/javascriptIntrinsicInvocation.ts` (+321 -29) 📝 `src/domain/javascript/javascriptModuleInterop.ts` (+601 -40) 📝 `src/domain/javascript/javascriptSemanticAmbientWrites.test.ts` (+12 -0) 📝 `src/domain/javascript/javascriptSemanticAnalysis.ts` (+21 -3) 📝 `src/domain/javascript/javascriptSemanticMutationInitializers.ts` (+2 -1) 📝 `src/domain/javascript/javascriptSemanticTraversal.ts` (+12 -3) 📝 `tests/acceptance/applications/electronModuleInteropCli.test.ts` (+7 -1) 📝 `tests/boundary/mcp/fridaLifecycleMcp.test.ts` (+5 -4) 📝 `tests/boundary/mcp/toolInputAdmission.test.ts` (+1 -1) </details> ### 📄 Description ## Summary Preserve intrinsic-invocation identity across aliased member reads, bound callables, and destructured writes. Identifier-aliased reads of intrinsic invocation members (e.g. `const change = Object.defineProperty.call; change(...)`) were left effect-free after #1912's receiver tracking: the member path resolved but derived no callable. This change keeps such calls' effects unknown (`opaque`) — argument expressions still evaluate — rather than effect-free or a confirmed write. Semantics, verified against a real engine (Node v26): a bare alias invocation throws `TypeError`, but its argument expressions still evaluate. Covers, on top of the shared captured-member identity model: - identifier-aliased `.call`/`.apply`/`.bind` reads resolved conservatively - bound invocation members with explicit receivers; alias initializers such as `invoke = change.call` resolve the captured member's canonical `Function.prototype.<member>` identity for **both** reads and writes - call-site re-reads of outer invocation members (`invoke.call`, `invoke.apply`) validated against writes at the callee's evaluation offset; nested `Function.prototype.<member>.<member>` reads checked at canonical depth - unknown bound-argument lists stay unknown instead of merging into an empty prefix - evaluation-order writes: destructuring RHS before pattern, per-leaf effect timing, sequence-expression callee tails - destructured write targets resolve object identity at the enclosing write site (statement context) while each leaf keeps its own effect timing; `for-in` sites positioned like `for-of`; transparent wrappers (`as` casts, assertions) defer a default target's write until after the default runs - captured-member aliases are followed transitively (`copy = invoke`, `(0, change.call)` sequence tails) and only canonicalize when the owner is a provable callable whose own slot was unwritten at capture — "recognized but replaced" resolves `opaque`, never effect-free or a confirmed write - captured members resolve as direct `Reflect.apply` targets (`Reflect.apply(invoke, change, [...])`) - merged upstream `origin(root, kind, writeSite)` signature and `[null]` unknown-child member-mutation encoding #### Test plan - [x] `electronIntrinsicCapture.test.ts`: 78/78 — semantic-contrast cases including alias writes to captured members, replaced outer-member reads, argument-side effects, sequence callees/tails, copied aliases, owner-slot replacement (opaque), bare calls of replaced captured members (opaque), destructured `call`/`apply`/`bind` captures (incl. slot checks at destructuring time), nested captured owners, explicit-receiver member calls, direct `Reflect.apply` targets, and wrapped destructuring defaults - [x] `javascriptSemanticAmbientWrites.test.ts`: 10/10 — destructured writes through reassigned vs still-global aliases (Worker specifier) - [x] `src/domain/javascript` suite: 71 files, 1778/1778 - [x] `check:fast` green; `oxfmt --check` clean on touched files - [x] Required CI lanes on `f3765f117` (run `38679888243`): CI required + Portable tests pass; newer heads pending - [ ] Provisioned CI lane: `check:pr` full suite #### Notes - No "proven regression" claim: base behavior retained no effect for aliased calls, keeping downstream intrinsic identity and producing unsound findings; the base/head contrast is recorded in the research notes (not part of this diff). Generated with [Devin](https://devin.ai) ## Author readiness Human owner: <!-- @GitHub-handle — required, must be filled by the human owner --> - [ ] 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. --- <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#5248
No description provided.