Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HypeScript

A proof-of-concept exploring what happens when you compile PHP with PHX syntax directly to WebAssembly.

⚠️ This is NOT production-ready code. This is an experiment to explore ideas.

What is this?

HypeScript is a proof-of-concept framework that attempts to answer the question: "Can we compile PHP code with PHX syntax to WebAssembly and make it reactive?"

The answer turns out to be "sort of, yes" - but with significant caveats and complexity.

Terminology:

  • HypeScript = The framework name
  • PHX = The templating syntax used in .phx files (angle bracket syntax in PHP)

The Basic Idea

Write PHP code that looks like this:

<?php

namespace MyApp;

use function PHX\createSignal;
use function PHX\on;

function Counter($props) {
    list($count, $setCount) = createSignal($props['initial'] ?? 0);

    $increment = function() use ($count, $setCount) {
        $setCount($count->value + 1);
    };

    $decrement = function() use ($count, $setCount) {
        $setCount($count->value - 1);
    };

    return <div class="counter">
        <div class="display">Count: {$count}</div>
        <button onclick={on($decrement, $count)}>-</button>
        <button onclick={on($increment, $count)}>+</button>
    </div>;
}

And have it compile to WebAssembly that runs in the browser with reactive updates.

How It Works (The Pipeline)

.phx files (PHP with PHX syntax)
    ↓
PHX Parser (nikic/php-parser) - converts PHX to createElement() calls
    ↓
.php files (Pure PHP)
    ↓
PeachPie - compiles PHP to .NET IL
    ↓
.NET IL (Intermediate Language)
    ↓
Blazor WebAssembly - compiles IL to WASM
    ↓
WebAssembly + JavaScript runtime

The reactivity system works by:

  1. Registering PHP closures during render
  2. Serializing signal state to JavaScript
  3. When events fire, calling back into WASM via JSInterop
  4. Executing the PHP closure in WASM
  5. Returning updated signal values to JavaScript
  6. Patching the DOM

Requirements

  • PHP 8.0+
  • .NET 8.0 SDK
  • A browser that supports WebAssembly

Quick Start

# Clone the repository
git clone https://github.com/lucasacoutinho/HypeScript
cd hypescript

# Build the project
./phx build

# Serve the app (builds and starts dev server on port 8080)
./phx serve

# Or serve on a custom port
./phx serve 3000

# Show help
./phx help

Project Structure

hypescript/
├── public/              # Your HTML template
│   └── index.html
├── src/                 # Your .phx files
│   └── App.phx
├── .phx/                # Build tooling (don't touch)
│   ├── runtime/        # PHX runtime (signals, createElement, etc)
│   ├── parser/         # PHX → PHP parser
│   ├── compiler/       # PeachPie + Blazor
│   └── build.sh
└── dist/                # Build output

The Thought Process

Why try this?

The idea came from observing that:

  • PeachPie can compile PHP to .NET IL
  • Blazor can compile .NET to WebAssembly
  • SolidJS has a nice reactive model using signals
  • Angle bracket syntax makes UI composition easier to read

Could these pieces fit together? Turns out they can, but it's complicated.

What works

  • PHX syntax in PHP files (parsed to function calls)
  • PHP closures executing as compiled WASM
  • Basic reactivity via signals
  • Function-based components

What doesn't work well

  • Bundle size - WASM output is huge compared to equivalent JS
  • Reflection overhead - Calling PHP closures from JS requires reflection
  • No automatic dependency tracking - You must explicitly pass signals to event handlers
  • Complex build pipeline - Five stages, multiple compilers
  • Debugging - Stack traces cross PHP → .NET → WASM → JS
  • Dev experience - No hot reload, slow builds

Code Examples

Basic Component

<?php

function Greeting($props) {
    return <div>
        <h1>Hello, {$props['name']}!</h1>
    </div>;
}

function App() {
    return <div>
        <Greeting name="World" />
    </div>;
}

Reactive State

<?php

use function PHX\createSignal;
use function PHX\on;

function Toggle($props) {
    list($isOn, $setIsOn) = createSignal(false);

    $toggle = function() use ($isOn, $setIsOn) {
        $setIsOn(!$isOn->value);
    };

    return <div>
        <button onclick={on($toggle, $isOn)}>
            Status: {$isOn->value ? 'ON' : 'OFF'}
        </button>
    </div>;
}

Component Composition

<?php

function Card($props) {
    return <div class="card">
        <h2>{$props['title']}</h2>
        <div class="content">
            {$props['children']}
        </div>
    </div>;
}

function App() {
    return <div>
        <Card title="Example">
            <p>This is inside the card</p>
        </Card>
    </div>;
}

Technical Notes

Signal Registry

Signals are tracked globally during render and assigned unique IDs. When the PHP code executes, it builds a JavaScript initialization script that sets up signal → DOM element bindings.

Closure Registry

PHP closures passed to on() are registered with IDs. When a DOM event fires, JavaScript calls back into WASM with the closure ID and affected signal IDs. The WASM runtime uses reflection to invoke the closure, then returns updated signal values.

Why It's Complicated

The abstraction layers are deep:

  • PHP → .NET IL → WASM → JavaScript
  • Each layer adds overhead and complexity
  • Debugging requires understanding all layers
  • Error messages can be cryptic

Why This Probably Shouldn't Be Used

  1. Size - Sending megabytes of WASM for a simple counter
  2. Performance - Slower initial load than vanilla JS
  3. Complexity - Too many moving parts
  4. Ecosystem - No libraries, no tooling, no community
  5. Maintenance - Depends on PeachPie + Blazor staying compatible

But It's Still Interesting Because...

  • It shows that PHP can target WebAssembly
  • It demonstrates JSInterop between WASM and JavaScript
  • It proves you can execute PHP closures in the browser
  • It's a fun exploration of compiler pipelines

Contributing

This is a proof-of-concept. If you want to experiment with it, go ahead! But don't expect production-ready code.

License

MIT - Use at your own risk

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages