Phasis
Engine JavaScript yang ditulis dalam PHP: lulus semua tes 50.506 test262 ES2024+ (snapshot 2025-05-05), ditambah URL, encoding, structuredClone, fetch, dan Streams.
composer require phasis/phasisRilis terbaru v0.4.2 MIT PHP 8.2+, ext-bcmath, ext-curl, ext-mbstring
./vendor/bin/phasis -e '1 + 2 * 3'
# 7
./vendor/bin/phasis -e '[1, 2, 3].map(x => x * x).join(",")'
# 1,4,9
./vendor/bin/phasis path/to/script.jsDalam praktik
Satu objek engine menjalankan JavaScript di dalam proses PHP dan meneruskan nilai ke kedua arah.
Jalankan JavaScript dari PHP
Phasis\Engine mengevaluasi string sumber dan file dalam proses PHP yang memanggilnya. setGlobal() mengubah array PHP menjadi array dan objek JavaScript, serta membungkus closure PHP sebagai fungsi.
Keluaran console.log disangga di engine dan dibaca kembali dengan getConsoleOutput(). Formatter di tab kedua sama sekali tidak memerlukan engine.
use Phasis\Engine;
$engine = new Engine();
// Evaluate an expression
$engine->eval('1 + 2 * 3'); // 7
// Run a file
$engine->execFile('/path/to/script.js');
// Bridge a PHP value into JS (arrays are copied)
$engine->setGlobal('config', ['debug' => true]);
$engine->eval('config.debug'); // true
// console.log is buffered, not printed
$engine->eval('console.log("hi")');
echo $engine->getConsoleOutput(); // hi
// Expose a PHP closure as a JS function
$engine->setGlobal('greet', fn(string $name) => "Hello, $name");
$engine->eval('greet("world")'); // "Hello, world"use Phasis\Formatter\Formatter;
use Phasis\Formatter\FormatOptions;
$formatted = Formatter::formatSource(
"const a={x:1,y:2};",
'script',
new FormatOptions(useTabs: true, singleQuote: true),
);
// "const a = { x: 1, y: 2 };\n"PHP Murni
Tanpa exec(), tanpa FFI, tanpa Node. Memerlukan PHP 8.2+ dengan ext-curl, ext-bcmath, dan ext-mbstring; CI menjalankan PHP 8.4 dan 8.5.
100% test262
Lulus seluruh 50.506 tes rangkaian uji kesesuaian ECMAScript pada snapshot 2025-05-05, di setiap kategori tanpa ada yang dilewati.
ECMAScript Modern
Class, async/await, generator, Symbol, BigInt, Proxy, Temporal, TypedArray, dan Intl dengan ext-intl. ES2024+ lengkap.
API Platform Web
URL, TextEncoder dan TextDecoder, atob dan btoa, structuredClone, performance, serta DOMException sudah tersedia secara bawaan.
fetch + Streams
HTTP sungguhan dari JS melalui ext-curl. Fetch API lengkap dengan AbortSignal, Blob, FormData, dan WHATWG Streams.
Tes Platform Web
Subtes WPT yang diimpor untuk fetch, headers, blob, abort, streams, dan encoding lulus, kecuali kasus brotli dan SharedArrayBuffer yang masuk daftar izin.
Interop PHP ↔ JS
setGlobal() mengekspos closure PHP sebagai fungsi JS, dan call() menjalankan fungsi JS dari PHP. Nilai dikonversi pada batas; array disalin.
Dapat disematkan
Satu class Engine: eval, execFile, setGlobal, call. Sematkan di aplikasi PHP atau CLI mana pun.
Batas Call Stack
Call stack tetap sebanyak 4.096 frame menghentikan rekursi tak terkendali dengan InternalError yang dapat ditangkap.
CLI
bin/phasis menjalankan file atau cuplikan -e dan mencetak AST dengan --ast. Dalam checkout repositori, bin/test262 menjalankan rangkaian uji kesesuaian.
Oracle Node.js
Skenario diperiksa terhadap Node.js (V8). WPT dan rangkaian uji library dijalankan di CI pada push yang menyentuh engine; uji test262 lengkap dijalankan sesuai kebutuhan, terakhir pada 2026-06-09.
Library Sungguhan
Sebanyak 204 paket npm, termasuk acorn, mustache.js, lodash, dan marked, diuji dengan keluaran yang identik byte demi byte dengan Node.
Mengapa Phasis
Tanpa proses Node.js
Phasis melakukan leksing, parsing, dan eksekusi JavaScript di dalam PHP itu sendiri, tanpa panggilan exec() ke Node dan tanpa FFI. Instalasinya berupa paket Composer.
fetch dikendalikan host
fetch() menggunakan ext-curl secara default. setFetchTransport() mengganti transport, misalnya dengan mock untuk pengujian, dan setFetchPolicy() dapat menolak atau menulis ulang setiap permintaan sebelum dikirim.
Timer berdasarkan waktu virtual
eval() menguras event loop sebelum kembali, dan jam melompat ke timer tertunda berikutnya alih-alih menunggu. Host yang berjalan lama dapat menggerakkan loop dalam waktu nyata dengan tickEventLoop().
Parser dan formatter sudah disertakan
Parser mengembalikan AST PHP bertipe yang dapat diekspor ke ESTree. Formatter mencetak ulang JavaScript, JSON, dan CSS dengan tata letak yang kompatibel dengan prettier.
Dibandingkan dengan
Cara lain untuk menjalankan atau memproses JavaScript dari aplikasi PHP.
| Alat | Keunggulan | Perbedaan dengan Phasis |
|---|---|---|
| Node.js | KeunggulanNode.js menjalankan JavaScript di engine V8 dan menyelesaikan paket dari folder node_modules, sehingga dependensi npm dimuat berdasarkan nama. | Perbedaan dengan PhasisMemanggil Node dari PHP menambahkan runtime kedua dan batas subprocess. Phasis berjalan di dalam PHP, tetapi pemuat modulnya tidak memiliki node_modules atau resolusi ekspor package.json, sehingga paket npm harus dibundel lebih dulu, misalnya dengan esbuild. |
| V8Js | KeunggulanV8Js menyematkan engine V8 milik Google di PHP dan menjalankan JavaScript dalam sandbox yang dapat dibatasi dengan batas waktu dan memori. | Perbedaan dengan PhasisV8Js adalah ekstensi terkompilasi yang memerlukan library libv8. Phasis adalah PHP murni dari Composer, dan dokumentasinya menyebut waktu jalan sekitar 100 kali waktu V8 pada kode yang dibatasi dispatch. |
| Peast | KeunggulanPeast mengurai JavaScript menjadi AST ESTree pada PHP 5.4 dan versi lebih baru, serta menyediakan traversal tree, kueri selector, dan rendering. | Perbedaan dengan PhasisPhasis memerlukan PHP 8.2. Parsernya mengembalikan objek node bertipe yang hanya dapat dibaca dengan ekspor ESTree, dan paket yang sama juga dapat menjalankan kode. |
| Prettier | KeunggulanPrettier memformat JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML, dan lainnya, serta diinstal dari npm. | Perbedaan dengan PhasisFormatter Phasis hanya mendukung JavaScript, JSON, dan CSS. Opsinya mengikuti prettier 3.x dan berjalan di PHP, tanpa Node.js. |
Tanya jawab
Jawaban singkat dari dokumentasi Phasis.
Composer memerlukan PHP 8.2 atau lebih baru dengan bcmath, curl, dan mbstring. intl disarankan untuk API Intl dan kalender Temporal non-ISO, serta openssl untuk enkripsi AES di crypto.subtle.
Phasis adalah interpreter tree-walking dengan VM bytecode, bukan JIT. Dokumentasinya menyebut waktu jalan sekitar 100 kali waktu V8 pada kode yang dibatasi dispatch; batas ini jarang berpengaruh untuk pekerjaan penyematan seperti aturan validasi.
Tidak berdasarkan nama. Pemuat modul menyelesaikan impor berdasarkan sistem file, memerlukan ekstensi file eksplisit, dan tidak mendukung node_modules atau ekspor package.json, jadi bundel paket dengan alat seperti esbuild dan berikan bundelnya kepada Phasis.
Tidak. window, document, dan tree DOM tidak disertakan, begitu pula global Node seperti process, Buffer, dan require().
Keluaran disangga di engine, bukan dicetak. Baca dengan getConsoleOutput() atau getConsoleLines(), lalu kosongkan buffer dengan clearConsole().
Throw yang tidak tertangkap muncul sebagai Phasis\Exceptions\JsThrowable. Error yang dihasilkan engine sendiri, seperti membaca properti null, muncul sebagai Phasis\Exceptions\TypeError, ReferenceError, atau RangeError, dan semuanya merupakan turunan Phasis\Exceptions\RuntimeError. Sumber yang tidak valid melempar Phasis\Parser\ParseError, sebuah Phasis\Exceptions\SyntaxError, beserta baris, kolom, dan offsetnya.
Mulailah dengan panduan memulai, lalu baca referensi API untuk hook fetch dan event loop.