Pure PHP JavaScript engine
Phasis lexes, parses, and executes ECMAScript in pure PHP. No exec('node …'), no FFI, no binary extensions beyond ext-mbstring (always shipped) and ext-bcmath (shipped by default on every mainstream PHP build for BigInt arithmetic and integer-precision number handling). ext-intl is optional — Phasis runs without it, but the Intl.* APIs (Collator, NumberFormat, DateTimeFormat, …) and non-ISO Temporal calendars require it. The whole engine ships as a Composer package and runs anywhere PHP 8.2+ runs.
The problem: PHP applications that need to run user-supplied JavaScript — templating engines, SSR shims, validation rules, content sandboxes, headless test runners — usually shell out to Node.js or skip the feature. Either path adds operational complexity: a second runtime, a serialization boundary, a network of subprocess pipes, and a hostile deployment story for shared hosting.
Phasis solves this by implementing the ECMAScript language and standard library natively in PHP:
- Full ES2024+ language surface (classes, async/await, generators, decorators, top-level await, ES modules)
- Complete standard library (
Array,String,Object,Math,JSON,Date,RegExp,Map,Set,Promise,Proxy,Reflect,Symbol,BigInt,TypedArray,Temporal,Intl) - Web Platform Pack:
URL,URLSearchParams,TextEncoder/TextDecoder,atob/btoa,structuredClone,performance,DOMException - Fetch Pack:
fetch,Request,Response,Headers,Body,AbortController/AbortSignal,Blob/File,FormData,EventTarget/Event, full WHATWG Streams,navigator - Crypto:
crypto.getRandomValues,crypto.randomUUID, fullSubtleCrypto(SHA family, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2) - WebSocket (RFC 6455 + replaceable transport), XMLHttpRequest (layered over fetch), and a real event loop (
setTimeout/setInterval/queueMicrotask, plus Stage-3AsyncContext) - Direct PHP↔JS interop — share objects without serialization, bind PHP callables as JS functions
- 100 % of the official test262 suite passes — ECMAScript conformance, every category, no skips
- 100 % of imported Web Platform Tests pass across fetch, headers, blob, abort, streams, encoding, URL, structured-clone, hr-time, and atob
composer require phasis/phasisuse 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
$engine->setGlobal('config', ['debug' => true]);
$engine->eval('console.log(config.debug)'); // true
// Expose a PHP closure as a JS function
$engine->setGlobal('greet', fn(string $name) => "Hello, $name");
$engine->eval('greet("world")'); // "Hello, world"
// Share a PHP object by reference
class Counter { public int $value = 0; }
$counter = new Counter();
$engine->setGlobal('counter', $counter);
$engine->eval('counter.value++');
echo $counter->value; // 1
// Call JS functions from PHP
$engine->eval('function add(a, b) { return a + b; }');
echo $engine->call('add', 2, 3); // 5Phasis ships two CLI binaries:
# Run a JavaScript file
./vendor/bin/phasis script.js
# Evaluate an expression
./vendor/bin/phasis -e '[1, 2, 3].map(x => x * x)'
# Interactive REPL
./vendor/bin/phasis --repl
# Dump the AST
./vendor/bin/phasis --ast script.js
# Run the official test262 conformance suite
./vendor/bin/test262 --category built-ins/Array
./vendor/bin/test262 --jobs 4Phasis is verified against Node.js (V8) and the official ECMAScript test262 conformance suite.
# Unit tests
composer test
# PHPStan (level 6, zero errors)
composer analyse
# Code standards
composer cs
# Oracle regression (scenarios with Node.js as the ground truth)
./bin/test-regression
# Full quality gate (PHPStan + PHPCS + PHPUnit + oracle)
./bin/verify-all
# test262 conformance sample
./bin/test262 --category built-ins/Array --jobs 4The complete test262 matrix runs in CI on every push. Compliance numbers are committed to COMPAT.md after each run.
| Engine | test262 pass rate |
|---|---|
| V8 (Chrome / Node) | 99.8 % |
| SpiderMonkey (Firefox) | 99.6 % |
| JavaScriptCore (Safari) | 99.4 % |
| QuickJS | ~97 % |
| Hermes (React Native) | ~95 % |
| Phasis | 100 % |
Every test in the official suite passes, every category. See COMPAT.md for the latest snapshot.
Phasis is a tree-walking interpreter with an opportunistic bytecode VM. Expect ~100× the runtime of V8 on dispatch-bound JS — the trade-off is zero dependencies, pure PHP, and host-controlled execution. For embedding workloads where you run user-supplied logic on PHP data, that ceiling rarely matters.
Current microbench numbers are committed in BENCH.md after each bench workflow run.
Full documentation lives at phasis.dev (or in docs/ if you're reading the repo).
- Getting Started: install and run your first script
- CLI:
bin/phasisandbin/test262 - API: full
Phasis\Enginereference - Parser: standalone
Phasis\Parser\ParserAPI, AST walker, ESTree export - Interop: PHP↔JS values, host functions, shared objects
- Compatibility: test262 coverage, spec surface, limitations
- Advanced: architecture, bytecode VM, oracle testing, benchmarks
MIT