Phasis
JavaScript variklis, parašytas PHP: ES2024+ išlaiko visus 50 506 test262 testus (2025-05-05 momentinė kopija), taip pat palaiko URL, kodavimą, structuredClone, fetch ir Streams.
composer require phasis/phasisNaujausia versija 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.jsPraktinis pritaikymas
Vienas variklio objektas vykdo JavaScript PHP procese ir perduoda reikšmes abiem kryptimis.
Vykdykite JavaScript iš PHP
Phasis\Engine įvertina šaltinio eilutes ir failus jį iškviečiančiame PHP procese. setGlobal() paverčia PHP masyvus į JavaScript masyvus bei objektus ir apgaubia PHP uždarinius kaip funkcijas.
console.log išvestis kaupiama variklyje, o nuskaitoma naudojant getConsoleOutput(). Antrame skirtuke esantis formatuoklis variklio visai nenaudoja.
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"Grynai PHP
Nenaudojama exec(), FFI ar Node. Reikalinga PHP 8.2+ su ext-curl, ext-bcmath ir ext-mbstring; CI vykdomas su PHP 8.4 ir 8.5.
100% test262
Išlaiko visus ECMAScript atitikties rinkinio 50 506 testus pagal 2025-05-05 momentinę kopiją: visose kategorijose, be praleistų testų.
Šiuolaikinis ECMAScript
Klasės, async/await, generatoriai, Symbol, BigInt, Proxy, Temporal, TypedArray ir Intl su ext-intl. Pilnas ES2024+.
Žiniatinklio platformos API
URL, TextEncoder ir TextDecoder, atob ir btoa, structuredClone, performance bei DOMException jau įtraukti.
fetch + Streams
Tikras HTTP iš JS naudojant ext-curl. Pilnas Fetch API su AbortSignal, Blob, FormData ir WHATWG Streams.
Žiniatinklio platformos testai
Importuoti WPT daliniai testai, skirti fetch, headers, blob, abort, streams ir encoding, išlaikomi, išskyrus į leidžiamų išimčių sąrašą įtrauktus brotli ir SharedArrayBuffer atvejus.
PHP ↔ JS sąveikumas
setGlobal() atskleidžia PHP uždarinius kaip JS funkcijas, o call() vykdo JS funkcijas iš PHP. Reikšmės konvertuojamos ties riba; masyvai kopijuojami.
Įterpiamas
Viena Engine klasė: eval, execFile, setGlobal, call. Įtraukite ją į bet kurią PHP programą arba CLI.
Iškvietimų dėklo riba
Fiksuoto dydžio, 4 096 kadrų iškvietimų dėklas sustabdo nevaldomą rekursiją ir leidžia pagauti InternalError.
CLI
bin/phasis vykdo failą arba -e fragmentą ir išveda AST naudodamas --ast. Saugyklos kopijoje bin/test262 vykdo atitikties testų rinkinį.
Node.js etalonas
Scenarijai tikrinami pagal Node.js (V8). WPT ir bibliotekos testų rinkinys CI vykdomi po pakeitimų, susijusių su varikliu; visas test262 testų rinkinys vykdomas pagal poreikį, paskutinį kartą – 2026-06-09.
Tikros bibliotekos
Testuojami 204 npm paketai, tarp jų acorn, mustache.js, lodash ir marked; jų išvestis baitas po baito sutampa su Node.
Kodėl Phasis
Nėra atskiro Node.js proceso
Phasis pats analizuoja ir vykdo JavaScript, nenaudodamas PHP, be jokio exec() kvietimo į Node ir be FFI. Jis įdiegiamas kaip Composer paketas.
fetch valdo pagrindinė programa
fetch() pagal numatytuosius nustatymus naudoja ext-curl. setFetchTransport() pakeičia transportą, pavyzdžiui, testuose naudojamu bandomuoju, o setFetchPolicy() gali uždrausti arba perrašyti kiekvieną užklausą prieš ją išsiunčiant.
Laikmačiai pagal virtualųjį laiką
eval() ištuština įvykių ciklą prieš grįždama, o laikrodis peršoka prie kito laukiančio laikmačio, užuot laukęs. Ilgai veikiantys pagrindiniai procesai gali vykdyti ciklą realiuoju laiku naudodami tickEventLoop().
Įtraukti analizatorius ir formatuoklis
Analizatorius grąžina tipizuotą PHP AST, kurį galima eksportuoti į ESTree. Formatuoklis iš naujo suformatuoja JavaScript, JSON ir CSS pagal prettier suderinamą išdėstymą.
Palyginimas su
Kiti būdai vykdyti arba apdoroti JavaScript iš PHP programos.
| Įrankis | Stipriosios pusės | Skirtumas nuo Phasis |
|---|---|---|
| Node.js | Stipriosios pusėsNode.js vykdo JavaScript naudodamas V8 variklį ir ieško paketų node_modules aplankuose, todėl npm priklausomybes galima įkelti pagal pavadinimą. | Skirtumas nuo PhasisKviečiant Node iš PHP, atsiranda antra vykdymo aplinka ir posistemio proceso riba. Phasis veikia PHP aplinkoje, tačiau jo modulių įkėliklis nepalaiko node_modules ir package.json eksportų paieškos, todėl npm paketus pirmiausia reikia sujungti, pavyzdžiui, naudojant esbuild. |
| V8Js | Stipriosios pusėsV8Js įterpia Google V8 variklį į PHP ir vykdo JavaScript smėlio dėžėje, kurios veikimą galima apriboti laiko ir atminties limitais. | Skirtumas nuo PhasisV8Js yra kompiliuojamas plėtinys, kuriam reikia libv8 bibliotekos. Phasis yra paprastas PHP iš Composer, o dokumentacijoje nurodoma, kad su dispečeriniu kodu jis veikia maždaug 100 kartų lėčiau nei V8. |
| Peast | Stipriosios pusėsPeast analizuoja JavaScript ir sukuria ESTree AST, naudodama PHP 5.4 ar naujesnę versiją, taip pat suteikia medžio perėjimo, parinkimo užklausų ir atvaizdavimo galimybes. | Skirtumas nuo PhasisPhasis reikia PHP 8.2. Jo analizatorius grąžina tipizuotus, tik skaityti skirtus mazgų objektus su ESTree eksportu, o tas pats paketas taip pat gali vykdyti kodą. |
| Prettier | Stipriosios pusėsPrettier formatuoja JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML ir dar daugiau, o įdiegiamas iš npm. | Skirtumas nuo PhasisPhasis formatuoklis palaiko tik JavaScript, JSON ir CSS. Jo parinktys atitinka prettier 3.x, jis veikia PHP aplinkoje ir neturi Node.js. |
Klausimai ir atsakymai
Trumpi atsakymai iš Phasis dokumentacijos.
Composer reikia PHP 8.2 ar naujesnės versijos su bcmath, curl ir mbstring. Intl API ir ne-ISO Temporal kalendoriams rekomenduojamas intl, o AES šifravimui crypto.subtle – openssl.
Phasis yra medį pereinantis interpretatorius su baitkodžio VM, o ne JIT. Dokumentacijoje nurodoma, kad su dispečeriniu kodu jis veikia maždaug 100 kartų lėčiau nei V8; anot jos, šis apribojimas retai svarbus integravimo darbams, pavyzdžiui, tikrinimo taisyklėms.
Pagal pavadinimą – ne. Modulių įkėliklis importų ieško failų sistemoje, reikalauja aiškiai nurodyti failų plėtinius ir nepalaiko node_modules bei package.json eksportų, todėl paketą sujunkite naudodami, pavyzdžiui, esbuild, ir perduokite Phasis sujungtą failą.
Ne. window, document ir DOM medis nepateikiami, kaip ir Node globalieji objektai, tokie kaip process, Buffer ir require().
Ji kaupiama variklyje, o ne išvedama į ekraną. Nuskaitykite ją naudodami getConsoleOutput() arba getConsoleLines(), o buferį išvalykite su clearConsole().
Neapdorotas išmetimas pateikiamas kaip Phasis\Exceptions\JsThrowable. Pačios variklio sukeltos klaidos, pavyzdžiui, bandant nuskaityti null savybę, pateikiamos kaip Phasis\Exceptions\TypeError, ReferenceError arba RangeError; visos jos išplečia Phasis\Exceptions\RuntimeError. Netinkamas šaltinio kodas išmeta Phasis\Parser\ParseError – Phasis\Exceptions\SyntaxError su eilutės, stulpelio ir poslinkio informacija.
Pradėkite nuo darbo pradžios vadovo, tada perskaitykite API žinyną, kuriame aprašyti fetch kabliai ir įvykių ciklas.