Skip to content

test(bundler): run esbuild/importstar.test.ts concurrently and tighten its assertions - #41028

Merged
Jarred-Sumner merged 1 commit into
mainfrom
robobun/0dbbc3bb/importstar-concurrent
Sep 1, 2026
Merged

Jarred-Sumner merged 1 commit into
mainfrom
robobun/0dbbc3bb/importstar-concurrent

Conversation

@robobun

@robobun robobun commented Aug 31, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • test/bundler/esbuild/importstar.test.ts takes 11s on the debian 13 x64-asan lane (build 108747). The default itBundled backend is api, which the harness registers with it.serial (expectBundled.ts:1962), so its 75 cases run one at a time. 64 of them spawn a subprocess for run.
  • Three cases only check that the build succeeds. ImportStarMangleNoBundleNoCapture is a copy of the Capture case.

Fix

  • Default the file to the CLI backend (the wrapper from bundler_compile.test.ts) and use describe.concurrent. Error and warning cases pass on it unchanged.
  • New checks: ImportStarAndCommonJS runs the bundle, no __commonJS wrapper. ExportSelfIIFE runs the bundle, no __reExport helper. ImportExportOtherAsNamespaceCommonJS requires the bundle and checks the JSON. ImportStarNoCapture and ImportStarExportStarNoCapture: no namespace object (__export). ImportStarMangleNoBundleNoCapture gets the upstream no-capture entry point.
  • Verified: bun bd test test/bundler/esbuild/importstar.test.ts (debug, ASAN): 35.3s and 35.4s before, 12.4s to 14.5s after (six runs). Released bun: 0.7s before, 0.25s after. 75 pass, 4 todo, every run. expect() calls: 64 before, 71 after.

Background

  • The api backend calls Bun.build() in the test process with process.chdir, so the harness makes it serial. The cli backend spawns bun build in the case's own directory and can overlap.
  • bun test runs consecutive concurrent cases as one group of up to 20. A serial case ends the group, so the no-run cases also use cli (on api they measured 15.4s).
  • __export builds a namespace object. __commonJS wraps a CommonJS module. __reExport copies exports at runtime for export * of an external module.
Notes

What was not changed, and why:

  • ImportStarExportStarAsNoCapture and ImportStarExportImportStarNoCapture get no __export check. Bun still materializes the namespace for ns.foo through a re-export (esbuild binds foo directly). bundler: bind property accesses on re-exported namespaces directly #41009 changes that and adds cases at the end of this file. This branch does not touch those lines.
  • ImportDefaultNamespaceComboNoDefault1 to 4 stay separate builds. Bun reports only the first entry point's error, so one build with four entry points would check one error instead of four.
  • No case in the file sets timeoutScale.
  • No cases are grouped into shared builds. Each case has its own module graph with the same file names (entry.js, foo.js, bar.js).

