Pular para o conteúdo

Phasis

Um mecanismo JavaScript escrito em PHP: passa em todos os testes 50 506 test262 ES2024+ (instantâneo de 2025-05-05), além de URL, codificação, structuredClone, fetch e Streams.

Terminal
composer require phasis/phasis

Versão mais recente v0.4.2 MIT PHP 8.2+, ext-bcmath, ext-curl, ext-mbstring

Na prática

Um único objeto de mecanismo executa JavaScript dentro do processo PHP e transfere valores nas duas direções.

Execute JavaScript a partir de PHP

Phasis\Engine avalia strings de código-fonte e arquivos no processo PHP que o chama. setGlobal() converte arrays de PHP em arrays e objetos de JavaScript, e encapsula closures de PHP como funções.

A saída de console.log fica em buffer no mecanismo e pode ser lida com getConsoleOutput(). O formatador na segunda aba não precisa de mecanismo.

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

PHP puro

Sem exec(), sem FFI, sem Node. Requer PHP 8.2+ com ext-curl, ext-bcmath e ext-mbstring; a CI executa PHP 8.4 e 8.5.

100% test262

Passa nos 50 506 testes do conjunto de conformidade ECMAScript no instantâneo de 2025-05-05, em todas as categorias, sem ignorar nenhum teste.

ECMAScript moderno

Classes, async/await, geradores, Symbol, BigInt, Proxy, Temporal, TypedArray e Intl com ext-intl. ES2024+ completo.

APIs da plataforma Web

URL, TextEncoder e TextDecoder, atob e btoa, structuredClone, performance e DOMException já vêm integrados.

fetch + Streams

HTTP reais de JS via ext-curl. Fetch API completo com AbortSignal, Blob, FormData e WHATWG Streams.

Testes da plataforma Web

Os subtestes WPT importados para fetch, headers, blob, abort, streams e encoding passam, exceto pelos casos de brotli e SharedArrayBuffer em uma lista de permissões.

Interop de PHP ↔ JS

setGlobal() expõe closures PHP como funções JS, e call() executa funções JS a partir de PHP. Os valores são convertidos na fronteira; os arrays são copiados.

Incorporável

Uma classe Engine: eval, execFile, setGlobal, call. Integre-a a qualquer aplicação PHP ou CLI.

Limite da pilha de chamadas

Uma pilha de chamadas fixa de 4 096 quadros interrompe a recursão descontrolada com um InternalError capturável.

CLI

bin/phasis executa um arquivo ou trecho -e e imprime a AST com --ast. Em um clone do repositório, bin/test262 executa o conjunto de testes de conformidade.

Oráculo Node.js

Os cenários são verificados com Node.js (V8). WPT e o conjunto de testes da biblioteca são executados na CI em envios que alteram o mecanismo; a execução completa de test262 ocorre sob demanda, mais recentemente em 2026-06-09.

Bibliotecas reais

204 pacotes npm, entre eles acorn, mustache.js, lodash e marked, são testados com saída idêntica byte a byte à do Node.

Por que Phasis

Sem processo Node.js

Phasis analisa léxica e sintaticamente e executa JavaScript no próprio PHP, sem chamada exec() ao Node e sem FFI. É instalado como um pacote Composer.

fetch sob controle do host

fetch() usa ext-curl por padrão. setFetchTransport() substitui o transporte, por exemplo por um mock nos testes, e setFetchPolicy() pode bloquear ou reescrever cada solicitação antes do envio.

Temporizadores com tempo virtual

eval() esvazia o loop de eventos antes de retornar, e o relógio avança até o próximo temporizador pendente em vez de esperar. Hosts de longa duração podem executar o loop em tempo real com tickEventLoop().

Parser e formatador incluídos

O parser retorna uma AST tipada PHP que pode ser exportada para ESTree. O formatador imprime novamente JavaScript, JSON e CSS com um layout compatível com prettier.

Comparação com

Outras maneiras de executar ou processar JavaScript em uma aplicação PHP.

Phasis em comparação com outras ferramentas
Node.js Ideal paraNode.js executa JavaScript no mecanismo V8 e resolve pacotes em pastas node_modules, então dependências npm são carregadas pelo nome. Diferenças em relação a PhasisChamar Node a partir de PHP adiciona um segundo ambiente de execução e uma fronteira de subprocesso. Phasis executa dentro de PHP, mas seu carregador de módulos não tem node_modules nem resolução de exports package.json; por isso, pacotes npm precisam ser empacotados antes, por exemplo com esbuild.
V8Js Ideal paraV8Js incorpora o mecanismo V8 de Google em PHP e executa JavaScript em uma sandbox que pode ser restringida por limites de tempo e memória. Diferenças em relação a PhasisV8Js é uma extensão compilada que precisa da biblioteca libv8. Phasis é PHP puro de Composer, e sua documentação estima um tempo de execução cerca de 100 vezes maior que o de V8 em código limitado pela distribuição de chamadas.
Peast Ideal paraPeast analisa JavaScript em uma AST ESTree no PHP 5.4 e versões posteriores, adicionando percurso da árvore, consultas por seletores e renderização. Diferenças em relação a PhasisPhasis requer PHP 8.2. Seu parser retorna objetos de nós tipados e somente para leitura, com exportação ESTree, e o mesmo pacote também pode executar o código.
Prettier Ideal paraPrettier formata JavaScript, TypeScript, JSX, CSS, HTML, Markdown, YAML e mais, e pode ser instalado de npm. Diferenças em relação a PhasisO formatador Phasis cobre apenas JavaScript, JSON e CSS. Suas opções seguem as de prettier 3.x e ele é executado em PHP, sem Node.js.

Perguntas e respostas

Respostas curtas da documentação do Phasis.

Comece pelo guia de introdução e depois consulte a referência API para os hooks de fetch e o loop de eventos.