Treci la conținut

Phasis

Un motor JavaScript scris în PHP: ES2024+ trece toate cele 50 506 teste test262 (instantaneu 2025-05-05), plus URL, codificare, structuredClone, fetch și Streams.

Terminal
composer require phasis/phasis

Cea mai recentă versiune v0.4.2 MIT PHP 8.2+, ext-bcmath, ext-curl, ext-mbstring

În practică

Un singur obiect motor rulează JavaScript în procesul PHP și transmite valori în ambele direcții.

Rulați JavaScript din PHP

Phasis\Engine evaluează șiruri sursă și fișiere în procesul PHP care îl apelează. setGlobal() transformă tablourile PHP în tablouri și obiecte JavaScript și încapsulează funcțiile anonime PHP ca funcții.

Ieșirea console.log este stocată temporar în motor și citită cu getConsoleOutput(). Formatorul din a doua filă nu are nevoie deloc de motor.

Motor
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"

PHP pur

Fără exec(), fără FFI, fără Node. Necesită PHP 8.2+ cu ext-curl, ext-bcmath și ext-mbstring; CI rulează PHP 8.4 și 8.5.

100% test262

Trece toate cele 50 506 teste ale suitei de conformitate ECMAScript din instantaneul 2025-05-05, în fiecare categorie, fără omisiuni.

ECMAScript modern

Clase, async/await, generatoare, Symbol, BigInt, Proxy, Temporal, TypedArray și Intl cu ext-intl. ES2024+ complet.

API-uri ale platformei web

URL, TextEncoder și TextDecoder, atob și btoa, structuredClone, performance și DOMException sunt incluse.

fetch + Streams

HTTP real din JS prin ext-curl. Întregul API Fetch, cu AbortSignal, Blob, FormData și WHATWG Streams.

Teste ale platformei web

Subtestele WPT importate pentru fetch, headers, blob, abort, streams și encoding trec, cu excepția unei liste de permisiuni pentru cazurile brotli și SharedArrayBuffer.

Interoperabilitate PHP ↔ JS

setGlobal() expune funcțiile anonime PHP ca funcții JS, iar call() execută funcțiile JS din PHP. Valorile sunt convertite la limită; tablourile sunt copiate.

Poate fi încorporat

O singură clasă Engine: eval, execFile, setGlobal, call. Se integrează în orice aplicație PHP sau CLI.

Limită pentru stiva de apeluri

O stivă de apeluri cu limită fixă de 4 096 cadre oprește recursivitatea fără sfârșit printr-o eroare InternalError care poate fi capturată.

CLI

bin/phasis execută un fișier sau un fragment -e și afișează AST-ul cu --ast. Într-un checkout al depozitului, bin/test262 rulează suita de conformitate.

Oracle Node.js

Scenariile sunt verificate cu Node.js (V8). WPT și suita bibliotecii rulează în CI la push-uri care ating motorul; testul complet test262 se rulează la cerere, ultima dată pe 2026-06-09.

Biblioteci reale

204 de pachete npm, printre care acorn, mustache.js, lodash și marked, sunt testate, iar rezultatele sunt identice la nivel de octet cu cele din Node.

De ce Phasis

Proces fără Node.js

Phasis analizează lexical, analizează sintactic și execută JavaScript în PHP însuși, fără apel exec() la Node și fără FFI. Se instalează ca pachet Composer.

fetch controlat de gazdă

fetch() folosește ext-curl în mod implicit. setFetchTransport() înlocuiește transportul, de exemplu cu o simulare în teste, iar setFetchPolicy() poate respinge sau rescrie fiecare solicitare înainte de trimitere.

Temporizatoare cu timp virtual

eval() golește bucla de evenimente înainte să returneze, iar ceasul sare la următorul temporizator în așteptare în loc să aștepte. Gazdele cu durată lungă pot rula bucla în timp real cu tickEventLoop().

Analizator sintactic și formator incluse

Analizatorul sintactic returnează un AST tipizat PHP care se exportă în ESTree. Formatorul reafișează JavaScript, JSON și CSS cu o structură compatibilă cu prettier.

Comparativ cu

Alte modalități de a rula sau procesa JavaScript dintr-o aplicație PHP.

Phasis în comparație cu alte instrumente
Node.js Potrivit pentruNode.js rulează JavaScript pe motorul V8 și rezolvă pachetele din directoarele node_modules, astfel încât dependențele npm se încarcă după nume. Diferența față de PhasisApelarea Node din PHP adaugă un al doilea mediu de execuție și o limită de subproces. Phasis rulează în PHP, însă încărcătorul de module nu are node_modules sau rezolvarea exporturilor package.json, așa că pachetele npm trebuie mai întâi incluse într-un pachet, de exemplu cu esbuild.
V8Js Potrivit pentruV8Js încorporează motorul V8 al lui Google în PHP și rulează JavaScript într-un mediu izolat care poate fi restricționat printr-o limită de timp și una de memorie. Diferența față de PhasisV8Js este o extensie compilată care necesită biblioteca libv8. Phasis este PHP simplu din Composer, iar documentația sa indică un timp de execuție de aproximativ 100 ori mai mare decât V8 pentru cod limitat de distribuirea apelurilor.
Peast Potrivit pentruPeast analizează JavaScript într-un AST ESTree pe PHP 5.4 și versiunile ulterioare și adaugă parcurgerea arborelui, interogări cu selectori și redare. Diferența față de PhasisPhasis necesită PHP 8.2. Analizatorul său sintactic returnează obiecte nod tipizate, doar pentru citire, cu export ESTree, iar același pachet poate și executa codul.
Prettier Potrivit pentruPrettier formatează JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML și altele și se instalează din npm. Diferența față de PhasisFormatorul Phasis acceptă doar JavaScript, JSON și CSS. Opțiunile sale corespund celor din prettier 3.x și rulează în PHP, fără Node.js.

Întrebări și răspunsuri

Răspunsuri scurte din documentația Phasis.

Începeți cu ghidul de inițiere, apoi consultați referința API pentru hook-urile de fetch și bucla de evenimente.