Phasis
Engine JavaScript napísaný v PHP: ES2024+ a úspešné absolvovanie všetkých testov 50,506 test262 (stav k 2025-05-05), plus URL, kódovanie, structuredClone, fetch a Streams.
composer require phasis/phasisNajnovšie vydanie 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.jsV praxi
Jeden objekt enginu spúšťa JavaScript v procese PHP a prenáša hodnoty oboma smermi.
Spúšťanie JavaScript z PHP
Phasis\Engine vyhodnocuje zdrojové reťazce a súbory v procese PHP, ktorý ho zavolá. setGlobal() premieňa polia PHP na polia a objekty JavaScript a uzávery PHP obaľuje ako funkcie.
Výstup console.log sa ukladá do vyrovnávacej pamäte enginu a číta sa pomocou getConsoleOutput(). Formátovač na druhej karte engine vôbec nepotrebuje.
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"Čisté PHP
Bez exec() a FFI, bez Node. Vyžaduje PHP 8.2+ s ext-curl, ext-bcmath a ext-mbstring; CI používa PHP 8.4 a 8.5.
100% test262
Prechádza všetkými testami 50,506 v súbore testov zhody so štandardom ECMAScript v stave k 2025-05-05, vo všetkých kategóriách, bez vynechaných testov.
Moderný ECMAScript
Triedy, async/await, generátory, Symbol, BigInt, Proxy, Temporal, TypedArray a Intl s ext-intl. Plná podpora ES2024+.
Rozhrania webovej platformy
Zabudované sú URL, TextEncoder a TextDecoder, atob a btoa, structuredClone, performance a DOMException.
fetch a Streams
Skutočné HTTP z JS cez ext-curl. Plné API Fetch s AbortSignal, Blob, FormData a WHATWG Streams.
Testy webovej platformy
Importované podtesty WPT pre fetch, headers, blob, abort, streams a encoding prechádzajú, s výnimkou zoznamu prípadov brotli a SharedArrayBuffer.
Interop PHP ↔ JS
setGlobal() sprístupňuje uzávery PHP ako funkcie JS a call() spúšťa funkcie JS z PHP. Hodnoty sa konvertujú na hranici; polia sa kopírujú.
Možnosť vloženia
Jedna trieda Engine: eval, execFile, setGlobal, call. Možno ju vložiť do ľubovoľnej aplikácie PHP alebo CLI.
Limit zásobníka volaní
Pevný zásobník volaní s kapacitou 4,096 rámcov zastaví nekonečnú rekurziu a vyvolá zachytiteľnú chybu InternalError.
CLI
bin/phasis spustí súbor alebo úryvok zadaný pomocou -e a vypíše AST pomocou --ast. V kópii repozitára spustí bin/test262 testovaciu súpravu zhody so štandardom.
Referenčný nástroj Node.js
Scenáre sa overujú oproti Node.js (V8). WPT a testy knižnice sa spúšťajú v CI pri zmenách zasahujúcich engine; úplný beh test262 sa spúšťa na požiadanie, naposledy 2026-06-09.
Skutočné knižnice
Testuje sa 204 balíkov npm vrátane acorn, mustache.js, lodash a marked; ich výstup je bajtovo zhodný s Node.
Prečo Phasis
Bez procesu Node.js
Phasis analyzuje lexikálne, syntakticky spracúva a vykonáva JavaScript priamo v PHP bez exec() volania Node a bez FFI. Inštaluje sa ako balík Composer.
fetch pod kontrolou hostiteľa
fetch() štandardne používa ext-curl. setFetchTransport() vymení prenos, napríklad za napodobeninu pri testovaní, a setFetchPolicy() môže každú požiadavku pred odoslaním zamietnuť alebo upraviť.
Časovače podľa virtuálneho času
eval() pred návratom vyprázdni slučku udalostí a hodiny preskočia na najbližší čakajúci časovač namiesto čakania. Dlhodobo bežiace hostiteľské aplikácie môžu riadiť slučku v reálnom čase pomocou tickEventLoop().
Parser a formátovač v jednom
Parser vracia typovaný AST PHP, ktorý možno exportovať do formátu ESTree. Formátovač znovu formátuje JavaScript, JSON a CSS v rozložení kompatibilnom s prettier.
V porovnaní s
Ďalšie možnosti spúšťania alebo spracovania JavaScript z aplikácie PHP.
| Nástroj | V čom vyniká | Rozdiel oproti Phasis |
|---|---|---|
| Node.js | V čom vynikáNode.js spúšťa JavaScript v engine V8 a vyhľadáva balíky v priečinkoch node_modules, takže závislosti npm sa načítajú podľa názvu. | Rozdiel oproti PhasisVolanie Node z PHP pridáva druhé runtime prostredie a hranicu podprocesu. Phasis beží v rámci PHP, ale jeho načítavač modulov nepodporuje node_modules ani rozlíšenie exportov package.json, preto sa balíky npm najprv zabalia, napríklad pomocou esbuild. |
| V8Js | V čom vynikáV8Js vkladá engine V8 od Google do PHP a spúšťa JavaScript v izolovanom prostredí, ktorého možnosti možno obmedziť časovým limitom a limitom pamäte. | Rozdiel oproti PhasisV8Js je skompilované rozšírenie, ktoré potrebuje knižnicu libv8. Phasis je čisté PHP od Composer a jeho dokumentácia uvádza, že pri kóde závislom od spracovania volaní má približne 100-násobný čas vykonávania oproti V8. |
| Peast | V čom vynikáPeast analyzuje JavaScript a vytvára AST vo formáte ESTree v PHP 5.4 a novších verziách; pridáva prechádzanie stromom, dotazy pomocou selektorov a vykresľovanie. | Rozdiel oproti PhasisPhasis potrebuje PHP 8.2. Jeho analyzátor vracia typované objekty uzlov iba na čítanie s exportom ESTree a ten istý balík dokáže kód aj spúšťať. |
| Prettier | V čom vynikáPrettier formátuje JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML a ďalšie formáty; inštaluje sa z npm. | Rozdiel oproti PhasisFormátovač Phasis podporuje iba JavaScript, JSON a CSS. Jeho možnosti kopírujú 3.x nástroja prettier a beží v PHP bez Node.js. |
Otázky a odpovede
Stručné odpovede z dokumentácie Phasis.
Composer vyžaduje PHP 8.2 alebo novšiu verziu s rozšíreniami bcmath, curl a mbstring. Rozšírenie intl sa odporúča pre rozhrania Intl API a kalendáre, ktoré nie sú ISO Temporal; openssl je potrebný na šifrovanie AES v crypto.subtle.
Phasis je interpret, ktorý prechádza strom a používa virtuálny stroj s bajtkódom, nejde o JIT. Dokumentácia uvádza, že pri kóde závislom od spracovania volaní má približne 100-násobný čas vykonávania oproti V8; podľa nej tento limit pri vkladaní, napríklad na účely validačných pravidiel, zvyčajne neprekáža.
Nie podľa názvu. Načítavač modulov vyhľadáva importy v súborovom systéme, vyžaduje explicitné prípony súborov a nepodporuje node_modules ani exporty package.json, preto balík zabaľte pomocou nástroja, ako je esbuild, a odovzdajte Phasis výsledný balík.
Nie. Neobsahuje window, document ani strom DOM a nie sú v ňom ani globálne objekty Node, napríklad process, Buffer a require().
Ukladá sa do vyrovnávacej pamäte enginu namiesto toho, aby sa vypísal. Prečítajte ho pomocou getConsoleOutput() alebo getConsoleLines() a vyprázdnite vyrovnávaciu pamäť pomocou clearConsole().
Nezachytená výnimka sa prejaví ako Phasis\Exceptions\JsThrowable. Chyby, ktoré vyvolá samotný engine, napríklad pri čítaní vlastnosti hodnoty null, sa prejavia ako Phasis\Exceptions\TypeError, ReferenceError alebo RangeError a všetky sú odvodené od Phasis\Exceptions\RuntimeError. Neplatný zdrojový kód vyvolá Phasis\Parser\ParseError, teda Phasis\Exceptions\SyntaxError s uvedením riadka, stĺpca a pozície.
Začnite sprievodcom pre začiatočníkov a potom si prečítajte referenčnú príručku API o obslužných funkciách fetch a slučke udalostí.