Przejdź do treści

Phasis

Silnik JavaScript napisany w PHP: ES2024+ ze wszystkimi 50 506 zaliczonymi testami test262 (migawka z 2025-05-05), a także URL, kodowanie, structuredClone, fetch i Streams.

Terminal
composer require phasis/phasis

Najnowsze wydanie v0.4.2 MIT PHP 8.2+, ext-bcmath, ext-curl, ext-mbstring

W praktyce

Jeden obiekt silnika uruchamia JavaScript w procesie PHP i przekazuje wartości w obu kierunkach.

Uruchamiaj JavaScript z PHP

Phasis\Engine oblicza ciągi źródłowe i pliki w procesie PHP, który go wywołuje. setGlobal() konwertuje tablice PHP na tablice i obiekty JavaScript oraz opakowuje funkcje domknięcia PHP jako funkcje.

Dane wyjściowe console.log są buforowane w silniku i odczytywane za pomocą getConsoleOutput(). Program formatujący w drugiej karcie nie wymaga silnika.

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

Czysty PHP

Bez exec(), FFI i Node. Wymaga PHP 8.2+ z ext-curl, ext-bcmath i ext-mbstring; CI działa na PHP 8.4 i 8.5.

100% test262

Zalicza wszystkie 50 506 testów zestawu zgodności ECMAScript z migawki 2025-05-05, w każdej kategorii, bez pominięć.

Nowoczesny ECMAScript

Klasy, async/await, generatory, Symbol, BigInt, Proxy, Temporal, TypedArray i Intl z ext-intl. Pełne ES2024+.

Interfejsy API platformy internetowej

URL, TextEncoder i TextDecoder, atob i btoa, structuredClone, performance oraz DOMException są wbudowane.

fetch + strumienie

Prawdziwe HTTP z JS przez ext-curl. Pełne Fetch API z AbortSignal, Blob, FormData i strumieniami WHATWG.

Testy platformy internetowej

Zaimportowane podtesty WPT dla fetch, headers, blob, abort, streams i encoding przechodzą, z wyjątkiem dozwolonej listy przypadków brotli i SharedArrayBuffer.

Interop PHP ↔ JS

setGlobal() udostępnia funkcje domknięcia PHP jako funkcje JS, a call() uruchamia funkcje JS z PHP. Wartości są konwertowane na granicy; tablice są kopiowane.

Możliwość osadzania

Jedna klasa Engine: eval, execFile, setGlobal, call. Można ją dodać do dowolnej aplikacji PHP lub CLI.

Limit stosu wywołań

Stały stos wywołań o głębokości 4 096 ramek zatrzymuje niekontrolowaną rekurencję, zgłaszając przechwytywalny InternalError.

CLI

bin/phasis uruchamia plik lub fragment -e i wyświetla AST za pomocą --ast. W kopii repozytorium bin/test262 uruchamia zestaw testów zgodności.

Oracle Node.js

Scenariusze są sprawdzane względem Node.js (V8). WPT i zestaw testów biblioteki działają w CI przy zmianach obejmujących silnik; pełny przebieg test262 jest uruchamiany na żądanie, ostatnio 2026-06-09.

Rzeczywiste biblioteki

Testowane są pakiety 204 npm, w tym acorn, mustache.js, lodash i marked; ich wynik jest identyczny bajt po bajcie z Node.

Dlaczego Phasis

Proces bez Node.js

Phasis analizuje leksykalnie, parsuje i wykonuje JavaScript w samym PHP, bez wywołań exec() do Node i bez FFI. Instaluje się jako pakiet Composer.

fetch pod kontrolą hosta

fetch() domyślnie używa ext-curl. setFetchTransport() zmienia transport, na przykład na atrapę w testach, a setFetchPolicy() może odrzucić lub zmienić każde żądanie przed jego wysłaniem.

Liczniki czasu wirtualnego

eval() opróżnia pętlę zdarzeń przed powrotem, a zegar przeskakuje do następnego oczekującego licznika zamiast czekać. Hosty działające długotrwale mogą sterować pętlą w czasie rzeczywistym za pomocą tickEventLoop().

Parser i formatter w zestawie

Parser zwraca typowane AST PHP, które można eksportować do ESTree. Formatter ponownie zapisuje JavaScript, JSON i CSS w układzie zgodnym z prettier.

W porównaniu z

Inne sposoby uruchamiania lub przetwarzania JavaScript z aplikacji PHP.

Phasis w porównaniu z innymi narzędziami
Node.js Dobre wNode.js uruchamia JavaScript na silniku V8 i rozwiązuje pakiety z folderów node_modules, dzięki czemu zależności npm można ładować po nazwie. Różnica w porównaniu z PhasisWywołanie Node z PHP dodaje drugi środowisko uruchomieniowe i granicę podprocesu. Phasis działa wewnątrz PHP, ale jego moduł ładujący nie obsługuje node_modules ani rozwiązywania eksportów package.json, więc pakiety npm trzeba najpierw połączyć, na przykład za pomocą esbuild.
V8Js Dobre wV8Js osadza silnik V8 z Google w PHP i uruchamia JavaScript w piaskownicy, którą można ograniczyć limitem czasu i pamięci. Różnica w porównaniu z PhasisV8Js to skompilowane rozszerzenie wymagające biblioteki libv8. Phasis to czyste PHP z Composer, a dokumentacja podaje, że jego czas działania na kodzie ograniczonym przez dispatch wynosi około 100 razy więcej niż V8.
Peast Dobre wPeast parsuje JavaScript do AST ESTree w wersji PHP 5.4 i nowszych oraz dodaje przechodzenie po drzewie, zapytania selektorów i renderowanie. Różnica w porównaniu z PhasisPhasis wymaga PHP 8.2. Jego parser zwraca typowane, tylko do odczytu obiekty węzłów z eksportem ESTree, a ten sam pakiet może również wykonywać kod.
Prettier Dobre wPrettier formatuje JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML i inne, a można go zainstalować z npm. Różnica w porównaniu z PhasisFormatter Phasis obsługuje tylko JavaScript, JSON i CSS. Jego opcje odzwierciedlają 3.x prettier, działa w PHP i nie wymaga Node.js.

Pytania i odpowiedzi

Krótkie odpowiedzi z dokumentacji Phasis.

Zacznij od przewodnika dla początkujących, a następnie przeczytaj dokumentację API, aby poznać hooki fetch i pętlę zdarzeń.