Other checks:

  • bun bd test ... --todo: the 4 todo cases still fail, as on main.
  • BUN_BUNDLER_TEST_USE_ESBUILD=1: main fails 32 cases because the API backend passes neither format nor external to esbuild.build(). This branch fails 2: ImportStarCommonJSCapture (esbuild adds default to the CommonJS namespace, noted in the case) and ReExportStarEntryPointAndInnerFileExternal (bundler: fix re-exports of the "bun" builtin with --target=bun #37829).
  • Mutation check of the new output checks with the released bun: capturing ns in ImportStarNoCapture makes __export appear and the case fails. A CommonJS foo.js in ImportStarAndCommonJS makes __commonJS appear and the case fails.
  • Line 2 (the itBundled import) also changes in bundler: emit namespace binding for runtime export * from <external> #36714 and js_printer: parenthesize missing-import void 0 on LHS of ** #36134 (they add expect to line 1). The merge conflict is those two lines.
  • Debug ASAN runs after the change: 12.4s, 12.4s, 12.5s, 14.1s, 12.6s, 14.5s (runner's own Ran 79 tests line, host load average about 30). Released bun: 0.78s and 0.67s before, 0.25s and 0.24s after.

[stamp-90s] gate passed · iteration 0 · 1 files touched

passes on PR (with fix)
Test-only change.

Debug/ASAN (expected pass):
$ bun bd test 'test/bundler/esbuild/importstar.test.ts'
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test test/bundler/esbuild/importstar.test.ts
bun test v1.4.1 (a6c4cc276)

test/bundler/esbuild/importstar.test.ts:
(pass) bundler > importstar/ImportStarExportImportStarUnused [860.67ms]
(pass) bundler > importstar/ImportStarCapture [933.82ms]
(pass) bundler > importstar/ImportStarUnused [1362.73ms]
(pass) bundler > importstar/ImportStarExportImportStarNoCapture [981.69ms]
(pass) bundler > importstar/ImportStarNoCapture [1252.30ms]
(pass) bundler > importstar/ImportStarExportImportStarCapture [737.57ms]
(pass) bundler > importstar/ImportStarExportStarAsUnused [729.34ms]
(pass) bundler > importstar/ImportStarExportStarAsNoCapture [754.71ms]
(pass) bundler > importstar/ImportStarExportStarAsCapture [944.90ms]
(pass) bundler > importstar/ImportStarExportStarUnused [767.40ms]
(pass) bundler > importstar/ImportStarExportStarCapture [680.23ms]
(pass) bundler > importstar/ImportStarCommonJSUnused [664.77ms]
(pass) bundler > importstar/ImportStarExportStarNoCapture [791.44ms]
(pass) bundler > importstar/ImportStarCommonJSNoCapture [701.31ms]
(pass) bundler > importstar/ImportStarCommonJSCapture [782.90ms]
(pass) bundler > importstar/ImportStarNoBundleUnused [414.74ms]
(pass) bundler > importstar/ImportStarAndCommonJS [682.71ms]
(pass) bundler > importstar/ImportStarNoBundleCapture [696.13ms]
(pass) bundler > importstar/ImportStarNoBundleNoCapture [689.50ms]
(pass) bundler > importstar/ImportStarMangleNoBundleUnused [726.10ms]
(pass) bundler > importstar/ImportStarMangleNoBundleCapture [718.23ms]
(pass) bundler > importstar/ImportStarMangleNoBundleNoCapture [640.67ms]
(pass) bundler > importstar/ImportExportStarAmbiguousError [366.27ms]
(pass) bundler > importstar/ImportStarExportStarOmitAmbiguous [723.51ms]
(pass) bundler > importstar/ImportExportStarAmbiguous [604.14ms]
(pass) bundler > importstar/ReExportStarNameCollisionNotAmbiguousImport [606.40ms]
(pass) bundler > importstar/ReExportS
... (truncated)
Exit: 0
diff hotspot
test/bundler/esbuild/importstar.test.ts | 44 ++++++++++++++++++++++++++++++---
 1 file changed, 40 insertions(+), 4 deletions(-)

gate history · 1 passed · 0 rejected · iteration 0

evidence per changed file
file                                     reads  edits  tests
test/bundler/esbuild/importstar.test.ts      2      9      0

…n its assertions

Default every case to the CLI backend and switch the describe block to
describe.concurrent. itBundled registers API-backend cases with it.serial,
so the file ran its 75 cases one at a time.

Add runtime and output checks to the cases that only checked that the
build succeeds, and give ImportStarMangleNoBundleNoCapture the no-capture
entry point it was ported for.
@robobun

robobun commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator Author

Status: ready for review. This PR only changes test/bundler/esbuild/importstar.test.ts.

Reproduced the slow run locally with bun bd test test/bundler/esbuild/importstar.test.ts (debug, ASAN): 35.3s and 35.4s on main, 12.4s to 14.5s on this branch over six runs, 75 pass and 4 todo each time. The CI asan lane number for this branch comes from the build on this PR.

@coderabbitai

coderabbitai Bot commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0c3de7aa-515b-4a67-a0be-820b1edc21a8

📥 Commits

Reviewing files that changed from the base of the PR and between 2a0fda9 and 0e20d0c.

📒 Files selected for processing (1)
  • test/bundler/esbuild/importstar.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.


Walkthrough

The import-star bundler tests now use the CLI backend and concurrent execution. They add assertions for omitted namespace helpers, ES module/CommonJS behavior, direct namespace property access, IIFE self-re-exports, and CommonJS namespace serialization.

Changes

Import-star bundler test coverage

Layer / File(s) Summary
Test harness execution
test/bundler/esbuild/importstar.test.ts
The tests default to the CLI backend and run concurrently.
Static helper elimination
test/bundler/esbuild/importstar.test.ts
The tests verify that unused namespace and re-export helpers are omitted from generated output.
Runtime namespace behavior
test/bundler/esbuild/importstar.test.ts
The tests validate CommonJS interop, direct namespace property access, IIFE self-re-exports, and CommonJS namespace serialization.

Merge Risk: ⚪ Minimal · up to 0e20d

This test-only change runs the import-star cases concurrently and strengthens their assertions, with the full test file passing repeatedly and completing faster. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description check ✅ Passed The description clearly explains the problem, implementation, verification steps, performance results, scope, and known limitations. It does not use the exact template headings, but it includes the re…
Title check ✅ Passed The title is concise, specific, and accurately summarizes the main changes: concurrent execution and stronger assertions in the import-star bundler tests.
Full details: Description check

Explanation

The description clearly explains the problem, implementation, verification steps, performance results, scope, and known limitations. It does not use the exact template headings, but it includes the required purpose and verification information.


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

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM — test-only change following the established bundler_compile.test.ts wrapper pattern, with strictly tighter assertions.

What was reviewed:

  • Concurrency safety: expectBundled.ts keys each case's root dir on its unique id and only the API backend touches process.chdir/configRef, so CLI cases overlap cleanly under describe.concurrent (matches 15 other bundler test files already doing this).
  • ImportStarMangleNoBundleNoCapture input change: the old body was a copy-paste of the Capture case; the new ns.foo, ns.foo body matches the other *NoCapture tests in this file and the Capture variant still exists unchanged, so no coverage is lost.
  • New onAfterBundle .not.toContain("__export"/"__commonJS"/"__reExport") checks and the added run:/runtimeFiles blocks mirror existing patterns in this file and esbuild/dce.test.ts/splitting.test.ts.
Extended reasoning...

Overview

This PR touches a single file, test/bundler/esbuild/importstar.test.ts. It (1) wraps itBundled to default every case to backend: "cli" and switches the outer describe to describe.concurrent, (2) fixes ImportStarMangleNoBundleNoCapture, which was previously byte-identical to the Capture variant, to actually use a non-capturing entry point, and (3) adds onAfterBundle assertions that runtime helpers (__export, __commonJS, __reExport) are absent plus run:/runtimeFiles stdout checks to four cases that previously only asserted the build succeeded. No production code changes.

Security risks

None. This is a test-only change to a bundler test file; it introduces no new inputs, no network access, no auth/crypto/permissions surface.

Level of scrutiny

Low-to-moderate. The wrapper is byte-identical to test/bundler/bundler_compile.test.ts:13, and describe.concurrent is already used across 15+ bundler test files. I verified in expectBundled.ts that (a) each case writes to path.join(tempDirectory, id) so concurrent cases never share a directory, and (b) only the API backend uses process.chdir and the module-global configRef — the harness itself registers API cases as it.serial for exactly this reason (line 1962-1965). Forcing CLI here does not drop meaningful Bun.build coverage: these are esbuild-ported semantic tests of bundler output, not JS-API-surface tests, and the bundler codepath is shared.

Other factors

The one input mutation (ImportStarMangleNoBundleNoCapture) is a fix to a mislabeled duplicate rather than repurposing a test — the Capture variant remains at line 325 with its original JSON.stringify(ns) assertion, so REVIEW.md's "never mutate an existing test's input to the new case" is satisfied. The new .not.toContain helper-name checks are stable bundler runtime symbols (used the same way elsewhere in the suite) and each is commented with the invariant it locks in. The new runtimeFiles/run: { file: "/test.js" } addition to ExportOtherAsNamespaceCommonJS copies the exact pattern from the adjacent ImportExportOtherAsNamespaceCommonJS case. No CODEOWNERS entry covers this path, the timeline shows no prior reviews or objections, and the bug-hunt exit reason was dry_streak.

@Jarred-Sumner
Jarred-Sumner merged commit 7e77beb into main Sep 1, 2026
7 of 8 checks passed
@Jarred-Sumner
Jarred-Sumner deleted the robobun/0dbbc3bb/importstar-concurrent branch September 1, 2026 00:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants