Skip to content

Remove BunPluginTarget, the plugin target value that nothing reads - #46089

Open
robobun wants to merge 4 commits into
mainfrom
robobun/cf290376/remove-plugin-target-value
Open

robobun wants to merge 4 commits into
mainfrom
robobun/cf290376/remove-plugin-target-value

Conversation

@robobun

@robobun robobun commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • JSBundlerPlugin__create takes a BunPluginTarget and stores it in BundlerPlugin::target (src/jsc/bindings/JSBundlerPlugin.h:164). No code reads it, or the target member of three more classes.
  • The Bun.plugin helpers in BunPlugin.cpp take the same type and do not use it. Implement virtual module support in Bun.plugin #6167 removed the last reader in 2023.

Fix

  • Drop the parameter from JSBundlerPlugin__create, JSBundlerPlugin::create, both constructors, PluginJscExt::create and five Bun.plugin helpers. Delete the four members, the Rust enum and the C++ typedef.
  • Delete four host functions that have no caller. Without the parameter they are copies of the bun pair.
  • Correct because a word search of sources, tests, docs and generated code finds no reader. Verified: bun bd, bun run rust:check-all (12 targets), 8 test files (Notes).
  • Self-reviewed: 41 concerns raised, 14 survived, all addressed. Rejected: the removal of other unread parameters in these files, which are not this flow (Notes).

Background

  • Rust creates one JSBundlerPlugin cell for the plugins of Bun.build, of the bake config, and of [serve.static].
  • Bun.plugin({ target }) still throws a TypeError for a string other than node, bun or browser.
  • Unread code has one place to delete, so no other design was weighed.

Downsides

  • Six open pull requests gain merge conflict hunks (Notes). Each of them already conflicts with main.
  • None found for users. Checked: every caller of the changed functions and the target tests in plugins.test.ts.

Behaviour change: none

Notes

Removed

  • src/jsc/bindings/JSBundlerPlugin.h: the target members of BundlerPlugin, NamespaceList and NativePluginList, the constructor parameter, and the store this->target = target.
  • src/jsc/bindings/JSBundlerPlugin.cpp: the parameter of JSBundlerPlugin::create, of the private constructor, and of JSBundlerPlugin__create.
  • src/jsc/bindings/BunPlugin.h: the target member of BunPlugin::Group.
  • src/jsc/bindings/BunPlugin.cpp: the parameter of jsFunctionAppendOnLoadPluginBody, jsFunctionAppendOnResolvePluginBody, jsFunctionAppendOnLoadPluginGlobal, jsFunctionAppendOnResolvePluginGlobal and setupBunPlugin, and the argument at each call.
  • src/jsc/bindings/BunPlugin.cpp: the host functions jsFunctionAppendOnLoadPluginNode, jsFunctionAppendOnLoadPluginBrowser, jsFunctionAppendOnResolvePluginNode and jsFunctionAppendOnResolvePluginBrowser (20 lines). Each name occurs only at its definition, and setupBunPlugin registers only the Bun pair. With the parameter gone, each body is the same line as the Bun one. REVIEW.md says to delete one of two functions that a change makes identical.
  • src/jsc/bindings/headers-handwritten.h: BunPluginTarget, BunPluginTargetBun, BunPluginTargetBrowser, BunPluginTargetNode, BunPluginTargetMax.
  • src/runtime/api/JSBundler.rs: the BunPluginTarget enum, its assert_ffi_discr! and comment, its re-export, the parameter of the extern declaration and of PluginJscExt::create, and the match this.target that built the argument.
  • src/runtime/bake/config/bundler.rs, src/runtime/server/server_body.rs: the argument at the two other call sites.
  • src/opaque/lib.rs: the doc example of assert_ffi_discr! named BunPluginTarget. It now names Loader, which has a real use of the variant form in src/ast/loader.rs.

Changed

  • src/runtime/server/server_body.rs: the SAFETY comment below the changed call said that Plugin::create returns a boxed pointer. It returns a protected JSC cell, and heap::take is sound there because Plugin is a zero-sized type. The comment now says that. A review of this pull request found it. The field stays Box<Plugin>.

Kept

Found unread in the same files, and left

  • void* config in the same three signatures, with BundlerPlugin::config and JSBundlerPlugin__setConfig. C++ only passes the value back to the callbacks, and Rust names that argument _unused. Bun.build / Bun.Transpiler: remove unsafe from JSBundler, the completion task and JSTranspiler #40405 removes them.
  • The vm parameter of NamespaceList::append and of NativePluginList::append, the plugin parameter of NativePluginList::call, and the index out-parameter of NamespaceList::group and NamespaceList::append. They are not part of the target flow, and they stay for a change of their own.
  • The three callback parameters of the constructors. Every caller takes the default, but the members are called.

History

Merge with main

Open pull requests

