Repository navigation
test: run WebpackCli suite under Bun instead of skipping - #21334
Conversation
Bun segfaults driving jest's native vm.SyntheticModule (its dynamic import() wrapper) through link/evaluate; substitute a pure-JS stand-in in the Bun preloader. webpack-cli 7.1.0's CLIPlugin import interop also breaks under Bun; bridge with a test-only patch (applied in the CI Bun job) until an upstream release ships the fix.
|
|
This PR is packaged and the instant preview is available (413b0be). Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@413b0be
yarn add -D webpack@https://pkg.pr.new/webpack@413b0be
pnpm add -D webpack@https://pkg.pr.new/webpack@413b0be |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #21334 +/- ##
=======================================
Coverage 92.64% 92.64%
=======================================
Files 594 594
Lines 65951 65951
Branches 18328 18328
=======================================
Hits 61103 61103
Misses 4848 4848
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR enables running the existing WebpackCLI longtest suite under Bun by removing a Bun-specific skip, and adds Bun-only CI patching/preload adjustments to work around Bun + jest vm behavior and a webpack-cli interop issue.
Changes:
- Unskip
test/WebpackCli.longtest.jsunder Bun so the integration suite runs. - Extend the Bun Jest preload to avoid Bun segfaults around
vm.SyntheticModuleand normalize dynamic import behavior. - Apply a Bun-only
webpack-clipatch in CI to fix CLIPlugin import interop until an upstream release lands.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| test/WebpackCli.longtest.js | Removes the Bun skip so the WebpackCLI integration suite runs under Bun. |
| test/bun-preload.js | Adds a vm.SyntheticModule stand-in and adjusts dynamic import namespace handling for Bun + jest. |
| test/patches/webpack-cli+7.1.0.patch | Introduces a Bun-only patch to fix webpack-cli CLIPlugin import interop under Bun. |
| .github/workflows/test.yml | Applies the new Bun-only webpack-cli patch during the Bun CI job. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async evaluate() { | ||
| if (this.status !== "linked") return; | ||
| try { | ||
| this._evaluationCallback(); | ||
| this.status = "evaluated"; | ||
| } catch (err) { | ||
| this.status = "errored"; | ||
| this.error = err; | ||
| throw err; | ||
| } | ||
| } |
There was a problem hiding this comment.
The callback is invoked as this._evaluationCallback() — a method call on the module instance — so this inside the callback is the module and this.setExport(...) works (the previous explicit .call(this) was flagged by no-useless-call for exactly this reason; the suite passes 20/20 under Bun with this code). On the promise point: Node's SyntheticModule evaluation callback is synchronous by definition and its return value is ignored, so awaiting it would diverge from the semantics we're standing in for.
Generated by Claude Code
| Bun-only test patch (applied in the CI Bun job, like jest-worker): | ||
| webpack-cli 7.1.0 unwraps its CLIPlugin dynamic import twice (`.default.default`), | ||
| correct under Node's CJS interop but `undefined` under Bun, which honors | ||
| `__esModule` and unwraps once already. Drop when webpack's webpack-cli | ||
| dependency includes the upstream interop fix. |
| # webpack-cli 7.1.0's CLIPlugin import interop breaks under Bun; see the | ||
| # patch header. Needed by WebpackCli.longtest.js until an upstream release. |
Move the rationale into the patched code and the workflow comment so the patch file parses as a plain diff.
The pure-JS stand-in reached the ESM harness, whose modules link into native SourceTextModule graphs and were rejected (asset-modules webpack-ignore). Dispatch on the creator: only jest-runtime wrappers get the stand-in.
| constructor(exportNames, evaluationCallback, options = {}) { | ||
| this.identifier = options.identifier || ""; | ||
| this.context = options.context; | ||
| this.status = "unlinked"; | ||
| this.error = undefined; | ||
| this._evaluationCallback = evaluationCallback; | ||
| this._namespace = Object.create(null); | ||
| Object.defineProperty(this._namespace, Symbol.toStringTag, { | ||
| value: "Module" | ||
| }); | ||
| } | ||
|
|
||
| setExport(name, value) { | ||
| this._namespace[name] = value; | ||
| } |
| // Bun segfaults while jest drives a native `vm.SyntheticModule` (its CJS/core | ||
| // wrapper for dynamic `import()`) through link/evaluate inside the jest | ||
| // environment context. Substitute a pure-JS stand-in with the same lifecycle | ||
| // API — jest's resolution/mocks/process globals still apply, but no native vm | ||
| // module code runs. |
| // Only jest-runtime's wrappers get the stand-in: they stay in JS and the | ||
| // dynamic-import boundary below unwraps them to a namespace. Any other | ||
| // creator (e.g. the ESM test harness) links the module into a native | ||
| // SourceTextModule graph, which requires a real native instance. |
| + // webpack: Bun honors __esModule and unwraps once already; the upstream | ||
| + // double `.default` is Node-only interop. Drop with this patch file when | ||
| + // a webpack-cli release ships the fix. |
Types CoverageCoverage after merging test/webpack-cli-bun into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Summary
WebpackCli.longtest.jswas skipped on Bun because Bun 1.3.11 segfaults when jest drives a nativevm.SyntheticModule(its dynamicimport()wrapper) through link/evaluate; the Bun preloader now substitutes a pure-JS stand-in for jest-runtime's wrappers, and webpack-cli is bumped to ^7.2.1, which ships the CLIPlugin import interop fix from webpack/webpack-cli#4799. The suite now passes 20/20 under Bun and stays 20/20 under Node.What kind of change does this PR introduce?
test
Did you add tests for your changes?
No new tests; the previously-skipped
test/WebpackCli.longtest.jssuite now runs under Bun.Does this PR introduce a breaking change?
No
If relevant, what needs to be documented once your changes are merged or what have you already documented?
n/a
Use of AI
Written with Claude Code: it diagnosed the Bun segfault and interop bug and authored the fix; verified by running the suite under Bun 1.3.11 and Node, plus lint/format checks.