-
-
Notifications
You must be signed in to change notification settings - Fork 714
feat: execute JS plugin in the Boa engine #7300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
WalkthroughAdds an optional JavaScript plugin system and runtime. Introduces crate Suggested labels
Suggested reviewers
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
CodSpeed Performance ReportMerging #7300 will not alter performanceComparing Summary
|
998ff69
to
cf64d70
Compare
cf64d70
to
5c524ff
Compare
58cf58c
to
461411d
Compare
9bc4a44
to
0466b70
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/preview.yml (1)
77-82
: Use the version job output for BIOME_VERSIONThe workflow’s
BIOME_VERSION
is currently set to${{ env.cli-version }}
, butenv.cli-version
isn’t defined anywhere in this file. You’ll need to pull in the generated version from theversion
job’s output instead. In both build steps, replace:env: # Strip all debug symbols from the resulting binaries RUSTFLAGS: "-C strip=symbols -C codegen-units=1" - BIOME_VERSION: ${{ env.cli-version }} + BIOME_VERSION: ${{ needs.version.outputs.version }}After that, run your preview binary with
--version
to ensure it reflects the value fromupdate-preview-version.mjs
.
🧹 Nitpick comments (29)
.github/workflows/main.yml (1)
95-95
: Also test the default feature set (optional).Running only
--features=js_plugin
means we no longer exercise the default build on main. Consider running both to catch regressions early.Minimal tweak:
- run: cargo test --workspace --features=js_plugin + run: | + cargo test --workspace + cargo test --workspace --features=js_pluginIf runtime is a concern, a small matrix over features is another tidy option.
.github/workflows/pull_request.yml (1)
88-88
: Exercise both default and js_plugin paths on PRs (optional).Same story here: only testing the feature build may hide default-config breakage. Suggest running both.
Quick win:
- run: cargo test --workspace --features=js_plugin + run: | + cargo test --workspace + cargo test --workspace --features=js_pluginBonus: you may want to include
packages/**
andplugins/**
inpaths:
so JS-only changes still trigger CI.crates/biome_js_runtime/Cargo.toml (2)
1-11
: Consider inheriting the crate version from the workspace.To keep versions consistent during releases, consider switching to workspace-inherited package metadata if the root defines
workspace.package
.Proposed change:
[package] @@ -name = "biome_js_runtime" +name = "biome_js_runtime" @@ -version = "0.0.1" +version.workspace = trueIf the workspace doesn’t yet define
workspace.package.version
, keep0.0.1
but ensure your release tooling bumps this crate in lockstep with the others.
1-11
: Decide whether this crate is publishable now.If
biome_js_runtime
isn’t meant to be published during the preview, addpublish = false
to avoid accidental publication; if it is, ignore this note.Example:
[package] @@ license.workspace = true name = "biome_js_runtime" repository.workspace = true -version = "0.0.1" +version = "0.0.1" +publish = falsepackages/@biomejs/plugin-api/LICENSE-APACHE (1)
189-201
: Year range nit: align copyright year.Optional: update the copyright year (currently 2023) to either the current year or a range (e.g., 2023–2025) for consistency across packages.
packages/@biomejs/plugin-api/index.d.ts (1)
1-3
: Tighten typings and document severity mapping.Two small improvements:
- Add JSDoc to clarify how severities map to Biome/LSP severities and how they’re handled at runtime.
- Consider a
const enum
or exported union object to help editors with completions; alternatively, keep the union but validate unknown values at runtime on the Rust side.Example (non-breaking):
-export type Severity = "fatal" | "error" | "warning" | "information" | "hint"; +/** + * Diagnostic severity recognised by Biome’s JS plugin runtime. + * Unknown values should be rejected at runtime. + */ +export type Severity = "fatal" | "error" | "warning" | "information" | "hint"; -export function addDiagnostic(severity: Severity, message: string): void; +/** + * Push a diagnostic from a JS plugin. + * @param severity Diagnostic severity. + * @param message Human-readable message to show to users. + */ +export function addDiagnostic(severity: Severity, message: string): void;Runtime action item: ensure
boa
-side implementation rejects/normalises unexpected severities and adds tests for each variant.packages/@biomejs/plugin-api/package.json (3)
1-11
: Include index.js in files (now or before publish).
exports.default
andmain
point to./index.js
, but it isn’t listed under"files"
. It’s fine while"private": true
, but will bite later if you flip this to publish. Safer to include it now."files": [ "README.md", "LICENSE-APACHE", "LICENSE-MIT", - "index.d.ts" + "index.d.ts", + "index.js" ],
12-19
: index.js throwing at import is deliberate — add a hint in package metadata.Because the runtime provides a virtual module,
index.js
throws when loaded outside Biome. Consider adding a short note in README to explain this to plugin authors.Happy to draft the README snippet explaining resolution via the Biome runtime vs Node.
30-32
: Peer dependency on @biomejs/biome — is it required?Given this package is types-only and the runtime injects the module, the peer dep on
@biomejs/biome
may not add value. If kept, please document the rationale; otherwise, consider removing to reduce noise for plugin authors later.crates/biome_plugin_loader/src/thread_local.rs (4)
28-33
: Minor: use a direct cast for pointer typeNot a bug, but we can avoid the const pointer and Some() verbosity. The API accepts a pointer; a simple cast keeps it tidy and avoids questions about mutability.
- let result = unsafe { win32::FlsSetValue(self.inner, Some(value as *const c_void)) }; + let result = unsafe { win32::FlsSetValue(self.inner, value as *const c_void) };
76-80
: Promote failure checks to hard errors on Unixpthread_setspecific can fail (EINVAL/ENOMEN). A debug_assert risks dropping failures in release. Prefer assert with a message to surface issues early.
- let result = unsafe { libc::pthread_setspecific(self.inner, value as *mut c_void) }; - - debug_assert_eq!(result, 0); + let result = unsafe { libc::pthread_setspecific(self.inner, value as *mut c_void) }; + assert_eq!(result, 0, "pthread_setspecific failed: {}", result);
124-140
: Intentional per-thread leak: document trade-offs and provide an escape hatchThe comment calls out that values aren’t dropped on thread exit, which implies a per-thread leak. That’s likely fine for long-lived worker threads, but can surprise test code and short-lived threads.
- Please expand the doc comment to state the leak explicitly and why it’s chosen.
- Consider exposing a cfg(test) only clear() to drop the current thread’s value safely.
Example (outside the shown range):
#[cfg(test)] impl<T> ThreadLocalCell<T> { /// Drops the current thread's value (tests only). pub fn clear(&self) { unsafe { let ptr = self.key.get(); if !ptr.is_null() { drop(Box::from_raw(ptr)); // drop RefCell<T> self.key.set(std::ptr::null_mut()); } } } }
101-107
: Make ThreadLocalCell Sync so it can be shared across threadsAnalyzer plugins are typically shared (Arc) across worker threads. The TLS key is process-wide and operations are thread-safe-by-design; marking Sync enables ergonomic sharing.
Add this (outside the shown range):
// Safe: all access is per-thread via TLS; no cross-thread aliasing of the inner RefCell<T>. unsafe impl<T> Sync for ThreadLocalCell<T> {}If you prefer belt-and-braces, gate it with T: 'static to mirror the no-destructor design.
crates/biome_plugin_loader/src/diagnostics.rs (2)
43-51
: Parity between Grit and JS compile diagnosticsGrit compile errors preserve the original error as source, whereas JS errors currently don’t (see below). Keeping behaviour consistent improves downstream reporting.
If biome_diagnostics::Error can’t wrap boa_engine::JsError directly, consider storing a stringified version as a source via a lightweight error wrapper type, or attach it as advice.
54-64
: Preserve underlying Boa error for richer reportingMessage is helpful, but we lose stack/location by dropping the source. Either wrap the js error as a source or add advice (e.g. LogAdvice) with value.to_string().
For example:
#[cfg(feature = "js_plugin")] impl From<boa_engine::JsError> for PluginDiagnostic { fn from(value: boa_engine::JsError) -> Self { Self::Compile(CompileDiagnostic { message: MessageAndDescription::from( markup! {"Failed to compile the JS plugin: "{value.to_string()}}.to_owned(), ), - source: None, + // If Error::from(value) isn’t available, consider wrapping value.to_string() + // into a structured error wrapper or attach it as advice instead. + source: None, }) } }Happy to draft a tiny wrapper error if you’d like.
biome.json (1)
27-27
: Including plugins/*.js is sensible; watch for noUndeclaredDependenciesWith this file now linted, imports like "@biomejs/plugin-api" inside plugins/*.js may trigger correctness/noUndeclaredDependencies since plugins/ isn’t a package. Two options:
- Add an override to disable that rule for plugins/*.js, or
- Add a minimal package.json in plugins/ declaring @biomejs/plugin-api as a devDependency.
Example override (outside the shown range):
{ "overrides": [ { "include": ["plugins/*.js"], "linter": { "rules": { "correctness": { "noUndeclaredDependencies": "off" } } } } ] }plugins/plugin.js (1)
3-8
: Tighten sample logic and avoid name shadowing.Minor polish: use early-return to reduce nesting and rename the parameter to
filePath
to avoid confusion with Node’spath
module.Apply:
-/** @param {string} path */ -export default function useMyPlugin(path) { - if (path.endsWith("plugin.js")) { - addDiagnostic("warning", "Hello, world!"); - } -} +/** @param {string} filePath */ +export default function useMyPlugin(filePath) { + if (!filePath.endsWith("plugin.js")) return; + addDiagnostic("warning", "Hello, world!"); +}crates/biome_js_runtime/src/lib.rs (1)
1-6
: Public re-exports look tidy.Clear surface area via
pub use
with private modules. Consider a short crate-level doc to explain the Boa-based runtime and how modules are loaded; future-you will thank you.crates/biome_service/src/workspace/server.rs (1)
491-496
: Arc handoff looks correct; tiny style nitPassing
self.fs.clone()
to the newBiomePlugin::load(Arc<dyn FsWithResolverProxy>, …)
is spot on. If you want to make the intent extra explicit, considerArc::clone(&self.fs)
(purely stylistic).crates/biome_js_runtime/src/plugin_api.rs (1)
40-47
: Consider including a stable category and optional code for plugin diagnosticsRight now every diagnostic is
category!("plugin")
. That’s fine for a POC, but you may wantcategory!("plugin/{name}")
or a rule code (e.g.with_category
/with_code
) so users can target-suppress per-plugin in future.Would you like me to sketch a minimal plugin “name” plumbed from the loader to prefix the category?
crates/biome_js_runtime/src/module_loader.rs (2)
56-60
: Enhance diagnostics by naming the module inModule::parse
If
Module::parse
accepts an optional identifier/source name, pass the specifier (or resolved path) so stack traces and error messages show the module name.
40-47
: Base dir fallback
unwrap_or_default()
gives an empty path; resolution libraries sometimes treat that oddly. Consider defaulting to the process working directory or/
explicitly ifworking_directory()
isNone
.crates/biome_plugin_loader/src/lib.rs (2)
62-75
: JS plugin detection: consider.mts
(and explicitly not.cjs
)You accept
.js
/.mjs
. If you anticipate TS-in-JS plugin transpilation or ESM variants, you might add.mts
later. Deliberately skipping.cjs
makes sense given ESM-only loader.Do we want to document the accepted extensions now to avoid plugin author confusion?
97-115
: Manifest rule extension checkUsing
ends_with(b".grit")
works but is a tad brittle.rule.extension() == Some("grit")
reads clearer and is platform-neutral.Apply this small refactor?
- .map(|rule| { - if rule.as_os_str().as_encoded_bytes().ends_with(b".grit") { + .map(|rule| { + if rule.extension().is_some_and(|ext| ext == "grit") {crates/biome_plugin_loader/src/analyzer_js_plugin.rs (2)
27-39
:load_plugin
ergonomicsLGTM for the core flow (context → import → default export check). Optional: attach the plugin path/specifier to the
TypeError
message for better UX.
72-108
: Good per-thread isolation; consider passing the AST soonThread-local context + function entrypoint is a sensible MVP. There’s already a TODO to pass the AST; doing so early will help stabilise the JS API shape.
crates/biome_js_runtime/src/context.rs (3)
1-8
: Drop unused import and minor nitpick on Rc cloning
- The
ModuleLoader
import (Line 5) isn’t used in this file; this will tripclippy -D warnings
in CI.- Style:
Rc::clone(&module_loader)
(Line 27) can bemodule_loader.clone()
.Apply:
- use boa_engine::module::ModuleLoader;
Optional style tweak:
- .module_loader(Rc::clone(&module_loader)) + .module_loader(module_loader.clone())
91-96
: Default export type is unchecked; consider a function-specific accessorDownstream code likely expects the default export to be callable. Returning a raw
JsValue
pushes type errors later and makes crashes more mysterious.Option A (add a helper, keep current API):
// Add alongside get_default_export pub fn get_default_export_function(&mut self, module: &Module) -> JsResult<JsFunction> { let value = self.get_default_export(module)?; let ctx = &mut self.inner; let obj = value.as_object().ok_or_else(|| { JsNativeError::typ() .with_message("Default export is not an object/function") .into() })?; if let Some(func) = obj.as_function() { Ok(func.clone()) } else { Err(JsNativeError::typ().with_message("Default export is not a function").into()) } }If Boa’s API differs, adjust to the available “is callable/as function” helpers.
98-105
: Call surface is fine; optional ergonomicsPassing an explicit
this
is flexible, but most plugin functions won’t need it. A conveniencecall_function_undefined_this
(or defaultingthis
internally) can reduce boilerplate for callers.Example:
pub fn call_function_undefined_this( &mut self, function: &JsFunction, args: &[JsValue], ) -> JsResult<JsValue> { function.call(&JsValue::undefined(), args, &mut self.inner) }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (3)
Cargo.lock
is excluded by!**/*.lock
and included by**
crates/biome_plugin_loader/src/snapshots/evaluate_in_worker_threads.snap
is excluded by!**/*.snap
and included by**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
and included by**
📒 Files selected for processing (26)
.github/workflows/main.yml
(1 hunks).github/workflows/preview.yml
(2 hunks).github/workflows/pull_request.yml
(1 hunks)Cargo.toml
(4 hunks)biome.json
(1 hunks)crates/biome_cli/Cargo.toml
(1 hunks)crates/biome_js_analyze/Cargo.toml
(1 hunks)crates/biome_js_runtime/Cargo.toml
(1 hunks)crates/biome_js_runtime/src/context.rs
(1 hunks)crates/biome_js_runtime/src/lib.rs
(1 hunks)crates/biome_js_runtime/src/module_loader.rs
(1 hunks)crates/biome_js_runtime/src/plugin_api.rs
(1 hunks)crates/biome_plugin_loader/Cargo.toml
(1 hunks)crates/biome_plugin_loader/src/analyzer_js_plugin.rs
(1 hunks)crates/biome_plugin_loader/src/diagnostics.rs
(3 hunks)crates/biome_plugin_loader/src/lib.rs
(11 hunks)crates/biome_plugin_loader/src/thread_local.rs
(1 hunks)crates/biome_service/Cargo.toml
(1 hunks)crates/biome_service/src/workspace/server.rs
(1 hunks)package.json
(1 hunks)packages/@biomejs/plugin-api/LICENSE-APACHE
(1 hunks)packages/@biomejs/plugin-api/LICENSE-MIT
(1 hunks)packages/@biomejs/plugin-api/index.d.ts
(1 hunks)packages/@biomejs/plugin-api/index.js
(1 hunks)packages/@biomejs/plugin-api/package.json
(1 hunks)plugins/plugin.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{rs,toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Format Rust and TOML files before committing (use
just f
/just format
).
Files:
crates/biome_js_analyze/Cargo.toml
crates/biome_js_runtime/Cargo.toml
crates/biome_service/Cargo.toml
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
crates/biome_js_runtime/src/plugin_api.rs
crates/biome_plugin_loader/Cargo.toml
crates/biome_cli/Cargo.toml
Cargo.toml
crates/biome_js_runtime/src/module_loader.rs
crates/biome_js_runtime/src/lib.rs
crates/biome_plugin_loader/src/thread_local.rs
crates/biome_service/src/workspace/server.rs
crates/biome_js_runtime/src/context.rs
crates/biome_plugin_loader/src/lib.rs
crates/biome_plugin_loader/src/diagnostics.rs
crates/**/Cargo.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
crates/**/Cargo.toml
: In internal crates, useworkspace = true
for internal dependencies.
Use path dependencies for dev-dependencies in internal crates.
Files:
crates/biome_js_analyze/Cargo.toml
crates/biome_js_runtime/Cargo.toml
crates/biome_service/Cargo.toml
crates/biome_plugin_loader/Cargo.toml
crates/biome_cli/Cargo.toml
{Cargo.toml,crates/**/Cargo.toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep the version field consistent across all crates during release.
Files:
crates/biome_js_analyze/Cargo.toml
crates/biome_js_runtime/Cargo.toml
crates/biome_service/Cargo.toml
crates/biome_plugin_loader/Cargo.toml
crates/biome_cli/Cargo.toml
Cargo.toml
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Files:
crates/biome_js_analyze/Cargo.toml
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_js_analyze/Cargo.toml
crates/biome_js_runtime/Cargo.toml
crates/biome_service/Cargo.toml
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
crates/biome_js_runtime/src/plugin_api.rs
crates/biome_plugin_loader/Cargo.toml
crates/biome_cli/Cargo.toml
crates/biome_js_runtime/src/module_loader.rs
crates/biome_js_runtime/src/lib.rs
crates/biome_plugin_loader/src/thread_local.rs
crates/biome_service/src/workspace/server.rs
crates/biome_js_runtime/src/context.rs
crates/biome_plugin_loader/src/lib.rs
crates/biome_plugin_loader/src/diagnostics.rs
Cargo.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Centralize shared dependencies in the root Cargo.toml using workspace dependencies.
Files:
Cargo.toml
crates/biome_service/src/workspace/server.rs
📄 CodeRabbit inference engine (crates/biome_service/CONTRIBUTING.md)
Use WorkspaceServer (src/workspace/server.rs) to maintain workspace state in daemon and CLI daemonless modes
Files:
crates/biome_service/src/workspace/server.rs
🧠 Learnings (32)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Add biome_js_formatter as a path dependency in Cargo.toml: biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }
📚 Learning: 2025-08-11T11:48:52.001Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Add biome_js_formatter as a path dependency in Cargo.toml: biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }
Applied to files:
crates/biome_js_analyze/Cargo.toml
crates/biome_js_runtime/Cargo.toml
crates/biome_service/Cargo.toml
crates/biome_plugin_loader/Cargo.toml
crates/biome_cli/Cargo.toml
Cargo.toml
crates/biome_plugin_loader/src/lib.rs
crates/biome_plugin_loader/src/diagnostics.rs
📚 Learning: 2025-08-11T11:48:27.774Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:27.774Z
Learning: Applies to crates/biome_formatter/biome_html_formatter/Cargo.toml : Add the specified dev-dependencies (biome_formatter_test, biome_html_factory, biome_html_parser, biome_parser, biome_service, countme with feature enable, iai 0.1.1, quickcheck, quickcheck_macros, tests_macros) to Cargo.toml under [dev-dependencies]
Applied to files:
crates/biome_js_analyze/Cargo.toml
crates/biome_js_runtime/Cargo.toml
crates/biome_service/Cargo.toml
crates/biome_plugin_loader/Cargo.toml
crates/biome_cli/Cargo.toml
Cargo.toml
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Specify category and severity using #[diagnostic(...)] on the type or derive them from fields
Applied to files:
packages/@biomejs/plugin-api/index.d.ts
crates/biome_plugin_loader/src/lib.rs
crates/biome_plugin_loader/src/diagnostics.rs
📚 Learning: 2025-08-17T08:55:30.118Z
Learnt from: CR
PR: biomejs/biome#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-17T08:55:30.118Z
Learning: Applies to crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/** : Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Applied to files:
crates/biome_js_runtime/Cargo.toml
crates/biome_plugin_loader/Cargo.toml
Cargo.toml
📚 Learning: 2025-08-11T11:40:38.097Z
Learnt from: CR
PR: biomejs/biome#0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:40:38.097Z
Learning: Applies to crates/**/Cargo.toml : In internal crates, use `workspace = true` for internal dependencies.
Applied to files:
crates/biome_js_runtime/Cargo.toml
crates/biome_plugin_loader/Cargo.toml
Cargo.toml
📚 Learning: 2025-08-11T11:53:15.299Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:53:15.299Z
Learning: Applies to crates/biome_service/src/workspace.rs : Implement the Workspace trait in src/workspace.rs
Applied to files:
crates/biome_js_runtime/Cargo.toml
crates/biome_plugin_loader/Cargo.toml
Cargo.toml
crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-08-17T08:57:34.751Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:57:34.751Z
Learning: Applies to crates/biome_parser/crates/biome_*_syntax/** : Create a new crate named biome_<language>_syntax under crates/
Applied to files:
crates/biome_js_runtime/Cargo.toml
Cargo.toml
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/lib/src/lint/nursery/*.rs : For new JavaScript lint rules generated by `just new-js-lintrule`, implement the rule in the generated file under `biome_js_analyze/lib/src/lint/nursery/`
Applied to files:
crates/biome_js_runtime/Cargo.toml
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
crates/biome_js_runtime/src/plugin_api.rs
crates/biome_cli/Cargo.toml
crates/biome_plugin_loader/src/lib.rs
📚 Learning: 2025-08-11T11:40:38.097Z
Learnt from: CR
PR: biomejs/biome#0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:40:38.097Z
Learning: Applies to Cargo.toml : Centralize shared dependencies in the root Cargo.toml using workspace dependencies.
Applied to files:
crates/biome_js_runtime/Cargo.toml
crates/biome_plugin_loader/Cargo.toml
Cargo.toml
📚 Learning: 2025-08-17T08:57:34.751Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:57:34.751Z
Learning: Applies to crates/biome_parser/crates/biome_*_factory/** : Create a new crate named biome_<language>_factory under crates/
Applied to files:
crates/biome_js_runtime/Cargo.toml
Cargo.toml
📚 Learning: 2025-08-11T11:53:15.299Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:53:15.299Z
Learning: Applies to crates/biome_service/../biome_lsp/src/server.tests.rs : Keep end-to-end LSP tests in biome_lsp’s server.tests.rs
Applied to files:
crates/biome_js_runtime/Cargo.toml
Cargo.toml
crates/biome_plugin_loader/src/lib.rs
📚 Learning: 2025-08-05T14:43:29.581Z
Learnt from: dyc3
PR: biomejs/biome#7081
File: packages/@biomejs/biome/configuration_schema.json:7765-7781
Timestamp: 2025-08-05T14:43:29.581Z
Learning: The file `packages/biomejs/biome/configuration_schema.json` is auto-generated and should not be manually edited or reviewed for schema issues; any changes should be made at the code generation source.
Applied to files:
biome.json
packages/@biomejs/plugin-api/package.json
packages/@biomejs/plugin-api/index.js
📚 Learning: 2025-08-11T11:53:15.299Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:53:15.299Z
Learning: For debugging: run commands against the daemon (e.g., `cargo run --bin=biome -- lint --use-server <path>`)
Applied to files:
.github/workflows/preview.yml
📚 Learning: 2025-08-11T11:40:38.097Z
Learnt from: CR
PR: biomejs/biome#0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:40:38.097Z
Learning: Applies to crates/**/Cargo.toml : Use path dependencies for dev-dependencies in internal crates.
Applied to files:
crates/biome_plugin_loader/Cargo.toml
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Define per-rule options in the `biome_rule_options` crate under `lib/`, with serde- and schemars-compatible derives and `#[serde(rename_all = "camelCase", deny_unknown_fields, default)]`
Applied to files:
crates/biome_plugin_loader/Cargo.toml
📚 Learning: 2025-08-11T11:48:52.001Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Build an intermediate IR via the provided helper APIs when formatting
Applied to files:
Cargo.toml
crates/biome_plugin_loader/src/diagnostics.rs
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/src/**/*.rs : Represent links between types using TypeReference (not Arc) to avoid cross-module retention and recursive structures; store type data in linear vectors
Applied to files:
Cargo.toml
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/{src,resolver,biome_module_graph/src}/**/*.rs : Implement and use type resolution via the TypeResolver trait; resolvers own TypeStore vectors and provide fast by-id and hashed lookups
Applied to files:
Cargo.toml
crates/biome_js_runtime/src/module_loader.rs
📚 Learning: 2025-08-11T11:48:27.774Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:27.774Z
Learning: Applies to crates/biome_formatter/biome_html_formatter/src/lib.rs : Place the plumbing traits and impls (AsFormat, IntoFormat, FormattedIterExt, and their Iterator adapters) in the biome_html_formatter crate’s lib.rs
Applied to files:
Cargo.toml
crates/biome_plugin_loader/src/diagnostics.rs
📚 Learning: 2025-08-11T11:53:15.299Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:53:15.299Z
Learning: Applies to crates/biome_service/src/workspace/server.rs : Use WorkspaceServer (src/workspace/server.rs) to maintain workspace state in daemon and CLI daemonless modes
Applied to files:
crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-08-11T11:53:15.299Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:53:15.299Z
Learning: Applies to crates/biome_service/src/workspace/client.rs : Use WorkspaceClient (src/workspace/client.rs) to connect to the daemon and communicate with WorkspaceServer
Applied to files:
crates/biome_service/src/workspace/server.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Types implementing Diagnostic must also implement Debug (e.g., use #[derive(Debug, Diagnostic)])
Applied to files:
crates/biome_plugin_loader/src/lib.rs
crates/biome_plugin_loader/src/diagnostics.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/tests/quick_test.rs : Use `biome_js_analyze/tests/quick_test.rs` for quick, ad-hoc testing; un-ignore the test and adjust the rule filter as needed
Applied to files:
crates/biome_plugin_loader/src/lib.rs
📚 Learning: 2025-08-11T11:48:27.774Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:27.774Z
Learning: Applies to crates/biome_formatter/biome_html_formatter/tests/spec_test.rs : Create tests/spec_test.rs implementing the run(spec_input_file, _expected_file, test_directory, _file_type) function as shown and include!("language.rs")
Applied to files:
crates/biome_plugin_loader/src/lib.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Use helper advice types from biome_diagnostics::v2 (CodeFrameAdvice, CommandAdvice, DiffAdvice, LogAdvice) when suitable
Applied to files:
crates/biome_plugin_loader/src/lib.rs
crates/biome_plugin_loader/src/diagnostics.rs
📚 Learning: 2025-08-11T11:48:27.774Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:27.774Z
Learning: Applies to crates/biome_formatter/biome_html_formatter/tests/spec_tests.rs : Create tests/spec_tests.rs in the biome_html_formatter crate that generates tests via tests_macros::gen_tests! for all HTML files at tests/specs/html/**/*.html
Applied to files:
crates/biome_plugin_loader/src/lib.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : #[derive(Diagnostic)] can be used on enums only if every variant contains a diagnostic type
Applied to files:
crates/biome_plugin_loader/src/lib.rs
📚 Learning: 2025-08-17T08:55:30.118Z
Learnt from: CR
PR: biomejs/biome#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-17T08:55:30.118Z
Learning: Applies to **/tests/specs/**/*.snap : Use snapshot spec tests stored as .snap files under tests/specs/ (via cargo insta)
Applied to files:
crates/biome_plugin_loader/src/lib.rs
📚 Learning: 2025-08-11T11:48:52.001Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Use dbg_write! to debug and inspect the written IR elements during formatter development
Applied to files:
crates/biome_plugin_loader/src/diagnostics.rs
📚 Learning: 2025-08-11T11:48:52.001Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Use the generic Format trait and FormatNode for AST nodes when implementing the formatter
Applied to files:
crates/biome_plugin_loader/src/diagnostics.rs
📚 Learning: 2025-08-11T11:48:52.001Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import the FormatNode trait and implement it for your Node
Applied to files:
crates/biome_plugin_loader/src/diagnostics.rs
🧬 Code graph analysis (7)
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (5)
crates/biome_plugin_loader/src/lib.rs (2)
load_plugin
(141-157)load
(40-118)crates/biome_plugin_loader/src/thread_local.rs (3)
new
(15-22)new
(56-70)new
(102-106)crates/biome_js_runtime/src/plugin_api.rs (2)
new
(17-21)None
(42-42)crates/biome_js_runtime/src/context.rs (1)
new
(23-36)crates/biome_js_runtime/src/module_loader.rs (1)
new
(17-22)
crates/biome_js_runtime/src/plugin_api.rs (2)
packages/@biomejs/plugin-api/index.d.ts (1)
Severity
(1-1)crates/biome_js_runtime/src/context.rs (2)
new
(23-36)pull_diagnostics
(39-41)
crates/biome_js_runtime/src/module_loader.rs (1)
crates/biome_js_runtime/src/context.rs (1)
new
(23-36)
crates/biome_service/src/workspace/server.rs (2)
crates/biome_plugin_loader/src/lib.rs (1)
load
(40-118)crates/biome_plugin_loader/src/analyzer_js_plugin.rs (1)
load
(57-69)
crates/biome_js_runtime/src/context.rs (2)
crates/biome_js_runtime/src/plugin_api.rs (3)
new
(17-21)pull_diagnostics
(73-75)None
(42-42)crates/biome_js_runtime/src/module_loader.rs (1)
new
(17-22)
crates/biome_plugin_loader/src/lib.rs (6)
crates/biome_fs/src/utils.rs (1)
normalize_path
(43-72)crates/biome_service/src/workspace/server.rs (3)
fs
(1590-1592)fs
(1672-1674)new
(119-141)crates/biome_plugin_loader/src/analyzer_js_plugin.rs (1)
load
(57-69)crates/biome_js_runtime/src/context.rs (1)
new
(23-36)crates/biome_js_runtime/src/module_loader.rs (1)
new
(17-22)crates/biome_fs/src/fs/memory.rs (1)
default
(37-49)
crates/biome_plugin_loader/src/diagnostics.rs (1)
crates/biome_service/src/diagnostics.rs (8)
fmt
(172-174)fmt
(178-180)fmt
(538-540)message
(357-364)message
(403-419)message
(499-501)message
(563-572)message
(642-650)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
- GitHub Check: End-to-end tests
- GitHub Check: Lint project (depot-windows-2022)
- GitHub Check: Check Dependencies
- GitHub Check: Documentation
- GitHub Check: Test Node.js API
- GitHub Check: Check JS Files
- GitHub Check: autofix
- GitHub Check: Bench (biome_package)
- GitHub Check: Bench (biome_configuration)
- GitHub Check: Bench (biome_html_parser)
- GitHub Check: Bench (biome_module_graph)
- GitHub Check: Bench (biome_html_formatter)
- GitHub Check: Bench (biome_graphql_formatter)
- GitHub Check: Bench (biome_graphql_parser)
- GitHub Check: Bench (biome_css_formatter)
- GitHub Check: Bench (biome_json_analyze)
- GitHub Check: Bench (biome_css_analyze)
- GitHub Check: Bench (biome_js_formatter)
- GitHub Check: Bench (biome_json_formatter)
- GitHub Check: Bench (biome_js_parser)
- GitHub Check: Bench (biome_json_parser)
- GitHub Check: Bench (biome_js_analyze)
- GitHub Check: Bench (biome_css_parser)
🔇 Additional comments (25)
crates/biome_js_analyze/Cargo.toml (2)
43-43
: Patch bump to roaring looks good.0.11.2 is a safe patch upgrade; no objections from me.
43-43
: All roaring dependencies aligned at 0.11.2
Scanned everyCargo.toml
and the lockfile only listsroaring v0.11.2
—no mismatches or duplicates. Lockfile refresh isn’t needed.packages/@biomejs/plugin-api/LICENSE-MIT (2)
1-22
: MIT licence file added — spot on.Standard text, correct attribution. Thanks for keeping the legal ducks in a row.
1-22
: Ensure npm metadata matches the chosen licence(s).If this package is dual-licensed (MIT/Apache-2.0 like the rest of the repo), please confirm
packages/@biomejs/plugin-api/package.json
haslicense: "MIT OR Apache-2.0"
(or just"MIT"
if that’s the intent).packages/@biomejs/plugin-api/index.js (2)
1-3
: Guardrail import that throws — sensible defensive move.Clear signal if someone tries to use this outside the Biome runtime. No objections.
1-3
: ✅ Verification complete: loader intercepts and bridged module provided
- In
crates/biome_js_runtime/src/context.rs
the loader registers"@biomejs/plugin-api"
viamodule_loader.register_module
(lines 29–33).- In
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
the plugin imports from"@biomejs/plugin-api"
, confirming the runtime wiring (lines 147–151).- The suggested package
@biomejs/js-api
exists underpackages/@biomejs/js-api
with a validpackage.json
.No changes required—this throw will never fire. Carry on!
.github/workflows/preview.yml (1)
76-76
: Enabling js_plugin in preview builds looks good.Nice and surgical: only the CLI is built with
--features=js_plugin
and only in preview. That keeps the feature well-gated while you iterate.Also applies to: 132-132
crates/biome_js_runtime/Cargo.toml (1)
13-21
: Workspace deps are correctly referenced.All internal crates use
workspace = true
. Third-party crates are also pulled from the workspace, aligning with the repo’s centralised dependency policy. Ship it.packages/@biomejs/plugin-api/LICENSE-APACHE (1)
1-3
: License file included — all good.Standard Apache-2.0 text present. Cheers for dual-licensing hygiene.
crates/biome_plugin_loader/src/diagnostics.rs (1)
142-155
: Nice: switch to MessageAndDescriptionGood move. This unifies message and description handling and plays nicely with the console formatter and snapshots.
crates/biome_service/Cargo.toml (1)
83-84
: Feature wiring looks goodTransitive enablement of biome_plugin_loader/js_plugin from biome_service is clean and keeps the path opt-in. No further changes needed here.
crates/biome_cli/Cargo.toml (1)
92-94
: CLI feature exposure is tidyExposing js_plugin at the CLI level via biome_service/js_plugin is exactly what we need. It remains non-default, which fits the “preview” gating.
package.json (1)
21-21
: All green for @biomejs/plugin-api
Both index.js and index.d.ts were found under packages/@biomejs/plugin-api. Ready to ship!crates/biome_plugin_loader/Cargo.toml (3)
33-35
: Optional, workspace-managed deps for the JS runtime are spot on.Using
workspace = true
withoptional = true
keeps compile costs down unlessjs_plugin
is enabled. Nice.
43-44
: Dev-deps wired to the workspace.
biome_js_parser
andinsta
via workspace are consistent with our guidelines.
36-41
: Seems our sandbox can’t cross-compile (no /proc), so the checks didn’t run. Could you please verify locally that:cargo check -p biome_plugin_loader --no-default-features --features js_plugin --target x86_64-unknown-linux-gnu cargo check -p biome_plugin_loader --no-default-features --features js_plugin --target aarch64-apple-darwin cargo check -p biome_plugin_loader --no-default-features --features js_plugin --target x86_64-pc-windows-msvcall pass cleanly?
Cargo.toml (1)
139-139
: Dependency feature graph & cross-target checks need your local runThe sandbox couldn’t execute
cargo tree
orcargo check
(no/proc/self/exe
), so please run these on your machine and share the outputs to confirm the JS runtime graph and versions:• Generate the feature graph for
js_plugin
:cargo tree -p biome_plugin_loader --features js_plugin -e features \ | rg -n 'boa_engine|windows|libc|biome_js_runtime'• Cross-target build verification:
for target in x86_64-unknown-linux-gnu aarch64-apple-darwin x86_64-pc-windows-msvc; do echo "==> Checking target: $target" cargo check --workspace --no-default-features \ --features biome_plugin_loader/js_plugin --target "$target" doneLet me know the results so we can sign off on the pinned versions and workspace setup.
crates/biome_js_runtime/src/plugin_api.rs (1)
73-75
: LGTM: cheap drain withmem::take
Returning and clearing the collected diagnostics atomically is perfect here.
crates/biome_plugin_loader/src/lib.rs (3)
8-15
: Feature-gated JS plugin plumbing looks tidyClean separation under
#[cfg(feature = "js_plugin")]
and re-export is good.
41-46
: API change toArc<dyn FsWithResolverProxy>
is applied correctlySwitching from
&dyn
toArc<dyn …>
here aligns with downstream runtime needs. Nice.
153-156
: Tests updated forArc<dyn FsWithResolverProxy>
look correctThe memory FS wrapping and new loads pass muster. The JS single-rule test is a nice sanity check.
Also applies to: 165-166, 181-183, 198-200, 209-213, 215-229
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (1)
119-195
: Concurrency smoke test is solidNice coverage across two threads; snapshots make regressions obvious.
crates/biome_js_runtime/src/context.rs (3)
16-20
: Nice encapsulation of runtime state
JsExecContext
cleanly bundles the BoaContext
, FS proxy and plugin API; good separation of concerns.
22-36
: Constructor looks solid; module pre-registration is neatInitialising the loader, building the context and pre-registering
@biomejs/plugin-api
up-front is a good call. Keeps plugin code simple.
38-41
: Diagnostic drain is tidyForwarding to
JsPluginApi::pull_diagnostics
is exactly what we want here.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (1)
crates/biome_plugin_loader/src/thread_local.rs (1)
15-24
: Make Key::new() fallible (don’t panic on FlsAlloc failure).FlsAlloc may return FLS_OUT_OF_INDEXES (u32::MAX). Panicking in release is unfriendly; return an io::Result and propagate instead. Mirrors the same concern on Unix (see below).
- impl<T> Key<T> { - pub(super) unsafe fn new() -> Self { - let inner = unsafe { win32::FlsAlloc(None) }; - // FlsAlloc returns FLS_OUT_OF_INDEXES (u32::MAX) on failure. - assert!(inner != u32::MAX, "FlsAlloc failed: out of FLS indexes"); - - Self { - inner, - _phantom: PhantomData, - } - } + impl<T> Key<T> { + pub(super) unsafe fn new() -> std::io::Result<Self> { + let inner = win32::FlsAlloc(None); + // FlsAlloc returns FLS_OUT_OF_INDEXES (u32::MAX) on failure. + if inner == u32::MAX { + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "FlsAlloc failed: out of FLS indexes", + )); + } + Ok(Self { inner, _phantom: PhantomData }) + }
🧹 Nitpick comments (2)
crates/biome_plugin_loader/src/thread_local.rs (2)
93-101
: Consider installing TLS destructors to prevent per-thread leaks.You’re intentionally leaking the per-thread Box to dodge drop-order hazards. If that becomes an issue under high churn threads, add a destructor (FlsAlloc callback / pthread_key_create dtor) that only frees the Box, or provide a clear_current_thread() for deterministic cleanup.
Would you like me to open a follow-up to prototype a safe destructor that avoids the double-free scenario you’ve seen?
125-134
: Minor: document safety invariants around raw pointer use.A brief SAFETY: comment stating why casting from TLS pointer and borrowing is sound (one Box per thread, never freed, RefCell borrow discipline) will help future maintainers.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
crates/biome_plugin_loader/src/thread_local.rs
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rs,toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Format Rust and TOML files before committing (use
just f
/just format
).
Files:
crates/biome_plugin_loader/src/thread_local.rs
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_plugin_loader/src/thread_local.rs
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Add biome_js_formatter as a path dependency in Cargo.toml: biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
- GitHub Check: Test Node.js API
- GitHub Check: autofix
- GitHub Check: Check JS Files
- GitHub Check: Bench (biome_css_analyze)
- GitHub Check: Bench (biome_package)
- GitHub Check: Bench (biome_html_parser)
- GitHub Check: Bench (biome_configuration)
- GitHub Check: Bench (biome_html_formatter)
- GitHub Check: Bench (biome_module_graph)
- GitHub Check: Bench (biome_js_analyze)
- GitHub Check: Bench (biome_json_analyze)
- GitHub Check: Bench (biome_graphql_formatter)
- GitHub Check: Bench (biome_graphql_parser)
- GitHub Check: Bench (biome_json_parser)
- GitHub Check: Bench (biome_js_parser)
- GitHub Check: Bench (biome_js_formatter)
- GitHub Check: Bench (biome_css_formatter)
- GitHub Check: Bench (biome_css_parser)
- GitHub Check: Bench (biome_json_formatter)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it!
Left a few comments, and CodeRabbit also pointed out some unwraps that I think would be good to address before merging, but I like where this is going!
Co-authored-by: Arend van Beelen jr. <arend@arendjr.nl>
df63ea0
to
317f1a9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (3)
27-39
: Consider adding timeout protection for plugin loading.Since JS plugins can potentially hang during module loading (infinite loops, blocking operations), you might want to add a timeout mechanism to prevent the loader from hanging indefinitely.
Would you like me to suggest an implementation using a timeout wrapper around the load operation?
73-108
: Consider adding resource limits for plugin execution.JS plugins could potentially consume excessive memory or CPU. Consider implementing resource limits (memory usage, execution time) to protect against misbehaving plugins.
You might want to explore Boa's built-in limits API or wrap the execution in a timeout to prevent runaway plugins from affecting the host application's performance.
90-90
: Track the AST passing TODO.The TODO indicates AST needs to be passed to the plugin. This is a core feature for plugins to analyse code structure.
Would you like me to create an issue to track implementing the AST serialisation and passing mechanism to JS plugins?
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
Cargo.lock
is excluded by!**/*.lock
and included by**
📒 Files selected for processing (8)
crates/biome_js_runtime/src/context.rs
(1 hunks)crates/biome_js_runtime/src/module_loader.rs
(1 hunks)crates/biome_js_runtime/src/plugin_api.rs
(1 hunks)crates/biome_plugin_loader/Cargo.toml
(1 hunks)crates/biome_plugin_loader/src/analyzer_js_plugin.rs
(1 hunks)crates/biome_plugin_loader/src/thread_local.rs
(1 hunks)packages/@biomejs/plugin-api/index.d.ts
(1 hunks)plugins/plugin.js
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- packages/@biomejs/plugin-api/index.d.ts
- crates/biome_plugin_loader/Cargo.toml
- crates/biome_js_runtime/src/plugin_api.rs
- plugins/plugin.js
- crates/biome_js_runtime/src/module_loader.rs
- crates/biome_plugin_loader/src/thread_local.rs
- crates/biome_js_runtime/src/context.rs
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rs,toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Format Rust and TOML files before committing (use
just f
/just format
).
Files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Add biome_js_formatter as a path dependency in Cargo.toml: biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/lib/src/lint/nursery/*.rs : For new JavaScript lint rules generated by `just new-js-lintrule`, implement the rule in the generated file under `biome_js_analyze/lib/src/lint/nursery/`
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Use helper advice types from biome_diagnostics::v2 (CodeFrameAdvice, CommandAdvice, DiffAdvice, LogAdvice) when suitable
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/**/lib/src/**/nursery/**/*.rs : Use the local `rule_category!()` macro in diagnostics for the rule’s category, not string-parsed categories
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/tests/quick_test.rs : Use `biome_js_analyze/tests/quick_test.rs` for quick, ad-hoc testing; un-ignore the test and adjust the rule filter as needed
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Define per-rule options in the `biome_rule_options` crate under `lib/`, with serde- and schemars-compatible derives and `#[serde(rename_all = "camelCase", deny_unknown_fields, default)]`
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Types implementing Diagnostic must also implement Debug (e.g., use #[derive(Debug, Diagnostic)])
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Specify category and severity using #[diagnostic(...)] on the type or derive them from fields
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/**/lib/src/**/nursery/**/*.rs : Mark code blocks in docs with a language and required properties: use `expect_diagnostic` for invalid examples (exactly one diagnostic), `options`/`full_options` for config blocks, and `use_options` for subsequent examples
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
🧬 Code graph analysis (1)
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (5)
crates/biome_plugin_loader/src/diagnostics.rs (6)
from
(44-51)from
(56-63)from
(67-69)from
(73-75)from
(79-81)from
(137-139)crates/biome_plugin_loader/src/lib.rs (2)
load_plugin
(141-157)load
(40-118)crates/biome_js_runtime/src/context.rs (1)
new
(25-38)crates/biome_js_runtime/src/plugin_api.rs (2)
new
(17-21)None
(51-51)crates/biome_plugin_loader/src/thread_local.rs (3)
new
(15-24)new
(57-71)new
(106-110)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
- GitHub Check: Check JS Files
- GitHub Check: Test Node.js API
- GitHub Check: Bench (biome_html_formatter)
- GitHub Check: Bench (biome_graphql_parser)
- GitHub Check: Bench (biome_graphql_formatter)
- GitHub Check: Bench (biome_module_graph)
- GitHub Check: Bench (biome_configuration)
- GitHub Check: Bench (biome_json_analyze)
- GitHub Check: Bench (biome_html_parser)
- GitHub Check: Bench (biome_json_formatter)
- GitHub Check: Bench (biome_css_analyze)
- GitHub Check: Bench (biome_css_formatter)
- GitHub Check: Bench (biome_js_formatter)
- GitHub Check: Bench (biome_json_parser)
- GitHub Check: Bench (biome_css_parser)
- GitHub Check: Bench (biome_js_parser)
- GitHub Check: Bench (biome_js_analyze)
- GitHub Check: autofix
🔇 Additional comments (2)
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (2)
56-69
: Good fix for the load error handling!The plugin is now properly loaded upfront to catch errors early, addressing the previous concern about swallowed errors.
142-194
: Well-structured multithreading test!The test effectively validates thread-local plugin isolation by running two workers with separate files and ensuring diagnostics are produced correctly.
317f1a9
to
7ba2798
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (6)
crates/biome_plugin_loader/src/thread_local.rs (6)
15-24
: Prefer a fallible constructor for TLS key allocationPanic on
FlsAlloc == u32::MAX
isn’t great UX in release. Returnio::Result<Self>
and propagate.Example:
- pub(super) unsafe fn new() -> Self { + pub(super) unsafe fn new() -> std::io::Result<Self> { let inner = unsafe { win32::FlsAlloc(None) }; - // FlsAlloc returns FLS_OUT_OF_INDEXES (u32::MAX) on failure. - assert!(inner != u32::MAX, "FlsAlloc failed: out of FLS indexes"); + if inner == u32::MAX { + return Err(std::io::Error::new(std::io::ErrorKind::Other, "FlsAlloc: FLS_OUT_OF_INDEXES")); + } - Self { + Ok(Self { inner, _phantom: PhantomData, - } + }) }Follow-up: bubble this through
ThreadLocalCell::new()
.
56-71
: POSIX: makepthread_key_create
path fallibleMirror Windows: don’t assert, return
io::Result
.Apply:
- pub(super) unsafe fn new() -> Self { - let inner = unsafe { - let mut inner = MaybeUninit::uninit(); - let result = libc::pthread_key_create(inner.as_mut_ptr(), None); - - assert_eq!(result, 0); - - inner.assume_init() - }; - - Self { - inner, - _phantom: PhantomData, - } - } + pub(super) unsafe fn new() -> std::io::Result<Self> { + let mut inner = MaybeUninit::uninit(); + let rc = libc::pthread_key_create(inner.as_mut_ptr(), None); + if rc != 0 { + return Err(std::io::Error::from_raw_os_error(rc)); + } + Ok(Self { inner: inner.assume_init(), _phantom: PhantomData }) + }
77-81
: POSIX: don’t ignorepthread_setspecific
failuresA failed set leads to a later
unwrap()
panic. Assert or, better, returnResult
.Minimal change:
- pub(super) unsafe fn set(&self, value: *mut T) { - let result = unsafe { libc::pthread_setspecific(self.inner, value as *mut c_void) }; - - debug_assert_eq!(result, 0); - } + pub(super) unsafe fn set(&self, value: *mut T) { + let rc = libc::pthread_setspecific(self.inner, value as *mut c_void); + debug_assert_eq!(rc, 0, "pthread_setspecific failed"); + }
102-110
: Remove the panic edge afterset()
; propagate TLS errors fromget_mut_or_try_init
self.set(value); Ok(self.get_mut().unwrap())
will panic if the platformset()
fails. Makeset()
returnio::Result<()>
and map errors inget_mut_or_try_init
.Sketch:
- pub(crate) fn new() -> Self { - Self { key: unsafe { platform::Key::new() }, } - } + pub(crate) fn new() -> std::io::Result<Self> { + Ok(Self { key: unsafe { platform::Key::new()? } }) + } - pub(crate) fn get_mut_or_try_init<F, E>(&self, default: F) -> Result<RefMut<'_, T>, E> + pub(crate) fn get_mut_or_try_init<F, E>(&self, default: F) -> Result<RefMut<'_, T>, E> where F: FnOnce() -> Result<T, E>, { match self.get_mut() { Some(r) => Ok(r), _ => match default() { - Ok(value) => { - self.set(value); - Ok(self.get_mut().unwrap()) - } + Ok(value) => { + self.set(value); // now returns io::Result<()> + // map TLS error into E if you prefer a unified error type + Ok(self.get_mut().expect("TLS set succeeded but value missing")) + } Err(err) => Err(err), }, } } - fn set(&self, value: T) { + fn set(&self, value: T) { let cell = Box::into_raw(Box::new(RefCell::new(value))); - unsafe { self.key.set(cell); } + unsafe { self.key.set(cell); /* -> io::Result<()> in platform layer */ } }Happy to wire a small
TlsInitError<E>
enum if you want the full error story.Also applies to: 112-126, 139-145
29-33
: Windows: FlsSetValue check is wrong; use .as_bool() and handle failure
windows
BOOL doesn’t have.is_ok()
. This is a build breaker on Windows targets.Apply:
- pub(super) unsafe fn set(&self, value: *mut T) { - let result = unsafe { win32::FlsSetValue(self.inner, Some(value as *const c_void)) }; - - debug_assert!(result.is_ok()); - } + pub(super) unsafe fn set(&self, value: *mut T) { + let ok = win32::FlsSetValue(self.inner, Some(value as *const c_void)).as_bool(); + debug_assert!(ok, "FlsSetValue failed"); + }
36-41
: Windows: FlsFree check is wrong; use .as_bool()Same issue as above;
.is_ok()
will not compile.Apply:
- fn drop(&mut self) { - let result = unsafe { win32::FlsFree(self.inner) }; - - debug_assert!(result.is_ok()); - } + fn drop(&mut self) { + let ok = unsafe { win32::FlsFree(self.inner) }.as_bool(); + debug_assert!(ok, "FlsFree failed"); + }
🧹 Nitpick comments (6)
crates/biome_js_runtime/src/module_loader.rs (2)
57-58
: Set source path for better stack tracesAttach the resolved path to
Source
so errors show correct filenames.Apply:
- let source = Source::from_bytes(source.as_bytes()); + let source = Source::from_bytes(source.as_bytes()).with_path(path.as_std_path());
33-36
: Cache key may collide across different referrers; confirm Boa’s specifier semanticsYou key the cache by the raw
specifier
string. If two modules in different directories import the same relative specifier (e.g."./config.js"
), you may return the wrong cached module. If Boa passes the original (unresolved) specifier intoget_module
, this is a real hazard.Options:
- Key by the resolved absolute path (preferred), and in
load_imported_module
consult this map first.- Or maintain a secondary map keyed by
(referrer_path, specifier)
.Would you confirm Boa’s contract for
get_module
/register_module
specifiers? If it’s unresolved, we should switch to a resolved-path cache.Also applies to: 40-47, 52-59, 86-88
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (3)
50-53
: Include plugin path in Debug outputHandy when multiple plugins are loaded.
Apply:
impl Debug for AnalyzerJsPlugin { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("AnalyzerJsPlugin").finish_non_exhaustive() + f.debug_struct("AnalyzerJsPlugin") + .field("path", &self.path) + .finish_non_exhaustive() } }
80-85
: Add plugin path to the “could not load” diagnosticGives users immediate context.
Apply:
- return vec![RuleDiagnostic::new( + return vec![RuleDiagnostic::new( category!("plugin"), None::<TextRange>, - markup!("Could not load the plugin: "<Error>{err.to_string()}</Error>), + markup!("Could not load the plugin "<Emphasis>{self.path.as_str()}</Emphasis>": "<Error>{err.to_string()}</Error>), )];
99-105
: Include plugin path in runtime error diagnosticSame rationale as above.
Apply:
- vec![RuleDiagnostic::new( + vec![RuleDiagnostic::new( category!("plugin"), None::<TextRange>, - markup!("Plugin errored: "<Error>{err.to_string()}</Error>), + markup!("Plugin "<Emphasis>{self.path.as_str()}</Emphasis>" errored: "<Error>{err.to_string()}</Error>), )]crates/biome_js_runtime/src/context.rs (1)
48-53
: Enrich I/O error with pathThe extra context helps debugging.
Apply:
- let source = self - .fs - .read_file_from_path(path) - .map_err(|err| JsNativeError::error().with_message(err.to_string()))?; + let source = self + .fs + .read_file_from_path(path) + .map_err(|err| JsNativeError::error().with_message(format!("Failed to read {}: {}", path, err)))?;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
Cargo.lock
is excluded by!**/*.lock
and included by**
📒 Files selected for processing (8)
crates/biome_js_runtime/src/context.rs
(1 hunks)crates/biome_js_runtime/src/module_loader.rs
(1 hunks)crates/biome_js_runtime/src/plugin_api.rs
(1 hunks)crates/biome_plugin_loader/Cargo.toml
(1 hunks)crates/biome_plugin_loader/src/analyzer_js_plugin.rs
(1 hunks)crates/biome_plugin_loader/src/thread_local.rs
(1 hunks)packages/@biomejs/plugin-api/index.d.ts
(1 hunks)plugins/plugin.js
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- plugins/plugin.js
- packages/@biomejs/plugin-api/index.d.ts
- crates/biome_js_runtime/src/plugin_api.rs
- crates/biome_plugin_loader/Cargo.toml
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rs,toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Format Rust and TOML files before committing (use
just f
/just format
).
Files:
crates/biome_js_runtime/src/module_loader.rs
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
crates/biome_plugin_loader/src/thread_local.rs
crates/biome_js_runtime/src/context.rs
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_js_runtime/src/module_loader.rs
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
crates/biome_plugin_loader/src/thread_local.rs
crates/biome_js_runtime/src/context.rs
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Add biome_js_formatter as a path dependency in Cargo.toml: biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/{src,resolver,biome_module_graph/src}/**/*.rs : Implement and use type resolution via the TypeResolver trait; resolvers own TypeStore vectors and provide fast by-id and hashed lookups
Applied to files:
crates/biome_js_runtime/src/module_loader.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/lib/src/lint/nursery/*.rs : For new JavaScript lint rules generated by `just new-js-lintrule`, implement the rule in the generated file under `biome_js_analyze/lib/src/lint/nursery/`
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Use helper advice types from biome_diagnostics::v2 (CodeFrameAdvice, CommandAdvice, DiffAdvice, LogAdvice) when suitable
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/**/lib/src/**/nursery/**/*.rs : Use the local `rule_category!()` macro in diagnostics for the rule’s category, not string-parsed categories
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/tests/quick_test.rs : Use `biome_js_analyze/tests/quick_test.rs` for quick, ad-hoc testing; un-ignore the test and adjust the rule filter as needed
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Specify category and severity using #[diagnostic(...)] on the type or derive them from fields
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Types implementing Diagnostic must also implement Debug (e.g., use #[derive(Debug, Diagnostic)])
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Define per-rule options in the `biome_rule_options` crate under `lib/`, with serde- and schemars-compatible derives and `#[serde(rename_all = "camelCase", deny_unknown_fields, default)]`
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/**/lib/src/**/nursery/**/*.rs : Mark code blocks in docs with a language and required properties: use `expect_diagnostic` for invalid examples (exactly one diagnostic), `options`/`full_options` for config blocks, and `use_options` for subsequent examples
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
🧬 Code graph analysis (3)
crates/biome_js_runtime/src/module_loader.rs (2)
crates/biome_js_runtime/src/context.rs (1)
new
(25-38)crates/biome_js_runtime/src/plugin_api.rs (1)
new
(17-21)
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (5)
crates/biome_plugin_loader/src/lib.rs (1)
load
(40-118)crates/biome_js_runtime/src/context.rs (1)
new
(25-38)crates/biome_js_runtime/src/module_loader.rs (1)
new
(17-22)crates/biome_js_runtime/src/plugin_api.rs (2)
new
(17-21)None
(51-51)crates/biome_plugin_loader/src/thread_local.rs (3)
new
(15-24)new
(57-71)new
(106-110)
crates/biome_js_runtime/src/context.rs (2)
crates/biome_js_runtime/src/module_loader.rs (1)
new
(17-22)crates/biome_js_runtime/src/plugin_api.rs (2)
new
(17-21)pull_diagnostics
(82-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: Documentation
- GitHub Check: End-to-end tests
- GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: Lint project (depot-windows-2022)
- GitHub Check: Check Dependencies
- GitHub Check: Test Node.js API
- GitHub Check: Check JS Files
- GitHub Check: autofix
🔇 Additional comments (2)
crates/biome_js_runtime/src/module_loader.rs (1)
60-67
: Nice: cache after parse to avoid re-parsingGood addition; this prevents duplicate work and aligns with Boa’s expectations.
crates/biome_js_runtime/src/context.rs (1)
90-95
: Double-checkJsError::try_native
return type for your Boa versionSome versions return
Option<JsNativeError>
, others aResult
. Yourmatch
usesOk(native)
, which may be incompatible.If it returns
Option
, prefer:if let Some(native) = opaque.try_native(ctx) { break Err(native.into()); } break Err(opaque);Else keep the current
Result
-based handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
crates/biome_js_runtime/src/module_loader.rs (1)
68-71
: Nice: parsed modules are cachedThis addresses redundant parsing; good alignment with Boa’s loader contract and prior feedback.
🧹 Nitpick comments (2)
crates/biome_js_runtime/src/module_loader.rs (1)
50-52
: Tiny clean-up: simplify default initMinor readability win.
- let options = ResolveOptions { - ..Default::default() - }; + let options = ResolveOptions::default();crates/biome_plugin_loader/src/analyzer_js_plugin.rs (1)
100-109
: Optional: include JS stack in error diagnosticsIf available, prefer a representation that preserves the JS stack/frames for quicker debugging.
Example (if Boa exposes it):
- .map_or_else( - |err| { + .map_or_else( + |err| { vec![RuleDiagnostic::new( category!("plugin"), None::<TextRange>, - markup!("Plugin errored: "<Error>{err.to_string()}</Error>), + markup!("Plugin errored: "<Error>{err.display().to_string()}</Error>), )] },Happy to wire a helper that formats Boa errors consistently across plugin diagnostics.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
crates/biome_js_runtime/src/context.rs
(1 hunks)crates/biome_js_runtime/src/module_loader.rs
(1 hunks)crates/biome_plugin_loader/src/analyzer_js_plugin.rs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/biome_js_runtime/src/context.rs
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rs,toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Format Rust and TOML files before committing (use
just f
/just format
).
Files:
crates/biome_js_runtime/src/module_loader.rs
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_js_runtime/src/module_loader.rs
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:48:52.001Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Add biome_js_formatter as a path dependency in Cargo.toml: biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/{src,resolver,biome_module_graph/src}/**/*.rs : Implement and use type resolution via the TypeResolver trait; resolvers own TypeStore vectors and provide fast by-id and hashed lookups
Applied to files:
crates/biome_js_runtime/src/module_loader.rs
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/biome_module_graph/src/js_module_info/scoped_resolver.rs : Full inference resolves TypeReference::Import across modules into TypeReference::Resolved using the module graph; do not cache full-inference results
Applied to files:
crates/biome_js_runtime/src/module_loader.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/lib/src/lint/nursery/*.rs : For new JavaScript lint rules generated by `just new-js-lintrule`, implement the rule in the generated file under `biome_js_analyze/lib/src/lint/nursery/`
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Use helper advice types from biome_diagnostics::v2 (CodeFrameAdvice, CommandAdvice, DiffAdvice, LogAdvice) when suitable
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/**/lib/src/**/nursery/**/*.rs : Use the local `rule_category!()` macro in diagnostics for the rule’s category, not string-parsed categories
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/tests/quick_test.rs : Use `biome_js_analyze/tests/quick_test.rs` for quick, ad-hoc testing; un-ignore the test and adjust the rule filter as needed
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Specify category and severity using #[diagnostic(...)] on the type or derive them from fields
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Define per-rule options in the `biome_rule_options` crate under `lib/`, with serde- and schemars-compatible derives and `#[serde(rename_all = "camelCase", deny_unknown_fields, default)]`
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Types implementing Diagnostic must also implement Debug (e.g., use #[derive(Debug, Diagnostic)])
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/**/lib/src/**/nursery/**/*.rs : Mark code blocks in docs with a language and required properties: use `expect_diagnostic` for invalid examples (exactly one diagnostic), `options`/`full_options` for config blocks, and `use_options` for subsequent examples
Applied to files:
crates/biome_plugin_loader/src/analyzer_js_plugin.rs
🧬 Code graph analysis (2)
crates/biome_js_runtime/src/module_loader.rs (1)
crates/biome_js_runtime/src/context.rs (1)
new
(25-38)
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (4)
crates/biome_plugin_loader/src/lib.rs (1)
load
(40-118)crates/biome_js_runtime/src/context.rs (1)
new
(25-38)crates/biome_js_runtime/src/plugin_api.rs (2)
new
(17-21)None
(51-51)crates/biome_plugin_loader/src/thread_local.rs (3)
new
(15-24)new
(57-71)new
(106-110)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (25)
- GitHub Check: Bench (biome_configuration)
- GitHub Check: Bench (biome_html_formatter)
- GitHub Check: Bench (biome_graphql_formatter)
- GitHub Check: Bench (biome_package)
- GitHub Check: Bench (biome_js_formatter)
- GitHub Check: Bench (biome_json_formatter)
- GitHub Check: Bench (biome_module_graph)
- GitHub Check: Bench (biome_graphql_parser)
- GitHub Check: Bench (biome_css_analyze)
- GitHub Check: Bench (biome_html_parser)
- GitHub Check: Bench (biome_json_analyze)
- GitHub Check: Bench (biome_json_parser)
- GitHub Check: Bench (biome_css_formatter)
- GitHub Check: Bench (biome_css_parser)
- GitHub Check: Bench (biome_js_parser)
- GitHub Check: Bench (biome_js_analyze)
- GitHub Check: Documentation
- GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
- GitHub Check: Lint project (depot-windows-2022)
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Check Dependencies
- GitHub Check: autofix
- GitHub Check: Check JS Files
- GitHub Check: Test Node.js API
🔇 Additional comments (1)
crates/biome_plugin_loader/src/analyzer_js_plugin.rs (1)
63-65
: No mapping needed—JsError
already converts toPluginDiagnostic
There’s an existing
impl From<boa_engine::JsError> for PluginDiagnostic
incrates/biome_plugin_loader/src/diagnostics.rs:55
, so the?
on aJsResult
will automatically convert aJsError
into aPluginDiagnostic
. The code compiles as-is.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this file used for testing purposes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, and I would keep it for an example of the plugin. Plus we can include it in the E2E test after lifted the js_plugin
feature
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's the case, should we add the package inside the peer dependencies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I'll do it in a follow-up PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should pull the type from workspace.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but I would avoid depending on the @biomejs/backend-jsonrpc
package as most part of it is unnecessary. I'll add a codegen for AST types later and will include the type of Severity
there
Summary
Part of #2469
This pull request integrates the Boa engine to Biome for JS plugins. It runs the default exported function and pulls diagnostics from the plugin. JS APIs for Biome's AST/CST aren't implemented yet.
Support for JS plugins is gated behind the
js_plugin
feature and it will be enabled only in preview releases. Thus I think we can merge this to the main branch.Test Plan
Added a simple test using multiple threads.
Docs
TODO