Phasis
PHP nyelven írt JavaScript motor: ES2024+; az összes 50 506 test262 teszt sikeres (2025-05-05-ös pillanatkép), továbbá URL, kódolás, structuredClone, fetch és Streams.
composer require phasis/phasisLegújabb kiadás 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.jsA gyakorlatban
Egy motorobjektum futtatja a JavaScript-t a PHP folyamaton belül, és mindkét irányban továbbít értékeket.
PHP-ból futtatható: JavaScript
A Phasis\Engine forrásszövegeket és fájlokat értékel ki az azt meghívó PHP folyamatban. A setGlobal() a PHP tömböket JavaScript tömbökké és objektumokká alakítja, a PHP closure-öket pedig függvényként burkolja be.
A console.log kimenetét a motor puffereli, majd a getConsoleOutput() segítségével olvashatja vissza. A második fül formázójához egyáltalán nincs szükség motorra.
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"Tisztán PHP-alapú
Nincs exec(), FFI vagy Node. PHP 8.2+ szükséges ext-curl, ext-bcmath és ext-mbstring bővítménnyel; a CI PHP 8.4 és 8.5 verzióval fut.
100% test262
Az ECMAScript-megfelelőségi tesztcsomag összes 50 506 tesztje sikeres a 2025-05-05-ös pillanatképen, minden kategóriában, kihagyás nélkül.
Modern ECMAScript
Osztályok, async/await, generátorok, Symbol, BigInt, Proxy, Temporal, TypedArray és Intl ext-intl-lel. Teljes ES2024+.
Webplatform-API-k
A URL, a TextEncoder és a TextDecoder, az atob és a btoa, a structuredClone, a performance és a DOMException beépítve érhető el.
fetch + Streams
Valódi HTTP a JS felől, ext-curl használatával. Teljes Fetch API AbortSignal, Blob, FormData és WHATWG Streams támogatással.
Webplatform-tesztek
A fetchhez, headerekhez, blobhoz, megszakításhoz, streameléshez és kódoláshoz tartozó importált WPT-alegységtesztek sikeresek, a brotli- és SharedArrayBuffer-esetek engedélyezési listáját kivéve.
PHP ↔ JS együttműködés
A setGlobal() a PHP closure-öket JS függvényként teszi elérhetővé, a call() pedig JS függvényeket futtat PHP-ból. Az értékek a határfelületen konvertálódnak; a tömbök másolatként kerülnek átadásra.
Beágyazható
Egyetlen Engine osztály: eval, execFile, setGlobal, call. Illessze bármely PHP alkalmazásba vagy CLI-be.
Hívásverem-korlát
A rögzített, 4 096 keretből álló hívásverem elkapással kezelhető InternalError hibával állítja meg az elszabaduló rekurziót.
CLI
A bin/phasis fájlt vagy -e kódrészletet futtat, és a --ast kapcsolóval kiírja az AST-t. A repository klónozott példányában a bin/test262 futtatja a megfelelőségi teszteket.
Node.js oracle
A forgatókönyveket a Node.js (V8) alapján ellenőrzi. A WPT és a könyvtár tesztcsomagja a motort érintő pushoknál fut a CI-ben; a teljes test262 tesztfuttatás igény szerint indul, legutóbb 2026-06-09-én futott.
Valódi könyvtárak
A 204 npm csomagot, köztük az acornt, a mustache.js-t, a lodash-t és a markedet Node-dal bájtról bájtra azonos kimenettel tesztelik.
Miért Phasis?
Nincs Node.js folyamat
A Phasis JavaScript-t elemez és hajt végre közvetlenül PHP-ban, Node-hoz intézett exec() hívás és FFI nélkül. Composer csomagként telepíthető.
A fetchet a gazdagép vezérli
A fetch() alapértelmezés szerint ext-curlt használ. A setFetchTransport() lecseréli az átviteli réteget, például tesztekhez használt mockra, a setFetchPolicy() pedig minden kérést elutasíthat vagy átírhat, mielőtt az elküldésre kerül.
Időzítők virtuális időben
A eval() visszatérés előtt kiüríti az eseményhurkot, az óra pedig alvás helyett a következő függőben lévő időzítőre ugrik. A hosszan futó gazdafolyamatok valós időben is vezérelhetik a hurkot a tickEventLoop() használatával.
Beépített parser és formázó
A parser típusozott PHP AST-t ad vissza, amely ESTree formátumba exportálható. A formázó prettier-kompatibilis elrendezéssel újra kiírja a JavaScript, JSON és CSS elemeket.
Összehasonlítás
Más lehetőségek a PHP alkalmazásból történő JavaScript-futtatásra vagy -feldolgozásra.
| Eszköz | Amiben jó | Különbségek Phasis-hoz képest |
|---|---|---|
| Node.js | Amiben jóA Node.js a V8 motoron futtatja a JavaScript-t, és a node_modules könyvtárakból oldja fel a csomagokat, így a npm függőségek név alapján betölthetők. | Különbségek Phasis-hoz képestHa a PHP a Node-ot hívja meg, az egy második futtatókörnyezetet és alfolyamat-határt jelent. A Phasis a PHP környezetben fut, de a modulbetöltője nem kezeli a node_modules könyvtárat és a package.json exportfeloldást, ezért a npm csomagokat előbb össze kell csomagolni, például esbuilddel. |
| V8Js | Amiben jóA V8Js beágyazza a Google V8 motorját a PHP környezetbe, és a JavaScript-t olyan homokozóban futtatja, amely idő- és memóriakorláttal szabályozható. | Különbségek Phasis-hoz képestA V8Js egy lefordított bővítmény, amelyhez libv8 könyvtár szükséges. A Phasis egyszerű PHP a Composer környezetből; dokumentációja szerint diszpécselés-korlátos kód esetén nagyjából 100-szer annyi ideig fut, mint a V8. |
| Peast | Amiben jóA Peast a JavaScript kódot ESTree AST-vé elemzi PHP 5.4-es vagy újabb verzióján, és bejárást, választólekérdezéseket, valamint renderelést biztosít. | Különbségek Phasis-hoz képestA Phasis működéséhez PHP 8.2 szükséges. Parserje típusozott, csak olvasható csomópontobjektumokat ad vissza, ESTree-exporttal; ugyanaz a csomag a kódot is futtathatja. |
| Prettier | Amiben jóA Prettier formázza a JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML fájlokat és másokat is, és a npm használatával telepíthető. | Különbségek Phasis-hoz képestA Phasis formázó csak a JavaScript, JSON és CSS elemeket kezeli. Beállításai a prettier 3.x opcióit követik, PHP környezetben fut, és nincs hozzá Node.js. |
Kérdések és válaszok
Rövid válaszok a Phasis dokumentációjából.
A Composer futtatásához PHP 8.2 vagy újabb verzió szükséges bcmath, curl és mbstring bővítménnyel. Az Intl API-khoz és a nem-ISO Temporal-naptárakhoz az intl, a crypto.subtle AES-titkosításához pedig az openssl ajánlott.
A Phasis egy AST-t bejáró értelmező bájtkód-VM-mel, nem JIT. A dokumentáció szerint diszpécselés-korlátos kód esetén a futásideje nagyjából 100-szerese a V8-ének; ez a felső határ a beágyazási feladatoknál, például validációs szabályoknál ritkán számít.
Név alapján nem. A modulbetöltő a fájlrendszerben oldja fel az importokat, kifejezett fájlkiterjesztéseket igényel, és nem támogatja a node_modules könyvtárat vagy a package.json exportfeloldást. Csomagokat például esbuilddel kell összeállítani, majd átadni a Phasis-nek.
Nincs. A window, a document és a DOM-fa nem része a csomagnak; a Node globálisai, például a process, a Buffer és a require() sem.
A kimenet a motor pufferébe kerül, nem a terminálra. Olvassa ki a getConsoleOutput() vagy a getConsoleLines() segítségével, a puffer ürítéséhez pedig használja a clearConsole()-t.
Az el nem kapott kivétel Phasis\Exceptions\JsThrowable formájában jelenik meg. A motor által okozott hibák, például egy null érték tulajdonságának olvasása, Phasis\Exceptions\TypeError, ReferenceError vagy RangeError formájában jelennek meg, és mindegyik az Phasis\Exceptions\RuntimeError kiterjesztése. A hibás forrás Phasis\Parser\ParseError hibát dob, egy Phasis\Exceptions\SyntaxError-t, a sor, az oszlop és az offset megadásával.
Kezdje a kezdő útmutatóval, majd olvassa el a API referenciát a fetch-hookokról és az eseményhurokról.