はじめに
BoaはRustで書かれた実験的なJavaScriptエンジンですね。
GitHubで6,690スター以上、204名以上の貢献者を持つプロジェクトで、7年以上の開発歴があります。個人的には、自分のRustアプリケーションにJavaScriptを組み込みたいケースで、かなり有力な選択肢だと思っています。
正直なところ、「JavaScriptエンジンを自作?そんなの大手しかできないでしょ」と思っていたんですよ。でもBoaを触ってみると、Cargoでサクッとインストールできて、数行のRustコードでJSを実行できる。「なるほど、こういう世界もあるのか」という感覚でした。
ライセンスはMITまたはUnlicenseのデュアルライセンスで、商用利用も安心です。
Boaとは
Boaは「An ECMAScript engine written in Rust」を掲げるJavaScriptエンジンです。字句解析器、パーサー、インタープリターをすべてRustで実装しています。
特筆すべきは、ECMAScript Test262テストスイートの90%以上をパスしていること。これ、意外とすごいことで、仕様準拠度がかなり高い。V8やSpiderMonkeyのような巨大エンジンには及ばないものの、実用的なJavaScriptコードは問題なく動きます。
特徴・メリット
1. Rustのメモリ安全性
BoaはRustで実装されているので、メモリ安全性が保証されています。
C++で書かれた従来のJSエンジンと比べて、バッファオーバーフローやメモリリークのリスクが低い。セキュリティを重視する場面では、これが大きなアドバンテージになります。
2. 埋め込みが簡単
Cargo.tomlに依存関係を追加するだけで、自分のRustアプリにJavaScriptエンジンを組み込めます。
V8やQuickJSをRustから使おうとすると、FFIやバインディングの設定が面倒なんですよね。Boaは純粋なRustなので、そういった煩わしさがない。
3. 複数のクレート構成
Boaは以下のクレートを提供しています:
boa_engine- メインの実行エンジンboa_parser- 字句解析と構文解析boa_ast- 抽象構文木(AST)boa_gc- ガベージコレクターboa_cli- REPL/コマンドラインツール
必要な部分だけを使える設計になっている。パーサーだけ使いたい場合はboa_parserだけ依存すればいい。
4. WebAssembly対応
BoaはWASMにコンパイルして、ブラウザ上で動かすこともできます。
公式サイトにはプレイグラウンドがあって、その場でJavaScriptコードを実行できる。ブラウザの中でブラウザのJSエンジンを使わずにJSを実行する、という不思議な体験ができます。
5. 豊富なCLIオプション
開発者向けに、ASTのダンプやフローグラフの生成など、デバッグに便利な機能が揃っています。
JSエンジンの内部動作を学びたい人にとっては、良い教材になると思います。
インストール方法
前提条件
Rust 1.70以上がインストールされていること。
ライブラリとして使用
Cargo.tomlに以下を追加します:
[dependencies]
boa_engine = "0.21.0"
CLIツールのインストール
REPLを使いたい場合は、CLIをインストールします:
cargo install boa_cli
これでboaコマンドが使えるようになります。
基本的な使い方
シンプルなJavaScript実行
use boa_engine::{Context, Source, JsResult};
fn main() -> JsResult<()> {
// JavaScriptコード
let js_code = r#"
let two = 1 + 1;
let result = two + "2";
result
"#;
// コンテキストを作成
let mut context = Context::default();
// JavaScriptを実行
let result = context.eval(Source::from_bytes(js_code))?;
// 結果を表示
println!("Result: {}", result.display());
Ok(())
}
これを実行するとResult: 22と出力されます。数値の2が文字列として連結されるJavaScriptらしい挙動ですね。
Rust関数をJavaScriptから呼び出す
use boa_engine::{
Context, JsResult, JsValue, NativeFunction, Source,
};
fn main() -> JsResult<()> {
let mut context = Context::default();
// Rust側の関数を定義
let greet = NativeFunction::from_fn_ptr(|_this, args, _ctx| {
let name = args
.get(0)
.and_then(|v| v.as_string())
.map(|s| s.to_std_string_escaped())
.unwrap_or_else(|| "World".to_string());
Ok(JsValue::from(format!("Hello, {}!", name)))
});
// グローバルオブジェクトに登録
context
.register_global_builtin_callable(
"greet".into(),
1,
greet,
)?;
// JavaScript側から呼び出し
let result = context.eval(Source::from_bytes(r#"greet("Rust")"#))?;
println!("{}", result.display());
Ok(())
}
RustとJavaScriptの相互運用がこれだけ簡単にできる。これ、意外と便利です。
CLIでREPLを使う
$ boa
Welcome to Boa v0.21.0
> let x = 10;
undefined
> x * 2
20
> function add(a, b) { return a + b; }
undefined
> add(1, 2)
3
Node.jsのREPLと同じ感覚で使えます。
実践的なユースケース
ゲームエンジンへの組み込み
自作のゲームエンジンにスクリプティング機能を追加したいケース。
Luaの代わりにJavaScriptを使いたい場合、Boaは良い選択肢になります。Rustで書かれたゲームエンジンなら、統合がスムーズ。
設定ファイルの動的評価
JSONやTOMLだと表現力が足りない場合、JavaScriptで設定を書けるようにする。
let config_code = std::fs::read_to_string("config.js")?;
let mut context = Context::default();
let config = context.eval(Source::from_bytes(&config_code))?;
ただし、セキュリティには注意が必要です。
プラグインシステム
アプリケーションにプラグイン機能を持たせたい場合。
ユーザーがJavaScriptでプラグインを書けるようにして、Boa経由で実行する。サンドボックス化されたJavaScript実行環境として使えます。
教育目的
JavaScriptエンジンの仕組みを学びたい人には、Boaのソースコードは良い教材になります。
字句解析、構文解析、ASTの構築、インタープリターの実装など、教科書に載っているような概念を実際のコードで追えます。
V8やQuickJSとの比較
正直な比較をしておきます。
| 観点 | Boa | V8 | QuickJS |
|---|---|---|---|
| 言語 | Rust | C++ | C |
| 速度 | 遅め | 最速 | 中程度 |
| ECMAScript準拠 | 90%+ | 99%+ | 高い |
| バイナリサイズ | 小さい | 大きい | 非常に小さい |
| Rust統合 | ネイティブ | FFI必要 | FFI必要 |
| JIT | なし | あり | なし |
| 成熟度 | 発展途上 | 成熟 | 成熟 |
Boaの弱点は速度です。JITコンパイラがないので、V8と比べると実行速度は遅い。計算量の多い処理には向きません。
ただし、設定ファイルの評価や小規模なスクリプト実行なら、速度差は気にならないレベルです。
30代になって思うのは、「最速である必要があるか」を考えることの重要性。用途によっては、統合のしやすさや安全性の方が重要なこともある。
今後の展望
Boaは活発に開発が続いています。
最近の動向としては、Temporal API(新しい日付/時刻API)の実装が進んでいるとのこと。ECMAScript仕様への追従も継続的に行われています。
直近1ヶ月で1日平均18スター以上を獲得しているので、注目度は高まっている印象です。
まとめ
Boaを触ってみて感じたこと:
- 統合のしやすさ: Cargoで一発インストール、数行で動く
- 安全性: Rustのメモリ安全性がそのまま活きる
- 学習価値: JSエンジンの仕組みを学ぶのに最適
- 実用性: 軽量な組み込みスクリプトとしては十分
速度重視のプロダクション環境にはまだ早いかもしれませんが、プロトタイプや趣味プロジェクト、教育目的なら十分使えます。
Rustでアプリを書いていて「ちょっとスクリプト機能を追加したいな」と思ったら、Boaを検討してみる価値はありますね。