コンテンツへスキップ

はじめに

Phasisは純粋なPHP製のJavaScriptエンジンです。ホストのPHPプロセス内でECMAScriptを字句解析、構文解析、実行します。exec('node …')、FFI、カスタムバイナリ拡張は不要です。標準のPHP拡張が3つ必要です。ext-mbstring、ext-bcmath、およびデフォルトのfetch()トランスポートであるext-curlです。ext-intlとext-opensslは任意です。bcmathを含めないビルドについてははじめにをご覧ください。

  • 埋め込み可能 — Phasis\Engineクラスを使って、任意のPHPアプリ、フレームワーク、CLIツールにJSランタイムを組み込めます。
  • 仕様準拠 — 公式test262スイートの全カテゴリをスキップなしで100 %通過します。
  • Web API — Web Platform Pack全機能(URL、TextEncoder/Decoder、atob/btoa、structuredClone、performance、DOMException)、Fetch Pack全機能(fetch、Request、Response、Headers、Body、AbortController/Signal、Blob、File、FormData、EventTarget、WHATWG Streams全機能、navigator)に加え、crypto + SubtleCrypto、WebSocket、XMLHttpRequest、実際のイベントループを搭載。インポートしたWeb Platform Testsの100 %に合格します。
  • モダンな機能 — アロー関数、クラス、async/await、Promises、ジェネレーター、Symbol、BigInt、Proxy、Reflect、Temporal、Intl、TypedArrays、モジュールの完全サポート。
  • PHP↔JS相互運用 — PHPのスカラー値と配列をJSに渡せます(配列はコピーされます)。PHPのクロージャをJS関数としてバインドし、PHPからJS関数を呼び出せます。PHPオブジェクトはまだJSと共有できません。共有オブジェクトをご覧ください。

Phasisが作られた理由

ユーザー提供のJavaScriptを実行する必要があるPHPアプリ(テンプレートエンジン、フロントエンドSSRの代替手段、データ検証ルール、コンテンツのサンドボックス、ヘッドレステストランナーなど)は、通常Node.jsを別プロセスで起動するか、機能自体を見送ります。どちらの方法でも運用は複雑になります。2つ目のランタイム、シリアライズ境界、サブプロセスとの多数のパイプ、共有ホスティングでの扱いにくいデプロイ構成が必要です。

Phasisはその課題を解決します。PHPのコードはJavaScriptを字句解析、構文解析、実行できます。必要なのはPHP 8.2+、mbstring、bcmath、curlだけです。エンジンはComposerパッケージとして提供され、シンプルで小さなAPIインターフェースを備えています。

機能

  • ECMAScript標準ライブラリ全体を実装:Array、String、Object、Math、JSON、Date、RegExp、Map、Set、Promise、Proxy、Reflect、Symbol、BigInt、TypedArray、Temporal、Intl、ジェネレーター、asyncイテレーター、モジュール。
  • 実際のJSライブラリが事前に存在を確認するWeb Platform APIを搭載:URL、URLSearchParams、TextEncoder/TextDecoder、atob/btoa、structuredClone、performance、DOMException。全機能についてはWeb APIをご覧ください。
  • fetch にFetch関連の全機能を搭載 — Request、Response、Headers、ボディの読み取りメソッド、AbortController/AbortSignal、Blob、File、FormData、EventTarget/Event、WHATWG Streams全機能(ReadableStream、WritableStream、TransformStream、BYOB、キューイング戦略)。実際のHTTPはPHPのext-curlによってすぐに使えます。
  • crypto とSubtleCrypto全機能(SHAファミリー、HMAC、AES-GCM/CBC/CTR、RSA-OAEP/PSS/PKCS1、ECDSA、ECDH、HKDF、PBKDF2)、WebSocket(RFC 6455 + 交換可能なトランスポート)、XMLHttpRequest(同じfetchトランスポートを基盤として実装)を搭載。
  • 実際のイベントループを搭載:setTimeout、setInterval、clearTimeout、clearInterval、queueMicrotaskに加え、非同期境界を越えて値を伝播するStage-3のAsyncContext。
  • モダンな構文をサポート — 分割代入、スプレッド/レスト、計算されたプロパティ、オプショナルチェーン、Null合体、テンプレートリテラル、タグ付きテンプレート、クラス(プライベートフィールド、staticブロック、デコレーターを含む)、トップレベルawait。
  • PHP↔JS境界で値を変換。スカラー値と配列はコピーして渡され、PHPの呼び出し可能オブジェクトはJS関数になり、JSからの結果はPHPのスカラー値と配列として返されます。詳しい規則は値の変換をご覧ください。
  • ホスト側で制御して実行。fetchトランスポートとポリシーフックはホストが管理し、イベントループは仮想時間で動作します。固定のコールスタック上限で無限再帰を防ぎます。ループ反復回数の上限はありますが、バイトコードVMが実行するループにはまだ適用されず、文字列長、出力、実時間の上限もありません。API: setLimitをご覧ください。
  • Node.js(V8)に対して検証済み。CIはすべてのpushとプルリクエストでmainのユニットテストとオラクルテストを実行し、エンジンのソースに変更があった場合はWeb Platform Testsと人気パッケージのテストも実行します。test262の全マトリクスは手動で実行し、結果のスナップショットをCOMPAT.mdにコミットします。互換性をご覧ください。

merqlでできないこと

PhasisはJITコンパイラーではありません。ツリーウォーキングインタープリターと、状況に応じて使われるバイトコードVMです。ディスパッチがボトルネックとなる処理では、V8の約100倍の実行時間を見込んでください。依存関係ゼロの純粋なPHPと、ホストが実行を制御できることが利点です。生の処理速度より正確性と分離が重要なPHPアプリにJavaScriptを組み込む用途に最適です。

まず読むページ

  • はじめに — インストールして最初のスクリプトを実行します。
  • CLI — ファイルの実行、ソースの評価、ASTの出力に使うbin/phasis。
  • API — PHPアプリにPhasis\Engineを埋め込みます。
  • 相互運用 — PHPの値や呼び出し可能オブジェクトをJavaScriptに渡します。
  • 互換性 — test262のカバレッジとサポート対象の機能。
  • パーサー — JavaScriptを実行せずに型付きASTまたはESTreeへ解析します。
  • フォーマッター — prettier互換のレイアウトでJavaScript、JSON、CSSを整形します。
  • 高度な内容 — アーキテクチャ、バイトコードVM、ベンチマーク、オラクルテストの仕組み。