Skip to content

Lint the loader name list in bun-types and the docs against src/ast/loader.rs - #38424

Open
robobun wants to merge 1 commit into
mainfrom
farm/8eb106a3/loader-names-lint
Open

robobun wants to merge 1 commit into
mainfrom
farm/8eb106a3/loader-names-lint

Conversation

@robobun

@robobun robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Problem

Fix

Background

  • A loader is how Bun turns a file into a module. Its name is what users write in bun build --loader .ext:name, Bun.build({ loader: { ".ext": "name" } }), bunfig [loader] and plugin onLoad results, and what BuildArtifact.loader / OnLoadArgs.loader return. The Loader union in bun-types is the type of all of those.
  • src/ast/loader.rs holds the enum (#[strum(serialize_all = "snake_case")], so SqliteEmbedded is the name sqlite_embedded) and LOADER_NAMES, the table Loader::from_string accepts. The table also has aliases (mjs, node, txt, markdown, ...), which is why the lint derives the list from the variants and only looks the canonical name up in the table.
  • test/internal/source-lints/ holds tests that only read the source tree; .buildkite/ci.mjs excludes them from the binary lanes and .github/workflows/source-lints.yml runs them against a released bun, so this needs no build. Delete the schema::api mirror types and bun_api; one loader numbering across Rust/C++/JS #37095 adds loader-numbering.test.ts to the same directory for the numeric discriminant copies (C header, Rust plugin crate); this lint covers the names and does not overlap with it.
Lint output against main's copies, and the 1.4.0 runs behind the synced names
(pass) src/ast/loader.rs: notPublic only names variants of the Loader enum
(pass) src/ast/loader.rs: LOADER_NAMES accepts every public loader under its own name
(fail) packages/bun-types/bun.d.ts: the Loader union lists the public loaders
    -   "json5",
    -   "md",
(fail) docs: every `type Loader` snippet lists the public loaders
    docs/bundler/index.mdx      -  "json5",  -  "md",  -  "xml",
    docs/bundler/plugins.mdx    -  "json5",  -  "md",  -  "xml",
    docs/runtime/plugins.mdx    -  "json5",  -  "md",  -  "xml",
$ bun --version
1.4.0
$ bun build ./e.mjs --loader .j5:json5 --loader .mdx2:md --loader .xm:xml --outdir out && bun out/e.js
{"a":1,"b":[1,2]} "<h1>Title</h1>\n<p>hello</p>\n" {"r":{"a":{"@v":"1"}}}
$ # Bun.build({ entrypoints: ["./data.json5", "./doc.md", "./conf.xml"] }) -> outputs.map(o => o.loader)
[["data.js","json5"],["doc.js","md"],["conf.js","xml"]]

Why the excluded names are excluded, on 1.4.0 (Bun.build({ loader: { ".sh": name }, target: "bun" })):

base64          -> bundles, module is `var s_default = "";`      (empty-module stub, src/bundler/ParseTask.rs)
dataurl         -> bundles, module is `var s_default = "";`      (same)
sh              -> bundles as the file loader (asset copied)
bunsh           -> rejected as a loader name
sqlite          -> bundles as import.meta.require(path, { type: "sqlite" }).db, but is not in the union (#38247)
sqlite_embedded -> rejected as a loader name today (#38247)

…oader.rs

The public loader names are the snake_case variants of bun_ast::Loader.
The Loader union in packages/bun-types/bun.d.ts and the three
`type Loader =` snippets in the docs are hand-written copies of that
list, and recent loaders landed with some copies stale: json5 and md
never reached the union, xml never reached the docs snippets.

Add test/internal/source-lints/loader-names.test.ts, which derives the
public names from the enum minus an explicit, commented list of
variants that are deliberately not in the union (base64, dataurl,
bunsh, sqlite, sqlite_embedded), and asserts that LOADER_NAMES accepts
each public name, that the bun.d.ts union equals the set, and that
every `type Loader` snippet under docs/ equals it. Bring the copies up
to date so the lint passes, and add bun.d.ts and docs/**/*.mdx to the
source-lints workflow triggers, since the lint reads them.
@robobun
robobun requested a review from alii as a code owner August 14, 2026 07:25
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 26 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: df7833f6-697e-4ff0-b020-a6d3b8d98bef

📥 Commits

Reviewing files that changed from the base of the PR and between 01aa7cd and c10cd0a.

📒 Files selected for processing (8)
  • .github/workflows/source-lints.yml
  • docs/bundler/index.mdx
  • docs/bundler/plugins.mdx
  • docs/runtime/plugins.mdx
  • packages/bun-types/bun.d.ts
  • src/ast/loader.rs
  • test/internal/source-lints/README.md
  • test/internal/source-lints/loader-names.test.ts

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

@robobun

robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Status: the lint in this PR fails against main's copies of the loader list (bun.d.ts union missing json5 and md; the three docs snippets missing json5, md and xml) and passes with the copies synced here. Run with bun test test/internal/source-lints/loader-names.test.ts, no build needed. Related in-flight PRs: #38267 (same sync hunks plus docs sections), #38247 and #36327 (each adds names to the union and will need to drop the matching notPublic entries and update the snippets once this lands), #37095 (the numbering lint in the same directory).

@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 — docs/types sync plus a source-lint that keeps them synced; no runtime code changes.

What was reviewed

  • Verified the new lint passes locally (4 tests, 17 expects) and that its enum/table regexes match src/ast/loader.rs as written; the [^}]* bodies have no nested braces.
  • Confirmed the added names (json5, md, xml) are real Loader variants and that docs/runtime/transpiler.mdx's skipped type Loader is genuinely a different (JS-only) subset.
  • Checked bun.d.ts has exactly one type Loader = declaration and the docs glob finds exactly the three snippets the test expects.
  • Workflow path triggers added symmetrically to both push and pull_request; the loader.rs hunk is comment-only.
Extended reasoning...

Overview

This PR adds a source-tree lint (test/internal/source-lints/loader-names.test.ts) that parses pub enum Loader and LOADER_NAMES from src/ast/loader.rs, derives the set of public loader names (enum variants minus a documented notPublic exclusion list), and asserts that the Loader string-literal union in packages/bun-types/bun.d.ts and every type Loader = snippet under docs/**/*.mdx equal that set. It also brings the currently-stale copies up to date (json5/md in bun.d.ts; json5/xml/md in three docs files), adds packages/bun-types/bun.d.ts and docs/**/*.mdx to the source-lints workflow's path filters, adds a pointer comment above the enum, and documents the path-filter requirement in the source-lints README.

Security risks

None. No runtime code is touched: the .rs hunk is a comment, the .d.ts hunk adds string-literal union members, the docs hunks are prose snippets, and the test only reads files from the repo tree. The workflow change only widens which paths trigger an existing read-only test job.

Level of scrutiny

Low. This is test + docs + type-declaration + CI-trigger territory with no compiled-code changes. The test follows the established pattern of the ~20 other regex-based lints already in test/internal/source-lints/. I ran it locally against the checked-out tree and it passes cleanly. The regex parsers are guarded against silent breakage (toBeGreaterThan(10) on the enum and table sizes, snippets.length > 0 on the docs scan, and an explicit assertion that the union body contains only string literals and |), so a future refactor of loader.rs or the docs that breaks the parser will fail loudly rather than pass vacuously.

Other factors

  • Verified via grep that bun.d.ts has exactly one type Loader = (line 5555), that the three docs files listed are the only full-union snippets, and that the skipped docs/runtime/transpiler.mdx declares the unrelated four-member JavaScriptLoader subset — the skip is correct.
  • The snakeCase helper correctly reproduces strum's snake_case for every current variant (checked SqliteEmbedded -> sqlite_embedded, Json5 -> json5).
  • The notPublic exclusions each carry a reason and are themselves asserted to name real variants, so they cannot go stale silently.
  • No prior human review comments; only bot noise (CodeRabbit rate-limit notice, robobun status).

@robobun

robobun commented Aug 14, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 5:05 AM PT - Aug 14th, 2026

❌ @robobun, your commit c10cd0a has some failures in Build #95677 (All Failures)


🧪   To try this PR locally:

bunx bun-pr 38424

That installs a local version of the PR into your bun-38424 executable, so you can run:

bun-38424 --bun

This branch has not been deployed

No deployments
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.

1 participant