Repository navigation
Conversation
|
Warning Review limit reached
Next review available in: 20 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis PR fixes POSIX shell variable semantics for ChangesShell export and assignment semantics
Sequence Diagram(s)sequenceDiagram
participant Script as Shell Script
participant Interpreter as ShellExecEnv
participant ExportBuiltin as Export::start
participant EnvMap as EnvMap
Script->>Interpreter: assign_var(NAME, value, AssignCtx::Shell)
Interpreter->>EnvMap: check export_env for NAME
alt NAME already exported
Interpreter->>EnvMap: remove(NAME) from shell_env
Interpreter->>EnvMap: insert into export_env
else NAME not exported
Interpreter->>EnvMap: insert into shell_env
end
Script->>ExportBuiltin: export NAME[=value]
alt NAME=value
ExportBuiltin->>EnvMap: remove(NAME) from shell_env
ExportBuiltin->>EnvMap: insert into export_env
else NAME only
ExportBuiltin->>EnvMap: check shell_env / export_env
ExportBuiltin->>EnvMap: promote or preserve value in export_env
end
Compact metadata
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
|
Updated 9:55 PM PT - Jul 6th, 2026
❌ @robobun, your commit 7bb237c has 2 failures in
🧪 To try this PR locally: bunx bun-pr 33550That installs a local version of the PR into your bun-33550 --bun |
|
Found 1 issue this PR may fix:
🤖 Generated with Claude Code |
|
Good catch, fixed in f3db27c. The
|
|
Note on the auto-linked issue: this PR does not fix #32202. That issue is about the |
|
Fixed in b2561c9. The export builtin now uses the same shadow-clearing logic:
Added four tests covering these forms, all matching bash. The |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/js/bun/shell/bunshell.test.ts`:
- Around line 1006-1051: These independent subprocess-spawning shell tests
should run concurrently instead of sequentially. Update each of the seven test
declarations in bunshell.test.ts to use test.concurrent while keeping the
existing bodies and env isolation intact, so the cases around
reassigning/exporting FOO and OUTER can execute in parallel without shared-state
issues.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 3109313d-dfa7-4641-ba99-8d82dc8b1d16
📒 Files selected for processing (4)
src/runtime/shell/EnvMap.rssrc/runtime/shell/builtin/export.rssrc/runtime/shell/interpreter.rstest/js/bun/shell/bunshell.test.ts
There was a problem hiding this comment.
Both earlier findings are addressed and the refcount flow traces cleanly on every path, but the final shape — manual ref/deref across an unsafe get→remove→insert sequence plus the new export NAME promote/preserve semantics in b2561c9 — is the kind of change a shell maintainer should sign off on rather than me auto-approving.
Extended reasoning...
Overview
Touches four files: adds EnvMap::remove (derefs the owned key/value on swap-remove), reworks ShellExecEnv::assign_var's AssignCtx::Shell arm to route reassignments of already-exported names into export_env and clear any shell-local shadow, and substantially expands the export builtin to (a) clear the shell-local shadow on export NAME=value and (b) handle export NAME with no = by promoting a shell-local value / preserving an already-exported one instead of unconditionally blanking it. Seven new tests in bunshell.test.ts cover shell-view and child-view for each form.
Security risks
None identified. This only changes which of three in-process EnvMaps a shell variable lands in; no new external input parsing, no path handling, no privilege boundaries.
Level of scrutiny
Medium-high. The logic itself is small and well-tested, but it lives in unsafe blocks doing manual EnvStr refcounting — exactly the category CLAUDE.md calls out as most-blocked. I traced every path (including the get→remove→insert→deref ordering in the export NAME promote branch, where the get's +1 keeps the value alive across remove's -1) and the counts balance. But this PR has already needed two correction rounds, and b2561c9 expanded scope beyond the original fix into a semantic redesign of export NAME — that's a design decision a maintainer should confirm, not something to rubber-stamp.
Other factors
Both of my prior inline findings are resolved with dedicated tests. The bug-hunting pass on the latest revision found nothing. fetch_swap_remove exists on ArrayHashMap and returns owned (K, V), so EnvMap::remove is sound. The AssignCtx::Exported arm remains unpatched but is confirmed dead code. CI on 99929fc is still building. Net: I have no outstanding concerns, just not enough confidence in an unsafe-refcounting change with expanded scope to skip human review.
|
Status: the diff is green. All shell tests pass locally (full test/js/bun/shell/bunshell.test.ts, 393 pass) and the changed files (shell env handling) have no failures in CI. The only red lane on the latest run (build 69429) is test/napi/napi.test.ts under the "flaky" annotation, which is unrelated to this change and also flakes on main. An earlier run's unrelated failures (windows napi, windows update_interactive_install, aarch64 bun init timeout) were already re-rolled once. Needs a maintainer to merge. |
|
Closing as part of a cleanup of stale pull requests. This PR has had no new commits since 2026-07-06, it conflicts with main, and its last CI run failed. This is not a judgment on the fix itself. If the problem still reproduces on a current build, reopen this PR after a rebase or open a new one against main. |
What
In Bun Shell, a plain assignment to a variable that is already exported (inherited or set with
export) updated only the shell's own view. Child processes spawned afterward still received the original value, and the commonPATH=/opt/x/bin:$PATH tool/LC_ALL=C sortidioms silently ran with the stale value.Repro
echo $OUTERinside the shell reported the new value while the child got the old one, with no diagnostics and exit 0.Cause
The interpreter keeps three env maps:
shell_env(shell-local vars),cmd_local_env(NAME=value cmdprefixes), andexport_env(exported/inherited vars). A bareNAME=valuealways wrote intoshell_env(AssignCtx::Shell), but the child environment is built fromexport_env+cmd_local_envonly. So an assignment to an already-exported name landed inshell_env, which children never see, while$NAMEexpansion (which checksshell_envfirst) picked up the new value. The two maps disagreed.Fix
assign_varnow checks, for a bare assignment, whether the name already lives inexport_env. If it does, it updates the exported binding in place (POSIX: a variable that carries the export attribute keeps it on reassignment). Names that are not already exported still become shell-local, so a freshNEWV=nvis correctly not exported.Verification
Added three tests to
test/js/bun/shell/bunshell.test.tsundervariables:VAR="$VAR+more"reaches the childThe first two fail on the released binary and pass with the fix; the control passes both ways.