Skip to content

bunfig: honor smol and install.prefer for bun file.js / bun test, and let the flags override them for bun run - #38611

Open
robobun wants to merge 1 commit into
mainfrom
farm/a5f0ba68/bunfig-smol-prefer-cli-precedence
Open

bunfig: honor smol and install.prefer for bun file.js / bun test, and let the flags override them for bun run#38611
robobun wants to merge 1 commit into
mainfrom
farm/a5f0ba68/bunfig-smol-prefer-cli-precedence

Conversation

@robobun

@robobun robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Problem

  • smol = true in bunfig.toml is ignored by bun file.js and bun -e, and [test] smol = true is ignored by bun test. Only bun run file.js honors it.
  • In the other direction, bun run --smol file.js with smol = false in bunfig.toml runs without smol mode: the file overrides the flag, although the bunfig docs say CLI flags override bunfig.toml.
  • install.prefer (--prefer-offline / --prefer-latest) has the same two problems.
  • Cause: Arguments::parse (src/runtime/cli/Arguments.rs) assigns ctx.runtime_options.smol = args.flag("--smol") and ctx.debug.offline_mode_setting = Some(...) unconditionally. For bun file.js, bun -e and bun test it has already applied bunfig.toml at that point (load_config_with_cmd_args), so with no flag on the command line both assignments reset what the file set (src/bunfig/bunfig.rs: top-level smol, [test] smol, install.prefer).
  • bun run <target> loads bunfig.toml later, from RunCommand, and the bunfig parser assigned the keys unconditionally, so there the file overwrote a flag that was given.

Fix

  • Arguments::parse only writes the two settings when the flag is present. Without a flag offline_mode_setting stays None, which all three readers (RunCommand, bun repl, bun build --app) already map to online, so the default is unchanged.
  • A flag that is present is also recorded in ctx.cli_overrides (new CliOverrides in src/options_types/context.rs), and the bunfig parser skips the assignment for a recorded key (the key is still type-checked). This is the mechanism test.pathIgnorePatterns already uses (path_ignore_patterns_from_cli), and it gives the same result in both load orders without touching the late-load sites.
  • bunfig: keep CLI flags ahead of bunfig.toml when it is loaded after argv (bun run) #38599 adds the same cli_overrides struct for the keys that were only broken in the bun run order; it leaves smol and install.prefer to this PR. The struct and field are named the same here so whichever lands second only has to merge the field lists.
  • Test: test/config/bunfig/smol.test.ts. Smol mode has no direct JS reflection; on Linux it lowers the size at which a Blob is backed by a memfd from 8 MiB to 1 MiB (LinuxMemFdAllocator::should_use), so a 2 MiB Blob plus a look at /proc/self/fd tells the two modes apart with an unmodified binary. The cases cover bun file.js, bun -e, bun run file.js, bun test, and --smol beating smol = false / [test] smol = false with the flag before and after the subcommand. Linux only because of the probe; the code under test is not platform specific.
    • On the release build of main, 5 of the 13 cases fail (smol = true with bun index.js and with bun -e, [test] smol = true with bun test, smol = false with bun run --smol and with bun --smol run); with this change all 13 pass.
  • install.prefer gets the same code change but no behavioural test: on main, --prefer-offline itself has no observable effect on auto-install (the disk cache lookup it enables never matches; install: make --prefer-offline resolve auto-installs from the disk cache #36776 fixes that, and I confirmed the flag changes nothing on main with that PR's scenario), so neither the flag nor the key can be distinguished from the default yet. Once install: make --prefer-offline resolve auto-installs from the disk cache #36776 lands, its --prefer-offline test with prefer = "offline" in bunfig.toml covers this path.
  • Also ran test/config/bunfig/, test/cli/run/run-autoinstall.test.ts, test/cli/run/autoinstall-cached-manifest.test.ts, test/regression/issue/24387.test.ts, the execArgv tests in test/js/node/worker_threads/worker_threads.test.ts and test/bundler/compile-argv.test.ts (standalone executables parse their execArgv through the same function): all pass. cargo fmt --check is clean.

Background

  • ContextData (ctx, src/options_types/context.rs) is the process-wide record of parsed CLI state. Both Arguments::parse and the bunfig parser write into it, and the commands read from it afterwards (RunCommand::boot, bun test, the REPL, the parallel test runner); whichever writer runs second owns a field.
  • bunfig.toml is loaded at one of two points. bun test, bun -e, and bun file.js with a known extension load it inside Arguments::parse, before the runtime flags are applied. bun run <target>, bun <script>, the node shim and bun repl skip that and load it once argv parsing is done (the loaded_bunfig checks in run_command.rs / repl_command.rs). A setting that both argv and the file can set has to come out the same either way.
  • smol (--smol) makes RunCommand / bun test / the REPL create the JSC VM with a small heap and makes a few native caches release memory eagerly; the memfd threshold the test observes is one of those knobs.
  • install.prefer / --prefer-offline / --prefer-latest set ctx.debug.offline_mode_setting, which becomes the runtime auto-installer's install_preference.

… let the flags win over the file

Arguments::parse wrote ctx.runtime_options.smol and
ctx.debug.offline_mode_setting unconditionally, after bunfig.toml had
already been applied for `bun file.js`, `bun -e` and `bun test`, so
`smol = true`, `[test] smol = true` and `install.prefer` in bunfig.toml
had no effect there. For `bun run file.js` bunfig.toml is loaded later
and overrode --smol / --prefer-* instead.

Only write the two settings when the flag is present, and record flags
given on the command line in ctx.cli_overrides so the bunfig parser
leaves those keys alone whichever of the two is applied first.
@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: 32 seconds

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: a51affda-75d2-473c-9eb8-c5cb53a3d89e

📥 Commits

Reviewing files that changed from the base of the PR and between 2f5c180 and 77f22ef.

📒 Files selected for processing (4)
  • src/bunfig/bunfig.rs
  • src/options_types/context.rs
  • src/runtime/cli/Arguments.rs
  • test/config/bunfig/smol.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: reproduced on the release build of main with the Linux memfd probe used in test/config/bunfig/smol.test.ts (5 of the 13 cases fail there: smol = true with bun index.js / bun -e, [test] smol = true with bun test, and smol = false with bun run --smol / bun --smol run); all 13 pass with this branch. install.prefer gets the same code change; it cannot be observed on main until #36776 lands (details in the description). Sibling change for the other keys: #38599.

CI: 177 of 179 jobs passed with no test failures; the build is marked failed only because the two darwin 14 aarch64 - test-bun jobs expired without ever being picked up by an agent. The new tests are Linux-only and passed on every Linux lane; the changed code is not platform specific. Ready for review as is; I have not retriggered, since that would re-run the whole build against the same macOS queue.

@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 — focused fix for CLI-flag vs bunfig.toml precedence on smol and install.prefer.

What was reviewed:

  • Verified all three readers of offline_mode_setting (run_command.rs, repl_command.rs, bake/production.rs) already .unwrap_or(Online), so leaving it None when no flag is passed preserves the default.
  • Confirmed the CliOverrides gate in bunfig.rs still type-checks the key even when the flag wins, and matches the existing path_ignore_patterns_from_cli pattern.
  • Checked the memfd probe against LinuxMemFdAllocator::should_use (1 MiB vs 8 MiB threshold) and the memfd-num- label — a 2 MiB Blob distinguishes the two modes; can_use_memfd() failing would produce a false fail, not a false pass.
  • Traced both load orders (bunfig-before-flags for bun file.js/-e/test at Arguments.rs:921, bunfig-after-flags for bun run) — the flag wins in each.
Extended reasoning...

Overview

Four files: src/runtime/cli/Arguments.rs stops unconditionally overwriting ctx.runtime_options.smol and ctx.debug.offline_mode_setting when the corresponding flags are absent, and records presence in a new ctx.cli_overrides. src/options_types/context.rs adds the two-field CliOverrides struct to ContextData. src/bunfig/bunfig.rs skips assigning smol / [test].smol / install.prefer when the corresponding CLI override bit is set (still runs the type check). test/config/bunfig/smol.test.ts covers 13 combinations across bun file.js, bun -e, bun run, and bun test, with the flag before and after the subcommand.

Security risks

None. This is CLI/bunfig option precedence for --smol (heap sizing) and --prefer-offline/--prefer-latest (auto-install cache preference). No untrusted input parsing, no auth/crypto/permissions.

Level of scrutiny

Low-to-moderate. The change is small (~30 net lines of Rust), mechanical, and follows the exact pattern already used for test.pathIgnorePatterns (path_ignore_patterns_from_cli). The only behavioral risk was that leaving offline_mode_setting as None (rather than Some(Online)) might change a reader's behavior; I grepped all three readers and each does .unwrap_or(OfflineMode::Online), so the default is preserved.

Other factors

  • The test is Linux-only by necessity (the memfd threshold is the only externally observable smol-mode signal without adding test-only hooks), but the code under test is platform-agnostic. The probe is anchored to real constants in LinuxMemFdAllocator::should_use (1 MiB vs 8 MiB) and the memfd-num- label, and asserts the exact blob size so a probe failure surfaces rather than passing vacuously.
  • install.prefer gets the same code fix without a test; the description explains this is because --prefer-offline itself is currently unobservable on main (pending #36776), which is a reasonable justification.
  • The CliOverrides struct is deliberately named to merge cleanly with sibling PR #38599.
  • No CODEOWNERS coverage on the touched files. No prior reviewer comments to address.

@github-actions

Copy link
Copy Markdown
Contributor

This PR may be a duplicate of:

  1. bunfig: keep CLI flags ahead of bunfig.toml when it is loaded after argv (bun run) #38599 - Adds the identically-named CliOverrides struct and ctx.cli_overrides field to the same three files for the same CLI-beats-bunfig fix, just for a different key set (define/loader/jsx/console-depth/install.auto/macros/preload).
  2. Make CLI flags override their [run] counterparts in bunfig.toml #33198 - Same three files, same "flag was passed → bunfig must not overwrite it" fix (via *_from_cli bools instead of a struct) for the [run] bun/silent/shell/elideLines keys.
  3. cli(test): make --coverage/--coverage-reporter/--coverage-dir override bunfig #36669 - Same three files and same override-tracking pattern for the [test] coverage keys; its bunfig.rs hunk is the block immediately after the [test] smol block this PR guards.
  4. Fix object loader missing default export and coverage CLI flag override #28547 - Contains the same [test] coverage override fix in the same three files, bundled with an unrelated ObjectModule.cpp change.

🤖 Generated with Claude Code

@robobun

robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Not duplicates: none of #38599, #33198, #36669 or #28547 touch smol or install.prefer (checked their diffs of the three shared files). They apply the same flag-beats-bunfig pattern to other keys; #38599 lists these two as out of scope and is where the shared CliOverrides name comes from. The overlap is adjacent hunks in the same files, so whichever of them land first leave a field-list merge here.

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