CLI tool
boa-dev/boa avatar
boa-dev/boa

Boa: an embeddable JavaScript engine in Rust, from boa-dev/boa

Boa is an embeddable Javascript engine written in Rust.

7,575 stars665 forksRustMIT

At a glance

What is it?
Boa is an experimental ECMAScript lexer, parser and interpreter written in Rust, distributed as a set of crates. It is aimed at Rust developers who want to run JavaScript inside their own programs rather than ship a separate runtime.
Who is it for?
Adopt Boa if you are writing Rust and want to evaluate JavaScript inside your own process through the boa_engine crate, and you accept that the project describes itself as experimental with roughly 90 percent or more of the latest ECMAScript specification covered. Do not adopt it as a drop-in replacement for Node.js or for a full browser engine, because the Web API surface lives in the separate boa_runtime crate and the README does not claim completeness.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Boa is for, and who should embed it

Boa is a JavaScript engine written in Rust, published by the boa-dev organisation. The README describes it as an experimental JavaScript lexer, parser and interpreter, and states that it supports more than 90% of the latest ECMAScript specification. That word experimental is the project's own, and it sets the expectation for everything else.

The intended consumer is a Rust program that needs to run JavaScript as part of its own logic: a plugin layer, a rules engine, a configuration language, a scripting hook in a larger application. The README's example is a Rust binary that creates a Context, evaluates a string of JavaScript and prints the result. Nothing in that example starts a process, opens a socket or installs a runtime. The JavaScript lives inside the host program.

Boa is not a browser engine and it is not a Node.js replacement. The repository separates concerns into crates: boa_parser for the lexer and parser, boa_engine for builtin objects and execution, boa_gc for garbage collection, boa_interner for string interning, boa_ast for the syntax tree, boa_string for the ECMAScript string implementation, and boa_runtime for Web API features. If you need fetch, timers or other host APIs, the README points you at boa_runtime, not at the engine crate.

The crate split behind boa_engine

The workspace Cargo.toml lists the members by category: core, ffi, tests, tools, examples, cli, utils and benches. The core directory holds the pieces that ship to users, and the version pins are exact within a minor line, written as tilde requirements such as boa_engine = { version = "~0.22.0", path = "core/engine", default-features = false }. That default-features = false on the engine is worth noting: the workspace definition does not turn features on for you.

The execution model follows the crate boundaries. Source text goes through boa_parser, which produces a syntax tree in boa_ast. Strings inside that tree are deduplicated by boa_interner. Execution happens in boa_engine, and the objects it allocates are managed by boa_gc. The README lists tag_ptr as a utility crate that associates a pointer with a usize tag, which is the kind of low-level detail you only expose when you expect other people to build on your internals.

There is also an FFI directory in the repository, and a deprecated set of crates: the README states that the Boa and boa_unicode crates are deprecated. If you find an older tutorial that tells you to depend on a crate named Boa, that advice is out of date. The current entry point is boa_engine.

Two targets are supported beyond native Rust. The topics list includes wasm and webassembly, and the README links a live playground at boajs.dev/playground, which the project describes as a Wasm build. The CLI crate, boa_cli, is the other consumer-facing artifact.

Installing boa_engine and running your first script

The README's install path is a Cargo dependency. Add boa_engine to your Cargo.toml; the README shows the version as 0.21.0, while the workspace in the repository is at 0.22.0, so use the version you actually intend to pin.

toml
[dependencies]
boa_engine = "0.21.0"

Then write a main.rs that creates a Context, evaluates a Source and prints the result. The README's example relies on string concatenation to show that JavaScript coercion is happening inside the engine, not in Rust.

rust
use boa_engine::{Context, Source, JsResult};

fn main() -> JsResult<()> {
  let js_code = r#"
      let two = 1 + 1;
      let definitely_not_four = two + "2";

      definitely_not_four
  "#;

  let mut context = Context::default();

  let result = context.eval(Source::from_bytes(js_code))?;

  println!("{}", result.display());

  Ok(())
}

