Skip to content

Repository files navigation

Phasis

Pure PHP JavaScript engine

CI Packagist license


What is Phasis?

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, full SubtleCrypto (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-3 AsyncContext)
  • 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

Quick Start

composer require phasis/phasis
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
$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);              // 5

CLI

Phasis 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 4

Testing

Phasis 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 4

The complete test262 matrix runs in CI on every push. Compliance numbers are committed to COMPAT.md after each run.

Compatibility

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.

Performance

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.

Documentation

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/phasis and bin/test262
  • API: full Phasis\Engine reference
  • Parser: standalone Phasis\Parser\Parser API, 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

License

MIT

About

Pure PHP JavaScript engine with test262 conformance testing.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages