Skip to content

fix(typescript): no loader required under Bun - #5699

Open
mirao wants to merge 1 commit into
codeceptjs:4.xfrom
mirao:fix/5697-bun-typescript-loader
Open

fix(typescript): no loader required under Bun#5699
mirao wants to merge 1 commit into
codeceptjs:4.xfrom
mirao:fix/5697-bun-typescript-loader

Conversation

@mirao

@mirao mirao commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #5697

Problem

require: ['tsx/esm'] is mandatory even when running under Bun, which transpiles TypeScript natively. Without it the run aborts with process.exit(1) and the "TypeScript Test Files Detected but No Loader Configured" banner — although the tests run perfectly fine once the check is bypassed.

checkTypeScriptLoader() only string-matches the require array against a hardcoded list of Node loaders; there is no check of whether the runtime already handles TypeScript. So under Bun the require entry exists purely to satisfy that string match, and tsx sits in devDependencies and is imported on every run only to do nothing.

Bun's module.register() is a no-op stub, so tsx's resolve/load hooks are never invoked. Verified with a hooks module that logs on every call: bun --bun produces no hook line at all (and the enum evaluates fine, Bun having transpiled it itself), while node --experimental-strip-types does fire the hooks.

Fix

Return true early from checkTypeScriptLoader() when process.versions.bun is set.

This is deliberately Bun-specific and not "skip the check whenever the runtime can do TypeScript". Node cannot replace tsx here: its native type stripping rejects enums (ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX) and does not resolve extensionless relative imports.

Verification

Ran the minimal reproduction from the issue against this branch — Bun 1.4.2, no require entry, tsx not installed:

Run Result
Bun, with fix ✔ plain TS scenario with an enumOK | 1 passed
Bun, fix reverted loader banner, exit 1
Node, with fix loader banner (unchanged, as intended)

The Node row is the negative control: the fix is Bun-gated, so Node still demands a real loader — which it must, since native type stripping rejects the enum in that very repro file.

Also confirmed on a real 14-suite Playwright project (~1900 tests): removing the require line and deleting tsx from node_modules entirely, a full browser run passed unchanged — page objects, enums and extensionless relative imports included.

Tests

lib/utils/loaderCheck.js had no unit coverage. Added test/unit/utils/loaderCheck_test.js, which stubs process.versions.bun (mutable under both runtimes) and restores it in afterEach, pinning both the new Bun branch and the pre-existing Node behaviour so the loader list cannot regress silently.

  • New file: 5 passing
  • Full unit suite (mocha test/unit --recursive): 775 passing, 11 pending, 0 failing
  • eslint and prettier clean

🤖 Generated with Claude Code

Bun transpiles TypeScript natively, so `module.register()` is a no-op stub
and a registered tsx/ts-node loader never runs. checkTypeScriptLoader() only
string-matched the `require` array against a hardcoded list of Node loaders,
so `require: ['tsx/esm']` was mandatory under Bun purely to satisfy that
match, forcing tsx into devDependencies to do nothing on every run.

Return true early when process.versions.bun is set. This is deliberately
Bun-specific rather than "skip the check when the runtime handles
TypeScript": Node cannot replace tsx here, as its native type stripping
rejects enums and does not resolve extensionless relative imports.

Adds unit tests for loaderCheck.js, which had no coverage, pinning both the
new Bun branch and the existing Node behaviour.

Fixes codeceptjs#5697

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

4.x: Bun: require: ["tsx/esm"] is mandatory even though tsx isn't used under Bun

2 participants