[GH-ISSUE #7113] [Bug] Defaulted or destructured Webpack factory module parameter reports no exports with complete coverage #4278

Closed
opened 2026-10-31 00:48:26 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @kaoru0822-kitauji on GitHub (Oct 25, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7113

Originally assigned to: @kaoru0822-kitauji on GitHub.

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction.

Observed behavior

analyze-javascript-application reports exports: [] for a Webpack factory whose first (module) parameter is defaulted or destructured. The module observation is still observed / exact, and the application graph coverage is complete, so the empty list reads as a confirmed absence of exports.

Reproduction

bundle.js (one file in its own directory):

globalThis.webpackChunkApp.push([[1], {
  111(e = {}, t) { e.exports = {defaulted: 1}; },
  112({exports: x}, t) { x.destructured = 1; },
  101(e, t) { e.exports = {parse: value=>value}; }
}]);
node scripts/rea.mjs analyze-javascript-application <dir> --format json

Observed at main bc143125e (REA 6.8.0 built from source, Node 26.5.0, macOS). Exit 0. The javascript-module observations under normalized_result.graph.nodes are:

Module key REA exports Observation Graph coverage
111 [] observed / exact complete
112 [] observed / exact complete
101 (control) ["parse"] observed / exact complete

Node oracle, run separately on this inert fixture: capture the module table through a replacement push, then call each factory with m = {exports: {}}, m.exports and a stub loader, and print Object.getOwnPropertyNames(m.exports):

111 ["defaulted"]
112 ["destructured"]
101 ["parse"]

Expected behavior

  • 111 should report ["defaulted"]. The runtime passes the module object, so the default never applies.
  • 112 should report ["destructured"]. x is bound to the original module.exports.
  • Any other first-parameter pattern that can't be resolved exactly (rest, nested, or computed keys) should mark that module's export list as not complete, rather than return an exact empty list.

Impact and scope

The impact is incorrect export metadata in a successful result, with nothing in the coverage to show it. Unverified: whether real bundlers emit defaulted or destructured factory parameters. I have not seen it, but I have not surveyed bundlers or minifiers. Hand-written module maps and transformed output could contain these shapes.

Analysis (source-derived)

recoverBundlerModule in src/domain/javascript/javascriptStaticAnalysisBundler.ts assigns the factory roles through identifierAt, which returns a role only when the parameter is a plain Identifier. A defaulted or destructured parameter therefore leaves the module role undefined. collectJavaScriptExports then matches nothing and nothing records that the role was unresolved.

Found while checking related cases for #3551, which no longer reproduces on main. In the same 15-factory oracle comparison, every other case matched.

Originally created by @kaoru0822-kitauji on GitHub (Oct 25, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7113 Originally assigned to: @kaoru0822-kitauji on GitHub. ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Evidence, artifacts, or reconstruction. ## Observed behavior `analyze-javascript-application` reports `exports: []` for a Webpack factory whose first (module) parameter is defaulted or destructured. The module observation is still `observed` / `exact`, and the application graph coverage is `complete`, so the empty list reads as a confirmed absence of exports. ## Reproduction `bundle.js` (one file in its own directory): ```js globalThis.webpackChunkApp.push([[1], { 111(e = {}, t) { e.exports = {defaulted: 1}; }, 112({exports: x}, t) { x.destructured = 1; }, 101(e, t) { e.exports = {parse: value=>value}; } }]); ``` ```sh node scripts/rea.mjs analyze-javascript-application <dir> --format json ``` Observed at main `bc143125e` (REA 6.8.0 built from source, Node 26.5.0, macOS). Exit 0. The `javascript-module` observations under `normalized_result.graph.nodes` are: | Module key | REA `exports` | Observation | Graph coverage | | --- | --- | --- | --- | | `111` | `[]` | `observed` / `exact` | `complete` | | `112` | `[]` | `observed` / `exact` | `complete` | | `101` (control) | `["parse"]` | `observed` / `exact` | `complete` | Node oracle, run separately on this inert fixture: capture the module table through a replacement `push`, then call each factory with `m = {exports: {}}`, `m.exports` and a stub loader, and print `Object.getOwnPropertyNames(m.exports)`: ```text 111 ["defaulted"] 112 ["destructured"] 101 ["parse"] ``` ## Expected behavior - `111` should report `["defaulted"]`. The runtime passes the module object, so the default never applies. - `112` should report `["destructured"]`. `x` is bound to the original `module.exports`. - Any other first-parameter pattern that can't be resolved exactly (rest, nested, or computed keys) should mark that module's export list as not complete, rather than return an exact empty list. ## Impact and scope The impact is incorrect export metadata in a successful result, with nothing in the coverage to show it. **Unverified:** whether real bundlers emit defaulted or destructured factory parameters. I have not seen it, but I have not surveyed bundlers or minifiers. Hand-written module maps and transformed output could contain these shapes. ## Analysis (source-derived) `recoverBundlerModule` in `src/domain/javascript/javascriptStaticAnalysisBundler.ts` assigns the factory roles through `identifierAt`, which returns a role only when the parameter is a plain `Identifier`. A defaulted or destructured parameter therefore leaves the `module` role `undefined`. `collectJavaScriptExports` then matches nothing and nothing records that the role was unresolved. Found while checking related cases for #3551, which no longer reproduces on main. In the same 15-factory oracle comparison, every other case matched.
bsakaguchi 2026-10-31 00:48:26 +00:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@XinwangTao commented on GitHub (Oct 25, 2026):

这个 bug 影响面比表面看起来大:exports: [] 加上 coverage 又是 complete/exact,会让下游把“没有导出”当成被验证过的事实,而实际上只是 identifierAt 没有把 defaulted/destructured 参数绑定到 module 角色。支持 #7117 的修法——把 e = {} 和 {exports: x} 都绑定回 module 角色后,111/112 的导出就能正确恢复。另外建议对无法精确解析的 rest/nested/computed 首参模式直接标记 export list not complete,而不是返回空列表,这样即使修复不了也能让下游知道元数据不可信。可以顺带把这两个 fixture 加进回归测试。

<!-- gh-comment-id:6396492521 --> @XinwangTao commented on GitHub (Oct 25, 2026): 这个 bug 影响面比表面看起来大:exports: [] 加上 coverage 又是 complete/exact,会让下游把“没有导出”当成被验证过的事实,而实际上只是 identifierAt 没有把 defaulted/destructured 参数绑定到 module 角色。支持 #7117 的修法——把 e = {} 和 {exports: x} 都绑定回 module 角色后,111/112 的导出就能正确恢复。另外建议对无法精确解析的 rest/nested/computed 首参模式直接标记 export list not complete,而不是返回空列表,这样即使修复不了也能让下游知道元数据不可信。可以顺带把这两个 fixture 加进回归测试。
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#4278
No description provided.