Running cargo run should print the coerced string, which the README's variable naming makes clear is not the number four. If you prefer a command line over an embedding, the README describes cloning the repository and running cargo run -- test.js from the project root, where test.js is any file of valid JavaScript. The README adds a blunt sentence about that path: if any JavaScript does not work, the project treats it as a bug and asks you to open an issue.

The CLI accepts a set of options documented in the README, including --strict for strict mode, -a or --dump-ast with formats debug, json or json-pretty, -O or --optimize, --flowgraph with graphviz or mermaid output, -m or --module to treat input files as modules, and -r or --root to set the path from which the module resolver loads modules, defaulting to the current directory. There is also --debug-object, which injects a $boa debugging object, and --test262-object, which injects the $262 host object used by the conformance suite. Those last two are development tools rather than everyday flags.

WebAssembly needs a feature flag and a rustflag

Building for wasm32-unknown-unknown is not the default path. The README states that you must enable the js feature flag and set a rustflag for the getrandom backend. The README gives the setting as RUSTFLAGS='--cfg getrandom_backend="wasm_js"'.

The README notes that the same setting can live in a .cargo/config.toml at the project root, which is friendlier than exporting the variable in every shell.

toml
[target.wasm32-unknown-unknown]
rustflags = '--cfg getrandom_backend="wasm_js"'

According to the README, this applies only to the wasm32-unknown-unknown target; the WASI and Emscripten variants are handled automatically. The README links to the getrandom documentation for the underlying explanation. This is a real constraint rather than a footnote: if you skip the rustflag, the build configuration for randomness on wasm is incomplete, and the README gives no fallback for it.

Where Boa is the wrong tool

The conformance figure is the first limitation, and it comes from the project itself. More than 90% of the latest ECMAScript specification is not the same as all of it. The README also links a Test262 results page, which is where the exact gaps are visible; the README does not enumerate them, so the page is the only place to check before you depend on a particular language feature.

The second limitation is the word experimental. The README applies it to the engine as a whole. That is a statement about stability expectations, not a marketing hedge. If your product cannot tolerate a language feature that changes between releases, this is not the engine for that job.

The third limitation is host APIs. The engine crate implements ECMAScript builtins and execution. The README puts Web API features in boa_runtime, a separate crate. A script that calls fetch or expects browser-style timers will not find them in boa_engine alone.

The fourth is toolchain cost. The workspace declares rust-version = 1.91.0 and edition 2024. If your project is pinned to an older compiler, you cannot simply drop this in; you are upgrading the toolchain or you are not building it. Boa is also not the right choice when you need a JavaScript runtime with a package ecosystem, an npm-compatible module resolver, or a process model. It evaluates scripts. It does not give you a server.

Finally, performance is not something the README asserts. It points to benchmark results on boajs.dev/benchmarks and describes the benchmark scripts as taken from v8's benchmark suite, stored in a bench-v8 directory. The README gives the command cargo run --release -p boa_cli -- bench-v8/combined.js, and says that running only a subset means editing the Makefile in the bench-v8 directory and commenting out the benchmarks you do not want. Anyone choosing an engine on speed should read that page and run that command rather than take a number from an article.

Boa against QuickJS and other embeddable engines

The comparison people search for is Boa versus QuickJS, and the difference is mostly about what you are willing to link against. QuickJS is a small C library by Fabrice Bellard; you embed it through a C API and it has no Rust dependency graph. Boa is a Rust workspace, so its build is cargo, its types are Rust types, and its garbage collector is boa_gc rather than a C refcount or a manual free.

That difference cuts both ways. If your host program is C or C++, Boa is a poor fit: you would be crossing an FFI boundary, and although the repository has an ffi directory, the README's documented path is a Rust dependency. If your host program is Rust, Boa's advantage is that Context, Source and JsResult are ordinary Rust values you can pass around, and the error type integrates with Rust's result handling, as the README example's JsResult<()> return type shows.