Tests, debug build of this branch after the merge with main

  • test/js/bun/plugin/plugins.test.ts: 110 pass. This includes handles invalid 'target' and the two tests of a target that throws during string conversion.
  • test/js/bun/plugin/plugin-namespace-drive-letter.test.ts: 1 pass.
  • test/bundler/bundler_plugin.test.ts: 67 pass, 3 todo.
  • test/bundler/native-plugin.test.ts: 19 pass, 1 skip (with --timeout 1200000, because the beforeAll installs and compiles a native addon).
  • test/bake/serve-plugins-dev-server.test.ts: 11 pass.
  • test/bake/dev/plugins.test.ts: 3 pass.
  • test/bake/app-options.test.ts: 13 pass.
  • test/bundler/bun-build-api.test.ts: 87 pass, 1 skip, 1 todo, 3 timeouts. The two bytecode tests pass with --timeout 900000. Bun.build can be called thousands of times in one process without crashing exceeds its own 180 s limit with a debug build in this container. None of the three uses a plugin.

no test proof · iteration 0 · the description declares no behaviour change, so there is no failing test to prove; the existing suite in CI is the check

`JSBundlerPlugin__create` took a `BunPluginTarget` and stored it in
`BundlerPlugin::target`. No code reads that member. The `Bun.plugin`
helpers in BunPlugin.cpp took the same type as a parameter and did not
use it.

Drop the parameter from `JSBundlerPlugin__create`,
`JSBundlerPlugin::create`, both constructors, `PluginJscExt::create`
and the `Bun.plugin` helpers. Delete the four `target` members, the
Rust `BunPluginTarget` enum and the C++ `BunPluginTarget` typedef with
its constants.

Delete the host functions `jsFunctionAppendOnLoadPluginNode`,
`jsFunctionAppendOnLoadPluginBrowser`,
`jsFunctionAppendOnResolvePluginNode` and
`jsFunctionAppendOnResolvePluginBrowser`. They have no caller, and
without the parameter they are copies of the `Bun` pair.

`Bun.plugin` still validates the `target` string, and `Bun.build`
still reads its own `target` option.
@robobun

robobun commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 6:56 AM PT - Oct 21st, 2026

✅ @robobun, your commit 2706694f0ff780200e342bab0be132f433b1004f passed in Build #129995! 🎉


🧪   To try this PR locally:

bunx bun-pr 46089

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

bun-46089 --bun

@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.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

LGTM — mechanical removal of a value nothing reads; the Rust extern "C" declaration and the C++ JSBundlerPlugin__create definition still agree parameter-for-parameter, and no reference to BunPluginTarget or the four deleted host functions remains in the tree.

Extended reasoning...

The change deletes the unused BunPluginTarget type, four unread target members, the matching parameters on JSBundlerPlugin::create/constructors/JSBundlerPlugin__create and the Bun.plugin helper chain, and four uncalled host functions, then updates the three Rust call sites. It touches no security-sensitive surface: no user input handling changes, and the Bun.plugin({ target }) validation and error message are untouched. I confirmed the FFI signature on both sides matches, that bun_ast::Target remains used in JSBundler.rs so the import is live, and that no changed path is covered by CODEOWNERS. The one inline finding concerns a pre-existing SAFETY comment on the line below the edited call in server_body.rs, which this PR did not introduce, so it does not change the correctness of the removal itself.

Comment thread src/runtime/server/server_body.rs
@robobun

robobun commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: ready for review.

  • The change is a deletion of a value that no code reads. It has no test of its own, and the body carries Behaviour change: none.
  • How it was checked: bun bd, bun run rust:check-all (12 targets), and the 8 test files in the Notes, after the merge with main 71bc818.
  • Hardening: fix crashes across the runtime, bundler, dev server, shell and CLI #46021 is on main. The merge commit a81985a keeps its null prototype in JSBundlerPlugin__create and drops only the target argument.
  • Open pull requests: the branch was compared with the heads of 5,718 open pull requests at 2026-10-21 07:50 UTC. None reads the value. Six gain conflict hunks, and each of them already conflicts with main.

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: oven-sh/bun/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 86b34200-3df1-47dd-a095-13d1dc326862
📥 Commits

Reviewing files that changed from the base of the PR and between 71bc818 and 2706694.

📒 Files selected for processing: 9
  • src/jsc/bindings/BunPlugin.cpp
  • src/jsc/bindings/BunPlugin.h
  • src/jsc/bindings/JSBundlerPlugin.cpp
  • src/jsc/bindings/JSBundlerPlugin.h
  • src/jsc/bindings/headers-handwritten.h
  • src/opaque/lib.rs
  • src/runtime/api/JSBundler.rs
  • src/runtime/bake/config/bundler.rs
  • src/runtime/server/server_body.rs
💤 Files with no reviewable changes: 2
  • src/jsc/bindings/headers-handwritten.h
  • src/jsc/bindings/BunPlugin.h

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

Walkthrough

Plugin creation no longer passes a target through the plugin API. Bun registration uses Bun onLoad and onResolve handlers. Bundler and server call sites use the updated target-independent creation function.

Changes

Plugin creation

Layer / File(s) Summary
Remove target from plugin contracts
src/jsc/bindings/JSBundlerPlugin.h, src/jsc/bindings/JSBundlerPlugin.cpp, src/jsc/bindings/BunPlugin.h, src/jsc/bindings/headers-handwritten.h, src/runtime/api/JSBundler.rs, src/opaque/lib.rs
Removed BunPluginTarget state, declarations, and creation parameters. The FFI documentation example now uses Loader discriminants.
Use Bun registration handlers
src/jsc/bindings/BunPlugin.cpp
Removed target parameters from onLoad and onResolve registration. Bun host functions call the global helpers, and setupBunPlugin no longer accepts a target.
Update runtime plugin creation
src/runtime/api/JSBundler.rs, src/runtime/bake/config/bundler.rs, src/runtime/server/server_body.rs
Bundler and server plugin creation no longer passes a target.

Suggested reviewers: jarred-sumner, alii

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 27066

Plugin registration and dispatch remain target-independent, with no identified behavior change that needs correction before merge.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly identifies the primary change: removal of the unused BunPluginTarget value.
Description check Passed The description clearly explains the problem, fix, retained behavior, verification steps, test results, and known limitations. It does not use the exact template headings, but it provides the required…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description clearly explains the problem, fix, retained behavior, verification steps, test results, and known limitations. It does not use the exact template headings, but it provides the required information in equivalent sections.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

The comment said that `Plugin::create` returns a boxed pointer. It
returns a protected JSC cell. `heap::take` is sound there only because
`Plugin` is a zero-sized opaque type, so the `Box` owns no memory.

@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.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

LGTM — a mechanical dead-parameter removal, and the second commit's rewritten SAFETY comment in src/runtime/server/server_body.rs now matches what heap::take actually wraps (an opaque_ffi! zero-sized handle to a protected JSC cell).

Checked that JSBundlerPlugin__create has the same single-argument shape on the C++ extern "C" definition and the Rust unsafe extern "C" declaration, that no file in the repo still references BunPluginTarget or the deleted *Node/*Browser host functions, and that the only remaining target uses in BunPlugin.cpp are the kept string validation and the builder's "bun" property.

Extended reasoning...

The change removes an unread BunPluginTarget value end to end: the C++ typedef and constants in headers-handwritten.h, four target members, the parameter on JSBundlerPlugin::create/constructors/JSBundlerPlugin__create and the BunPlugin.cpp helpers, four never-registered host functions, and the Rust enum plus three call sites. It touches an FFI boundary but both sides of the signature were updated together and a repo-wide search finds no stale consumer; no security-sensitive surface is involved. The one inline finding is a pre-existing leak of the protected plugin cell that this PR neither introduces nor worsens, and the earlier inline comment about the inaccurate SAFETY text was addressed by commit 7e7ce61. No CODEOWNERS entry covers the changed files, and the diff is small (+26/-84) and behavior-preserving.

Comment thread src/runtime/server/server_body.rs
…ve-plugin-target-value

Conflict in `JSBundlerPlugin__create`: keep the null prototype from
main, and end the call without the `target` argument.

@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 — a mechanical dead-code removal, and the SAFETY-comment correction from the earlier inline thread is now in the branch.

What was reviewed:

  • JSBundlerPlugin__create diffed parameter-by-parameter across the Rust unsafe extern "C" declaration and the C++ definition (both now one argument); the post-merge conflict resolution in src/jsc/bindings/JSBundlerPlugin.cpp keeps the null prototype and ends the call with nullptr.
  • Repo-wide search for BunPluginTarget and the four deleted Node/Browser host functions returns nothing; setupBunPlugin still registers the Bun pair, and all three Rust callers (JSBundler.rs, bake/config/bundler.rs, server_body.rs) use the new one-argument Plugin::create.
  • The rewritten SAFETY comment in server_body.rs checked against opaque_ffi! (a repr(C) ZST) and heap::take (Box::from_raw) — accurate; the new Loader doc example in src/opaque/lib.rs matches the real discriminants in src/ast/loader.rs.
Extended reasoning...

The change deletes an unread plugin-target value across the C++/Rust FFI boundary: the BunPluginTarget typedef and enum, four target members, the parameter on JSBundlerPlugin__create and five Bun.plugin helpers, and four uncalled host functions, plus a corrected SAFETY comment in server_body.rs. It touches no security-sensitive surface; the only unsafe code affected is the heap::take on a zero-sized opaque JSC handle, whose comment is now accurate. The only commit since the prior review is a merge of origin/main whose single conflict resolution was verified. The change is small, purely subtractive, every removed symbol has zero remaining references, the FFI signature matches on both sides, no CODEOWNERS entry covers the changed files, and no third-party changes-requested review is visible, so a human look is not needed.

Still open from earlier reviews (1):

  • Unresolved: 1 minor or pre-existing.

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