Phasis
JavaScript-moottori, joka on kirjoitettu kielellä PHP: ES2024+ läpäisee kaikki 50,506 test262 -testit (tilannekuva 2025-05-05) sekä sisältää ominaisuudet URL, koodaus, structuredClone, fetch ja Streams.
composer require phasis/phasisUusin julkaisu 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.jsKäytännössä
Yksi moottoriolio suorittaa JavaScript:n PHP-prosessin sisällä ja välittää arvoja molempiin suuntiin.
Suorita JavaScript kohteesta PHP
Phasis\Engine arvioi lähdemerkkijonot ja tiedostot sitä kutsuvassa PHP-prosessissa. setGlobal() muuntaa PHP-taulukot JavaScript-taulukoiksi ja -olioiksi sekä käärii PHP-sulkeumat funktioiksi.
console.log-tuloste puskuroituu moottoriin, ja sen voi lukea takaisin komennolla getConsoleOutput(). Toisen välilehden muotoilija ei tarvitse moottoria lainkaan.
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"Pelkkää PHP-koodia
Ei exec():ää, FFI:tä eikä Nodea. Vaatii PHP 8.2+:n ja ext-curl-, ext-bcmath- sekä ext-mbstring-laajennukset; CI suoritetaan versioilla PHP 8.4 ja 8.5.
100 % test262
Läpäisee kaikki ECMAScript-yhteensopivuustestisarjan 50 506 testit 2025-05-05-tilannekuvassa: kaikki kategoriat, ei ohituksia.
Moderni ECMAScript
Luokat, async/await, generaattorit, Symbol, BigInt, Proxy, Temporal, TypedArray ja Intl ext-intl:n kanssa. Täysi ES2024+.
Web-alustan rajapinnat
URL, TextEncoder ja TextDecoder, atob ja btoa, structuredClone, performance ja DOMException sisältyvät.
fetch + Streams
Oikeat HTTP-pyynnöt kohteesta JS ext-curlin kautta. Täysi Fetch-API AbortSignalilla, Blobilla, FormDatalla ja WHATWG Streamsilla.
Web-alustan testit
fetchin, headersin, blobin, abortin, streamien ja koodauksen tuodut WPT-alitestit läpäistään, lukuun ottamatta brotli- ja SharedArrayBuffer-tapausten sallittujen listaa.
PHP ↔ JS-yhteentoimivuus
setGlobal() tarjoaa PHP-sulkeumat muodossa JS-funktiot, ja call() suorittaa JS-funktioita kohteesta PHP. Arvot muunnetaan rajapinnalla; taulukot kopioidaan.
Upotettava
Yksi Engine-luokka: eval, execFile, setGlobal, call. Lisää mihin tahansa PHP-sovellukseen tai CLI-ympäristöön.
Kutsupinon enimmäiskoko
Kiinteä 4 096-kehyksen kutsupino estää hallitsemattoman rekursion siepattavalla InternalError-virheellä.
CLI
bin/phasis suorittaa tiedoston tai -e-katkelman ja tulostaa AST:n valitsimella --ast. Koodivaraston checkoutissa bin/test262 suorittaa yhteensopivuustestisarjan.
Node.js-vertailuohjelma
Skenaariot tarkistetaan kohteeseen Node.js (V8) verraten. WPT ja kirjaston testisarja suoritetaan CI:ssä moottoria koskevissa push-tapahtumissa; koko test262-läpäisy suoritetaan pyynnöstä, viimeksi 2026-06-09.
Oikeat kirjastot
204 npm-pakettia, kuten acorn, mustache.js, lodash ja marked, testataan. Tulosteet ovat tavu tavulta identtisiä Noden tulosteiden kanssa.
Miksi Phasis
Ei Node.js-prosessia
Phasis jäsentää ja suorittaa JavaScript:n itse kohteessa PHP ilman exec()-kutsua Nodeen tai FFI:tä. Se asennetaan Composer-pakettina.
fetch isäntäohjelman hallinnassa
fetch() käyttää oletuksena ext-curliä. setFetchTransport() vaihtaa siirtotavan esimerkiksi testeissä käytettävään valepalveluun, ja setFetchPolicy() voi estää tai muokata jokaisen pyynnön ennen sen lähettämistä.
Ajastimet virtuaaliajassa
eval() tyhjentää tapahtumasilmukan ennen paluutaan, ja kello siirtyy seuraavan odottavan ajastimen aikaan nukkumisen sijaan. Pitkäikäiset isäntäohjelmat voivat ajaa silmukkaa reaaliajassa komennolla tickEventLoop().
Jäsennin ja muotoilija sisältyvät
Jäsennin palauttaa tyypitetyn PHP-AST:n, jonka voi viedä ESTree-muotoon. Muotoilija tulostaa JavaScript-, JSON- ja CSS-koodin uudelleen prettier-yhteensopivalla asettelulla.
Vertailu
Muita tapoja suorittaa tai käsitellä JavaScript:ta PHP-sovelluksesta käsin.
| Työkalu | Sopii hyvin | Ero kohteeseen Phasis |
|---|---|---|
| Node.js | Sopii hyvinNode.js suorittaa JavaScript:n V8-moottorissa ja etsii paketteja node_modules-kansioista, joten npm-riippuvuudet latautuvat nimensä perusteella. | Ero kohteeseen PhasisNoden kutsuminen kohteesta PHP lisää toisen suoritusympäristön ja aliohjelmarajan. Phasis suoritetaan kohteessa PHP, mutta sen moduulilataaja ei tunne node_modules-kansioita eikä package.json-vientien ratkaisua, joten npm-paketit täytyy ensin niputtaa esimerkiksi esbuildillä. |
| V8Js | Sopii hyvinV8Js upottaa Googlen V8-moottorin kohteeseen PHP ja suorittaa JavaScript:n hiekkalaatikossa, jota voi rajoittaa aika- ja muistirajoituksilla. | Ero kohteeseen PhasisV8Js on käännetty laajennus, joka tarvitsee libv8-kirjaston. Phasis on tavallista PHP:ta kohteesta Composer, ja sen dokumentaation mukaan sen suorittaminen kestää noin 100 kertaa kauemmin kuin V8n suoritus kutsunvälityssidonnaisessa koodissa. |
| Peast | Sopii hyvinPeast jäsentää JavaScript:n ESTree-AST:ksi versiolla PHP 5.4 tai uudemmalla sekä tarjoaa puun läpikäynnin, valitsinkyselyt ja renderöinnin. | Ero kohteeseen PhasisPhasis vaatii version PHP 8.2. Sen jäsennin palauttaa tyypitettyjä, vain luku -solmuolioita, jotka voi viedä ESTree-muotoon; sama paketti voi myös suorittaa koodia. |
| Prettier | Sopii hyvinPrettier muotoilee JavaScript-, TypeScript-, JSX-, CSS-, HTML-, Markdown-, YAML-koodia ja muuta, ja sen voi asentaa kohteesta npm. | Ero kohteeseen PhasisPhasis-muotoilija tukee vain JavaScript-, JSON- ja CSS-koodia. Sen asetukset vastaavat prettierin 3.x-asetuksia, ja se toimii kohteessa PHP ilman Node.js:ta. |
Kysymykset ja vastaukset
Lyhyet vastaukset Phasis-dokumentaatiosta.
Composer vaatii version PHP 8.2 tai uudemman sekä bcmath-, curl- ja mbstring-laajennukset. Intl-rajapintoja ja muita kuin ISO Temporal-kalentereita varten suositellaan intl-laajennusta, ja crypto.subtle:n AES-salausta varten openssl-laajennusta.
Phasis on puuta läpikäyvä tulkki, jossa on tavukoodivirtuaalikone, ei JIT-kääntäjä. Dokumentaation mukaan sen suoritusaika on kutsunvälityssidonnaisessa koodissa noin 100 kertaa V8:n suoritusaika; tämä yläraja on harvoin merkityksellinen upotustyössä, kuten validointisääntöjen käsittelyssä.
Ei nimen perusteella. Moduulilataaja ratkaisee tuonnit tiedostojärjestelmän perusteella, vaatii tiedostotunnisteet eikä tue node_modules-kansioita tai package.json-vientien ratkaisua. Niputa siis paketti esimerkiksi esbuildillä ja anna nippu Phasis:lle.
Ei. window, document ja DOM-puu eivät sisälly, eivätkä myöskään Noden globaalit, kuten process, Buffer ja require().
Tuloste puskuroituu moottoriin sen sijaan, että se tulostettaisiin. Lue se komennolla getConsoleOutput() tai getConsoleLines() ja tyhjennä puskuri komennolla clearConsole().
Sieppaamaton heitto näkyy muodossa Phasis\Exceptions\JsThrowable. Moottorin itse aiheuttamat virheet, kuten null-arvon ominaisuuden lukeminen, näkyvät muodossa Phasis\Exceptions\TypeError, ReferenceError tai RangeError, ja ne kaikki perivät luokan Phasis\Exceptions\RuntimeError. Virheellinen lähdekoodi aiheuttaa poikkeuksen Phasis\Parser\ParseError, joka on Phasis\Exceptions\SyntaxError ja sisältää rivin, sarakkeen ja siirtymän.
Aloita aloitusoppaasta ja lue sitten API-viite fetch-koukuista ja tapahtumasilmukasta.