Ga naar de inhoud

Phasis

Een JavaScript-engine geschreven in PHP: ES2024+ slaagt voor alle 50 506 test262-tests (snapshot van 2025-05-05), plus URL, encoding, structuredClone, fetch en Streams.

Terminal
composer require phasis/phasis

Nieuwste release v0.4.2 MIT PHP 8.2+, ext-bcmath, ext-curl, ext-mbstring

In de praktijk

Eén engineobject voert JavaScript uit binnen het PHP-proces en wisselt waarden in beide richtingen uit.

Voer JavaScript uit vanuit PHP

Phasis\Engine evalueert broncodestrings en bestanden in het PHP-proces dat de aanroep doet. setGlobal() zet PHP-arrays om in JavaScript-arrays en objecten, en verpakt PHP-closures als functies.

console.log-uitvoer wordt gebufferd in de engine en met getConsoleOutput() teruggelezen. De formatter in het tweede tabblad heeft helemaal geen engine nodig.

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

Zuiver PHP

Geen exec(), geen FFI, geen Node. Vereist PHP 8.2+ met ext-curl, ext-bcmath en ext-mbstring; CI draait op PHP 8.4 en 8.5.

100% test262

Slaagt voor alle 50 506 tests van de ECMAScript-conformiteitssuite volgens de snapshot van 2025-05-05, in elke categorie en zonder overgeslagen tests.

Modern ECMAScript

Classes, async/await, generators, Symbol, BigInt, Proxy, Temporal, TypedArray en Intl met ext-intl. Volledig ES2024+.

Webplatform-API's

URL, TextEncoder en TextDecoder, atob en btoa, structuredClone, performance en DOMException zijn ingebouwd.

fetch + Streams

Echte HTTP via ext-curl van JS. Volledige Fetch API met AbortSignal, Blob, FormData en WHATWG Streams.

Webplatformtests

Geïmporteerde WPT-subtests voor fetch, headers, blob, abort, streams en encoding slagen, met uitzondering van een allowlist voor brotli- en SharedArrayBuffer-cases.

PHP ↔ JS-interoperabiliteit

setGlobal() stelt PHP-closures beschikbaar als JS-functies en call() voert JS-functies uit vanuit PHP. Waarden worden op de grens omgezet; arrays worden gekopieerd.

Inbedbaar

Eén Engine-class: eval, execFile, setGlobal, call. Integreer deze in elke PHP-app of CLI.

Limiet voor de aanroepstack

Een vaste aanroepstack van 4 096 frames stopt onbeperkte recursie met een opvangbare InternalError.

CLI

bin/phasis voert een bestand of een -e-fragment uit en drukt de AST af met --ast. In een repository-checkout voert bin/test262 de conformiteitssuite uit.

Node.js-oracle

Scenario's worden gecontroleerd met Node.js (V8). WPT en de librarysuite draaien in CI bij pushes die de engine wijzigen; de volledige test262-test wordt op aanvraag uitgevoerd, voor het laatst op 2026-06-09.

Echte libraries

204 npm-packages, waaronder acorn, mustache.js, lodash en marked, worden getest met uitvoer die byte voor byte gelijk is aan die van Node.

Waarom Phasis

Geen Node.js-proces

Phasis lexet, parseert en voert JavaScript uit in PHP zelf, zonder exec()-aanroep naar Node en zonder FFI. Het wordt geïnstalleerd als een Composer-package.

fetch onder controle van de host

fetch() gebruikt standaard ext-curl. setFetchTransport() vervangt het transport, bijvoorbeeld door een mock voor tests, en setFetchPolicy() kan elk verzoek weigeren of aanpassen voordat het wordt verzonden.

Timers op virtuele tijd

eval() verwerkt de eventloop voordat deze terugkeert, en de klok springt naar de eerstvolgende timer in plaats van te wachten. Hosts die lang actief blijven, kunnen de loop in realtime aansturen met tickEventLoop().

Parser en formatter inbegrepen

De parser retourneert een getypeerde PHP-AST die naar ESTree kan worden geëxporteerd. De formatter genereert JavaScript, JSON en CSS opnieuw met een met prettier compatibele indeling.

Vergeleken met

Andere manieren om JavaScript vanuit een PHP-applicatie uit te voeren of te verwerken.

Phasis vergeleken met andere tools
Node.js Goed inNode.js voert JavaScript uit op de V8-engine en haalt packages op uit node_modules-mappen, zodat npm-dependencies op naam worden geladen. Verschil met PhasisNode aanroepen vanuit PHP voegt een tweede runtime en een subprocessgrens toe. Phasis draait binnen PHP, maar de moduleloader heeft geen node_modules en ondersteunt geen package.json-exportsresolutie, dus npm-packages moeten eerst worden gebundeld, bijvoorbeeld met esbuild.
V8Js Goed inV8Js integreert de V8-engine van Google in PHP en voert JavaScript uit in een sandbox die met een tijdslimiet en geheugenlimiet kan worden beperkt. Verschil met PhasisV8Js is een gecompileerde extensie waarvoor de libv8-library nodig is. Phasis is gewone PHP van Composer; de documentatie geeft aan dat de runtime op dispatch-gebonden code ongeveer 100 keer die van V8 bedraagt.
Peast Goed inPeast parseert JavaScript naar een ESTree-AST met PHP 5.4 en hoger, en voegt boomtraversal, selectoraanvragen en rendering toe. Verschil met PhasisPhasis vereist PHP 8.2. De parser retourneert getypeerde, alleen-lezen nodeobjecten met een ESTree-export, en hetzelfde package kan de code ook uitvoeren.
Prettier Goed inPrettier formatteert JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML en meer, en kan worden geïnstalleerd via npm. Verschil met PhasisDe Phasis-formatter ondersteunt alleen JavaScript, JSON en CSS. De opties komen overeen met die van prettier 3.x en de formatter draait in PHP, zonder Node.js.

Vragen en antwoorden

Korte antwoorden uit de documentatie van Phasis.

Begin met de handleiding om aan de slag te gaan en lees daarna de API-referentie voor de fetch-hooks en de eventloop.