Skip to content

fix: prevent TypeError when child compilations have missing assets - #741

Open
ronakmaheshwari wants to merge 2 commits into
webpack:mainfrom
ronakmaheshwari:test/typeError
Open

ronakmaheshwari wants to merge 2 commits into
webpack:mainfrom
ronakmaheshwari:test/typeError

Conversation

@ronakmaheshwari

@ronakmaheshwari ronakmaheshwari commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

Bug fix and test coverage improvement.

This PR improves the robustness of getViewerData and related functions when handling edge cases in Webpack stats, particularly child compilations with missing or undefined assets, stats provided as arrays, and differences in asset formats between Webpack versions.

It also improves child asset/module mapping and adds compatibility for Webpack 4 entrypoints where assets may be represented as strings.

Did you add tests for your changes?

Yes.

Added tests covering:

  • Child compilations with missing or undefined assets
  • Stats provided as an array of compilations
  • Correct module mapping for child compilation assets
  • Webpack 4 entrypoints containing string assets
  • Correct aggregation of assets across child compilations

Does this PR introduce a breaking change?

No.

The changes are intended to improve handling of existing Webpack stats structures without changing the expected behavior for supported inputs.

If relevant, what needs to be documented once your changes are merged or what have you already documented?

No documentation changes are required.

This PR is an internal robustness and compatibility improvement and does not introduce any new user-facing configuration or API.

Use of AI

No.

#490

Summary by CodeRabbit

  • New Features
    • The bundle viewer can process stats from multiple compilations supplied together.
    • Assets can be matched across child compilations, including assets listed by chunk name.
    • Entrypoint assets in string and named-object formats are supported.
  • Bug Fixes
    • Bundle data is processed reliably when compilations or entrypoints have missing, empty, or null asset entries.
    • Assets from child compilations are matched with the correct module details.

@changeset-bot

changeset-bot Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a5ab3a2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
webpack-bundle-analyzer Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ronakmaheshwari

Copy link
Copy Markdown
Contributor Author

@valscion can you review my PR please

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Walkthrough

getViewerData now accepts a compilation or an array of compilations. It handles child compilations with missing assets and maps child assets to their matching compilations. Entrypoint assets can be strings or objects with a name. Tests cover these input forms and child asset mappings.

Priority: ⬇️ Low

Merge Risk: 🟡 Moderate · up to a5ab3

Charts for multiple compilations can misidentify later entrypoint assets. Preserve each asset’s entrypoint metadata before merging.

Architecture Summary

Architecture risk: 🔵 Low · up to a5ab3

The change affects 2 systems.

Changed systems: src, test

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — src (service) was modified; 1 changed file maps to changed impact.
  • observed — test (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in src/analyzer.js: getChildAssetBundles now accepts the children list directly and returns the first child whose named assets or flattened assetsByChunkName contains the requested asset; the old implementation searched only chunk-name entries and returned a boolean.
  • observed — Modified behavior in src/analyzer.js: Entrypoint asset processing now derives the name from either a string or an asset object's name, skips missing names, and uses the resolved name as the map key instead of assuming every entry is an object.
  • observed — Modified behavior in src/analyzer.js: The getViewerData parameter documentation now permits a compilation or an array of compilations.
  • observed — Modified behavior in src/analyzer.js: getViewerData returns an empty chart when given a falsy input and wraps an array of compilations in a root compilation's children field before processing.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: preventing TypeError failures when child compilations have missing assets.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1 …
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/analyzer.js

ESLint failed to execute (timeout).

test/analyzerUtils.js

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟡 Minor · Preserve duplicate asset entries across compilation arrays. · analyzer.js:445-453

src/analyzer.js:445-453
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve duplicate asset entries across compilation arrays.

The array-input path appends assets from each compilation, but the reducer stores them in a filename-keyed object. If two compilations emit the same filename, result[statAsset.name] replaces the earlier asset. The returned chart data then contains only the later entry.

Store the intermediate assets as records in an array so duplicate filenames retain separate chart entries.

Suggested fix
-    const asset = (result[statAsset.name] = /** `@type` {Asset} */ ({
+    const asset = /** `@type` {Asset} */ ({
       size: statAsset.size,
-    }));
+    });
+    result.push({ filename: statAsset.name, asset });
...
-  }, /** `@type` {Record<string, Asset>} */ ({}));
+  }, /** `@type` {{ filename: string, asset: Asset }[]} */ ([]));
...
-  return Object.entries(assets).map(([filename, asset]) => ({
+  return assets.map(({ filename, asset }) => ({

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: d71a52c3-c89f-40bd-aff1-15869d64383a

📥 Commits

Reviewing files that changed from the base of the PR and between 6046503 and 2056f4c.

📒 Files selected for processing (3)
  • .changeset/fix-child-compilations-type-error.md
  • src/analyzer.js
  • test/analyzerUtils.js

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread src/analyzer.js
@codecov

codecov Bot commented Sep 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.29730% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 88.80%. Comparing base (6046503) to head (2056f4c).

Files with missing lines Patch % Lines
src/analyzer.js 97.29% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #741      +/-   ##
==========================================
+ Coverage   87.56%   88.80%   +1.24%     
==========================================
  Files          17       17              
  Lines        1110     1126      +16     
  Branches      406      421      +15     
==========================================
+ Hits          972     1000      +28     
+ Misses        126      117       -9     
+ Partials       12        9       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@valscion valscion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! The .changeset/ needs actual content, I don't know why that file ended up being a 0 byte file here.

Check if the coderabbit thing is something we need to address here. It doesn't look like an issue to me but I think you might be better equipped to judge it.

@ronakmaheshwari

Copy link
Copy Markdown
Contributor Author

Thanks for the review, @valscion!

I've pushed updates addressing both points:

  1. Populated Changeset: Added the patch description to .changeset/fix-child-compilations-type-error.md (verified with npx changeset status).
  2. Child Compilation Mapping: Adopted CodeRabbit's suggestion to use a WeakMap<StatsAsset, StatsCompilation> to remember each child asset's originating compilation at collection time (with fallback to getChildAssetBundles). This ensures each asset gets mapped to its own compilation even if multiple child compilations have matching asset names.
  3. Duplicate Filename Reducer: Agreed with your assessment that CodeRabbit's second suggestion (switching the asset reducer from an object to an array) is not something to address here. bundlesSources, parsedModulesByAsset, and chunkToEntrypointInititalMap all index by asset filename, so changing that would require a larger architectural refactor outside the scope of fixing TypeError: Cannot read property 'forEach' of undefined #490.
  4. Coverage: Added unit tests covering null/empty entrypoint items, null child compilations, and fallback matching, bringing patch coverage to 100%.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 38c666e9-b000-4e83-b181-e0b426584f61

📥 Commits

Reviewing files that changed from the base of the PR and between 2056f4c and a5ab3a2.

📒 Files selected for processing (3)
  • .changeset/fix-child-compilations-type-error.md
  • src/analyzer.js
  • test/analyzerUtils.js

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread src/analyzer.js
for (let i = 1; i < children.length; i++) {
for (const asset of children[i].assets || []) {
for (let i = 1; i < allChildren.length; i++) {
const child = allChildren[i];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Preserve entrypoint metadata for appended compilations.

When an array contains compilations with different asset names, these loops append the later assets but do not preserve their entrypoints. getChunkToInitialByEntrypoint(bundleStats) then reads only the first compilation. A later compilation’s entrypoint asset receives an empty isInitialByEntrypoint map. Build that metadata from each asset’s source compilation in both append paths.

Also applies to: 319-319

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.

2 participants