Hoppa till innehåll

Phasis

En JavaScript-motor skriven i PHP: ES2024+ klarar alla 50 506 test262-tester (ögonblicksbild 2025-05-05), samt URL, kodning, structuredClone, fetch och Streams.

Terminal
composer require phasis/phasis

Senaste versionen v0.4.2 MIT PHP 8.2+, ext-bcmath, ext-curl, ext-mbstring

I praktiken

Ett motorobjekt kör JavaScript i PHP-processen och skickar värden åt båda hållen.

Kör JavaScript från PHP

Phasis\Engine utvärderar källsträngar och filer i PHP-processen som anropar den. setGlobal() konverterar arrayer i PHP till arrayer och objekt i JavaScript, och omsluter closures i PHP som funktioner.

Utdata från console.log buffras på motorn och läses tillbaka med getConsoleOutput(). Formatteraren på den andra fliken behöver ingen motor alls.

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

Ren PHP

Ingen exec(), ingen FFI, ingen Node. Kräver PHP 8.2+ med ext-curl, ext-bcmath och ext-mbstring; CI kör PHP 8.4 och 8.5.

100% test262

Klarar alla 50 506-tester i ECMAScript-kompatibilitetssviten enligt ögonblicksbilden från 2025-05-05, samtliga kategorier, utan överhoppade tester.

Modern ECMAScript

Klasser, async/await, generatorer, Symbol, BigInt, Proxy, Temporal, TypedArray och Intl med ext-intl. Fullständigt ES2024+.

Webbplattformens API:er

URL, TextEncoder och TextDecoder, atob och btoa, structuredClone, performance och DOMException ingår.

fetch + Streams

Äkta HTTP från JS via ext-curl. Fullständigt Fetch-API med AbortSignal, Blob, FormData och WHATWG Streams.

Tester för webbplattformen

Importerade WPT-deltester för fetch, headers, blob, abort, streams och kodning klarar sig, förutom en tillåtelselista med fall för brotli och SharedArrayBuffer.

PHP ↔ JS-kompatibilitet

setGlobal() exponerar PHP-stängningar som JS-funktioner och call() kör JS-funktioner från PHP. Värden konverteras vid gränsen; arrayer kopieras.

Inbäddningsbar

En enda klass, Engine: eval, execFile, setGlobal, call. Lägg in den i valfri PHP-app eller CLI.

Anropsstackstak

En fast anropsstack på 4 096 ramar stoppar skenande rekursion med ett fångningsbart InternalError.

CLI

bin/phasis kör en fil eller ett -e-utdrag och skriver ut AST:n med --ast. I en utcheckad kodbas kör bin/test262 kompatibilitetssviten.

Node.js-orakel

Scenarier kontrolleras mot Node.js (V8). WPT och bibliotekssviten körs i CI vid pushar som berör motorn; hela testkörningen test262 körs vid behov, senast 2026-06-09.

Verkliga bibliotek

204 npm-paket, däribland acorn, mustache.js, lodash och marked, testas med utdata som är byteidentisk med Node.

Varför Phasis

Ingen Node.js-process

Phasis lexar, parsar och kör JavaScript i PHP självt, utan något exec()-anrop till Node och utan FFI. Det installeras som ett Composer-paket.

fetch under värdkontroll

fetch() använder ext-curl som standard. setFetchTransport() byter transport, till exempel till en mock i tester, och setFetchPolicy() kan neka eller skriva om varje begäran innan den skickas.

Timers med virtuell tid

eval() tömmer händelseloopen innan den returnerar, och klockan hoppar till nästa väntande timer i stället för att vila. Värdar med lång livslängd kan driva loopen i realtid med tickEventLoop().

Parser och formatterare ingår

Parsern returnerar en typad PHP-AST som exporteras till ESTree. Formatteraren skriver om JavaScript, JSON och CSS med en layout som är kompatibel med prettier.

Jämfört med

Andra sätt att köra eller bearbeta JavaScript från en applikation i PHP.

Phasis jämfört med andra verktyg
Node.js Bra påNode.js kör JavaScript på motorn V8 och löser paket från mapparna node_modules, så npm-beroenden laddas med namn. Skillnaden jämfört med PhasisAtt anropa Node från PHP lägger till en andra körtidsmiljö och en subprocessgräns. Phasis körs inuti PHP, men dess modulladdare saknar node_modules och upplösning av package.json-exporter, så paket i npm måste paketeras först, till exempel med esbuild.
V8Js Bra påV8Js bäddar in V8-motorn från Google i PHP och kör JavaScript i en sandlåda som kan begränsas med en tidsgräns och en minnesgräns. Skillnaden jämfört med PhasisV8Js är ett kompilerat tillägg som behöver libv8-biblioteket. Phasis är ren PHP från Composer, och dokumentationen anger att körningen tar ungefär 100 gånger så lång tid som V8 för kod som är bunden av dispatch.
Peast Bra påPeast parsar JavaScript till en ESTree-AST med PHP 5.4 och senare, och lägger till trädtraversering, väljarsökningar och rendering. Skillnaden jämfört med PhasisPhasis kräver PHP 8.2. Parsern returnerar typade, skrivskyddade nodobjekt med en ESTree-export, och samma paket kan även köra koden.
Prettier Bra påPrettier formaterar JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML med mera och installeras från npm. Skillnaden jämfört med PhasisFormatteraren i Phasis hanterar endast JavaScript, JSON och CSS. Alternativen speglar prettier 3.x, och den körs i PHP utan Node.js.

Frågor och svar

Korta svar från dokumentationen för Phasis.

Börja med kom igång-guiden och läs sedan referensen för API för hämtningskrokar och händelseslingan.