
# 既知の制限

Phasisは、観測可能なすべての仕様テストでV8と同じ動作を目指しています。このページでは、実際にその同一性が保たれない箇所を説明します。多くの場合、ツリーウォーキング方式のPHPインタープリターとJITコンパイル方式のC++エンジンとの根本的な違いが理由です。

## パフォーマンスの上限

このエンジンは、機会的にバイトコードVMを使うツリーウォーカーと、数値処理やローカル変数を多用する本体（`obj.method()`、`new Ctor()`、`this.member`の形式を含む）をネイティブなPHPクロージャに変換するJsToPhpトランスパイラーで構成されています。これらはPHP 8.5のトレーシングJITによってマシンコードにコンパイルできます。ホットなディスパッチの大半はVMのswitchループ内、またはJITコンパイルされたPHP内で直接行われ、ASTを走査して処理するわけではありません。ただし、VMの各オペコードでは依然としてPHPのディスパッチコストが発生し、JsToPhpがまだ対応していない形式は低速なVMにフォールバックします。ディスパッチ律速のワークロードでは、性能の上限はおよそV8の**約100倍遅い**水準です。

組み込み用途、たとえばPHPデータに対するユーザー提供ロジックの実行、コンテンツ変換パイプライン、検証ルールでは、この上限が問題になることはほとんどありません。V8なら100 ms、Phasisなら10 sですが、どちらもリクエストのタイムアウトを大きく下回ります。差をさらに縮めるには、JsToPhpが扱う形式を増やす（パラメーターの型推論、`await` / `yield*`への変換）か、`eval()`を介さずにopcacheオペコードを直接出力する必要があります。[ベンチマーク § ロードマップ](https://phasis.inline0.dev/ja/docs/advanced/benchmarks#roadmap)を参照してください。

## マルチエージェントの並行処理

JavaScriptの`SharedArrayBuffer` + `Atomics.wait` + `postMessage`モデルは、ホストが実際のOSスレッドを実行できることを前提とします。PHPではそれができません（すべてのホストで利用できるわけではない`pcntl_fork`なしでは）。

Phasisは単一のエージェントをシミュレートします。`Atomics.wait`は直ちに「not-equal」または「timed-out」を返し、`notify`は常に0を返します。これにより、単一エージェントで実行されるtest262テスト（入力検証、エラー経路、何もしないnotify）をすべて通過します。これはAtomicsテスト376件中376件に相当します。

互いを観測する2つのエージェントを実際に必要とするテストには対応していません。真の並列処理には、PHPレベルでワーカーキュー（Redis、Beanstalkd、…）を使用してください。

## Realmのセマンティクス

`ShadowRealm`は実装されていますが、各子Realmはホストと同じPHPプロセス内で実行されます。PHPコードを適切に隔離しないと、ホスト関数を通じてRealm間で参照が漏れる可能性があります。これは仕様上許容されていますが、V8は個別のv8::Isolateインスタンスを使って、より厳格に隔離します。

`createRealm()`（test262のホストフック）は、内部で新しい`Phasis\Engine`を作成し、標準ライブラリを橋渡しします。

## 正規表現エンジンの選択

Phasisは、主な正規表現バックエンドとしてPHPのPCRE2を使用し、PCRE2で厳密に処理できないケース（キャプチャ付き後読み、リセットを伴う量指定グループ、一部の`/v`フラグのセマンティクス）にはカスタムマッチャーを使います。カスタムマッチャーはPCRE2より低速で、ディスパッチ時に互換性のないパターンが検出された場合にのみ使用されます。

特筆すべき影響として、PCRE2の大文字・小文字変換テーブルはV8のICUバージョンと異なる場合があります。特に古いLinuxディストリビューションではその可能性があります（Ubuntu 22.04にはICU 70が含まれますが、Phasisは`/iu`パターンでホスト環境による差異を上書きするため、ICU 76以降の変換テーブルを同梱しています）。

## メモリモデル

PHPの参照カウント方式のGCは、V8のトレーシングコレクターとは異なります。ホストクロージャが捕捉したPHPオブジェクトは、エンジンがそれらのクロージャを保持している間は生存し続け、相互参照の循環は`Engine`が破棄されるまで回収されません。生存させたくないキャッシュには`WeakMap` / `WeakRef`を使用してください。

`process.memoryUsage()`や、V8固有の同様のイントロスペクションAPIは実装されていません。

## モジュールローダー

ESモジュールローダーはファイルシステムを基準に相対インポートを解決しますが、バンドラーの慣例には対応していません。

- `node_modules`解決には対応していません。
- `package.json`の`exports`マップはありません。
- ファイル拡張子は推測されません（`import './foo'`ではなく`import './foo.mjs'`と記述する必要があります）。
- HTTPインポートには対応していません。

これはECMAScript仕様の基本形には一致しますが、Nodeの動作とは異なります。独自のモジュールリゾルバー用フックはありません。npmパッケージを使うには、esbuildなどのツールで単一のスクリプトまたはモジュールにバンドルしてから、Phasisに渡してください。

## Wasm

`WebAssembly`は実装されていません。バインド先となるPHPWasmランタイムがありません。

## 対応していないブラウザー専用Web API

Phasisには完全な**Web Platform Pack**（`URL`、`TextEncoder`/`TextDecoder`、`atob`/`btoa`、`structuredClone`、`performance`、`DOMException`）、完全な**Fetch Pack**（`fetch`、`Request`、`Response`、`Headers`、`Body`、`AbortController`/`AbortSignal`、`Blob`/`File`、`FormData`、`EventTarget`/`Event`、WHATWG Streams全機能、`navigator`）、さらに`crypto`（`getRandomValues`、`randomUUID`、`SubtleCrypto`全機能：digest、HMAC、AES-GCM/CBC/CTR、RSA-OAEP/PSS/PKCS1、ECDSA、ECDH、HKDF、PBKDF2）、`WebSocket`（コンストラクターとRFC 6455フレームコーデック、交換可能なトランスポート）、`XMLHttpRequest`（fetchトランスポート上に構築）、および実際のイベントループ（`setTimeout`、`setInterval`、`clearTimeout`、`clearInterval`、`queueMicrotask`、`AsyncContext`）が含まれます。[Web API](https://phasis.inline0.dev/ja/docs/compatibility/web-apis)を参照してください。

含まれないもの：

- `window`、`document`、DOMツリー。Phasisはブラウザーではありません。
- `localStorage`、`sessionStorage`、`IndexedDB`。ホスト側の責任範囲であり、永続化は埋め込み側が担います。
- `Worker`、`SharedWorker`、`MessageChannel`。実際のOSスレッドが必要ですが、PHPにはありません。
- Service Workers、Push API、Notifications、BroadcastChannel。ブラウザー以外では用途がありません。

## Nodeのグローバル変数

`process`、`Buffer`、`__dirname`、`__filename`、`require()`も、どれも存在しません。これらはNodeホストの慣例であり、言語機能ではありません。

Nodeのコードを移植する場合は、`require('foo')`を`import 'foo'`に置き換え、`process.env.X`をホストにバインドされた`env.X`に差し替え、PHPから`__dirname`相当のパスを渡してください。

## 小数の精度

ECMAScriptの数値はIEEE 754倍精度浮動小数点数です。有効桁数が15桁を超える十進演算では、ほかのすべてのJSエンジンと同様に精度が失われます。整数を正確に扱うには`BigInt`を使い、端数も正確に扱う必要がある場合はJSの十進数ライブラリを使ってください。

PHPの`bcmath`は`BigInt`に内部で使われます。V8との実質的な違いは、非常に大きなbigint演算が、V8のC++実装よりPHPでは遅いことです。数値の正確さは同一です。
