js_parser: sanitize auto-generated default export name for digit-named modules (#31403)
Fixes #31401
## Repro
```ts
// 1.ts
export default function () {}
```
```console
$ bun run 1.ts
SyntaxError: No identifiers allowed directly after numeric literal
```
Two conditions are both required: the module filename starts with a
digit (`1.ts`, `9abc.ts`, …) **and** the source has an anonymous default
function declaration (`export default function () {}`). Named defaults,
anonymous classes, and arrows are unaffected.
## Cause
An anonymous `export default function () {}` is given an auto-generated
name derived from the module filename (`<name>_default`). The transpile
/ `bun run` path does **not** run the renamer (only bundling /
`minify_identifiers` do), so the generated name is emitted verbatim:
```console
$ bun build --no-bundle 1.ts
export default function 1_default() {} # invalid identifier
```
`create_default_name` built this name with the non-allocating
`fmt_identifier()` formatter. Unlike the allocating
`nonUniqueNameString` helper the Zig reference used
(`MutableString.ensureValidIdentifier`), `fmt_identifier` does **not**
prepend an underscore when the name starts with a non-identifier-start
character — so the leading `1` passed through unchanged, yielding
`1_default`. JSC's lexer then rejects `1_default` as a numeric literal
followed by an identifier.
The bundler path was fine because its `NumberRenamer` runs
`ensure_valid_identifier` on every name, rewriting `1_default` →
`_1_default`. This is effectively a regression of #2946 on the
no-renamer path: names must be generated valid up-front there.
## Fix
In `create_default_name`, sanitize the filename-derived base with
`MutableString::ensure_valid_identifier` (which carries the #2946
leading-underscore fix) before appending `_default`, matching the Zig
`createDefaultName` and the bundler output:
```console
$ bun build --no-bundle 1.ts
export default function _1_default() {} # valid
```
Non-digit filenames are unchanged (`foo.ts` → `foo_default`).
## Verification
- `bun run 1.ts` now exits 0.
- New regression test `test/regression/issue/31401.test.ts` covers the
`bun run`, `import`, and transpile-only paths. Fails with
`USE_SYSTEM_BUN=1` (3 fail), passes with the debug build (3 pass).
- `test/bundler/bundler_regressions.test.ts` (incl.
`InvalidIdentifierInFileName#2946`) and
`test/bundler/transpiler/transpiler.test.js` (156 pass) remain green.
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> R
robobun committed
146afa332a698f803a087f0d78eab801fe9ba96b
Parent: 0974d03
Committed by GitHub <noreply@github.com>
on 5/26/2026, 1:33:05 AM