The other axis is specification coverage and pace. The README describes a project that continuously improves conformance and publishes Test262 results, with releases at v0.21, v0.21.1, v0.22 and a last push on 2026-09-20. A smaller C engine may be easier to audit in one sitting; Boa's trade-off is a larger, faster-moving codebase that tracks a modern specification but carries the experimental label.

Licensing, maintenance and the cost of upgrading

The repository carries LICENSE-MIT and LICENSE-UNLICENSE at the top level, and the workspace package metadata states license = "Unlicense OR MIT". The GitHub repository page lists the license as MIT. For most users the practical effect is that you may choose either, but dual licensing is a question for your own legal review, not something this article can settle.

Maintenance looks current. The last push was on 2026-09-20, two days before this writing, and the repository is not archived. The most recent release, v0.22, is dated 2026-08-28. There is a CHANGELOG.md at the top level, which is where to look for breaking changes between releases.

Upgrade cost is where the workspace layout matters. The internal crates are versioned together at ~0.22.0, and the workspace pins dependencies such as boa_engine with a tilde requirement, meaning patch releases are accepted but minor bumps are deliberate. If you depend on boa_engine directly, a move from 0.21 to 0.22 is a minor-version change under Cargo's rules and can carry breaking changes. The README's install snippet still shows 0.21.0 while the repository is at 0.22.0, which is a small sign that documentation lags releases by one cycle.

There is also a toolchain cost on every upgrade. The workspace requires Rust 1.91.0 or newer and uses edition 2024, so each Boa release is a reason to check your CI image's compiler version. The repository ships a flake.nix and a Makefile.toml, which suggests the maintainers keep reproducible build tooling, but the README does not document a supported-versions policy beyond the rust-version field.

Editorial conclusion

Adopt Boa if you are writing Rust and want to evaluate JavaScript inside your own process through the boa_engine crate, and you accept that the project describes itself as experimental with roughly 90 percent or more of the latest ECMAScript specification covered. Do not adopt it as a drop-in replacement for Node.js or for a full browser engine, because the Web API surface lives in the separate boa_runtime crate and the README does not claim completeness. Before committing, check the Test262 conformance page the README links to, pick a release from the crates.io listing rather than the main branch, and confirm the Rust version your toolchain provides meets the workspace rust-version of 1.91.0.

Frequently asked questions

What does Boa stand for?

The README does not expand the name into an acronym; it uses Boa as the project name throughout and pairs it with the boa-dev organisation and the boajs.dev site. The repository description simply calls it an embeddable JavaScript engine written in Rust.

How do I install Boa in a Rust project?

Add the boa_engine crate to the dependencies section of your Cargo.toml, then create a Context and call eval on a Source, as the README example shows. The README's snippet uses version 0.21.0 while the repository workspace is at 0.22.0.

Does Boa support WebAssembly?

Yes, for the wasm32-unknown-unknown target the README says to enable the js feature flag and set RUSTFLAGS with getrandom_backend set to wasm_js, or place the same setting in a .cargo/config.toml. The README states that WASI and Emscripten targets are handled automatically.

Can I run Boa from the command line without writing Rust?

Yes. The README says to clone the repository and run cargo run -- test.js from the project root, where test.js is a path to a file of valid JavaScript. The CLI also exposes options such as --strict, --dump-ast, --optimize and --module, plus a REPL with an optional vi mode.

Is Boa a complete implementation of ECMAScript?

The README states that Boa supports more than 90% of the latest ECMAScript specification and links a Test262 conformance page for the details. It describes the engine as experimental, and the README does not claim full coverage.

Official sources

  1. boa-dev/boa on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/boa-dev-boa.svg)](https://hysenlabs.com/projects/boa-dev-boa)