Skip to content

fix(javascript): resolve module-level Electron options in functions - #8087

Closed
ShuaixinHuang wants to merge 5 commits into
morluto:mainfrom
ShuaixinHuang:codex/fix-electron-module-options
Closed

ShuaixinHuang wants to merge 5 commits into
morluto:mainfrom
ShuaixinHuang:codex/fix-electron-module-options

Conversation

@ShuaixinHuang

@ShuaixinHuang ShuaixinHuang commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Superseded by #8250 at the author's request: #8250 . The replacement uses the same verified head commit; this PR retains the original discussion and validation record.

Problem and resulting behavior

Fixes #7227. Electron static analysis loses module-level immutable webPreferences read inside a later activation. Retain those settings when initialization precedes the function's module-level uses, while preserving uncertainty when a hoisted function can run earlier.

For example, this source must remain dynamic rather than report a proven nodeIntegration: true:

const { BrowserWindow } = require("electron");
createWindow();
const webPreferences = { nodeIntegration: true };
function createWindow() {
  return new BrowserWindow({ webPreferences });
}

Moving the call after the const initializer yields object-literal with the literal setting, including when the function declaration appears before the initializer.

Owning change and scope

Initialization coverage stays in javascriptSemanticMutationInitializers.ts; Electron consumers use that fact without reinterpreting declaration order. A hoisted declaration's position does not prove activation timing. The owner indexes module-level function references once per immutable module body and treats earlier aliases, indirect activations, live exports and unproven timing conservatively. This is a bounded reference-order check, not a general call graph or runtime execution proof.

The existing ancestry cache also retains the enclosing function, avoiding repeated walks from deep reads. Initialization coverage remains separate from cross-function capture ordering: the latter stays unresolved so named child-process argv shapes retain their existing uncertainty. No public schema, provider, execution authority, deadline, resource ceiling or assertion was weakened.

Validation at the current follow-up

Windows, Node 24.22.1 / npm 11.16.0:

  • Exact preceding head fb2532ad61ceb4cce7d233131fc1edd4305925ff, with the new source regressions: 4 failed / 47 passed. Three cases expose early direct, aliased and forwarding calls; the fourth exposes a late-call positive control.
  • Inert Node VM controls reproduce a temporal-dead-zone ReferenceError for the three early calls. They substitute a stub BrowserWindow and do not run Electron.
  • Final committed follow-up 9bafc838629358fb8ebc0ce86abefa5c82c8a0ab: 112/112 passed across six complete files: Electron options 51, existing scope-depth/resource controls 14, binding initializers 13, argument shapes 30, existing child-process compiled CLI/stdio MCP 2, and new Electron initialization compiled CLI/stdio MCP 2. Three build prerequisite tasks passed.
  • Both public adapters report dynamic/empty preferences for the early-call source and object-literal/literal true for the late-call source. Source ranges distinguish the two files. Fixtures remain inert.
  • Test discovery passed: all 2,866 test files discovered exactly once. Normal precommit passed; typecheck/lint passed 2/2. Normal prepush typecheck/lint passed 2/2, 26.986 seconds; the normal fast-forward push to this PR's existing fork branch completed.

The earlier head's independent hosted CI passed, but it did not cover this hoisted-declaration review case. The new head requires its own hosted CI; an earlier green run does not validate it. Local checks use synthetic JavaScript through production static analysis and real local compiled CLI/stdio MCP. No real Electron application or Linux/macOS execution is claimed.

Loop ownership review follow-up

Commit cc2bb1242a5611527bfb99935bc7dbcf85e902f7 keeps enclosing-function identity in its own immutable ancestry cache. Loop ordering remains uncertain; entering a loop no longer erases which function owns the read. This retains initialized module-level Electron settings inside for-of, for and while loops while keeping early calls dynamic. No downstream reinterpretation or call graph expansion was added.

On exact preceding head 9bafc838, the three new loop source cases fail while the existing 51 pass. With the correction, six complete files pass 115/115 (Electron 54, scope-depth 14, initializers 13, shapes 30, existing child-process CLI/MCP 2, Electron initialization CLI/MCP 2). The public adapter cases include both early and late calls inside loops and outside loops, with source provenance. All three committed files match the tested bytes exactly after normal precommit hooks. Three build tasks passed; normal prepush typecheck/lint passed 2/2, 46.166 seconds. No assertions or resource controls were relaxed.

The earlier 9bafc838 own hosted workflow 41009833080 completed successfully; the new cc2bb124 head requires independent hosted validation. Validation uses synthetic inert JavaScript and real local compiled CLI/stdio MCP on Windows, Node 24.22.1 / npm 11.16.0; no real Electron application or Linux/macOS run is claimed.

Author readiness

Human owner: @ShuaixinHuang

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

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-30T03:00:40.439618Z
We couldn’t complete this review. Comment @codex review to try again.
283a6e8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@greptile-apps

greptile-apps Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; the loop regression is fixed without dropping the early-call guard.

Summary

This PR lets Electron analysis retain module-level const options inside functions without treating early calls as initialized.

  • Electron settings resolve inside functions only after module initialization.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Read a module-level const] --> B[Find the containing function]
  B --> C[Check initialization before activation]
  C -->|Proven| D[Retain initialization fact]
  C -->|Unproven| E[Keep options dynamic]
  D --> F[Keep capture ordering unresolved]
  F --> G[Electron checks object mutations]
Loading

Reviews (5) · Last reviewed commit: "fix(javascript): retain function ownersh..." · Reviewed by Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Module-level webPreferences constants are reported as dynamic when the window is created inside a function

1 participant