An ahead-of-time JavaScript compiler
Porffor compiles JavaScript ahead-of-time to WebAssembly and native binaries.
It is currently in pre-alpha with usability beginning in 2025.
JS -> Wasm
Porffor's WebAssembly output is 10-30x smaller and faster compared to existing JS -> Wasm projects as Porffor compiles JS instead of bundling an interpreter.
JS as Wasm allows for sandboxed execution but suffers drastic performance losses: Porffor solves this, allowing for:
Secure, efficient server-side JS hosting
For edge runtimes, Wasm sandboxing allows secure execution without needing excessive isolation; combined with AOTs low overhead compared to JITs, Porffor could allow for running many more customers on the same hardware with minimal performance loss.
Reverse-engineering resistance
If you have especially sensitive JS, compilation can be much harder to reverse than code obfuscation.
JS -> Native
As Porffor truly compiles JS without packaging a runtime, binary sizes are up to 1000x smaller (~90MB -> <100KB).
JS as native allows for simple one-click execution but has substandard sizes: Porffor solves this, allowing for:
Fast JS for embedded, game consoles, and more
Under the hood, Porffor compiles JS -> C -> native; anywhere you can use C, you can now use JS!
Tiny CLI apps written in JS
Imagine writing a CLI app in JS and compiling it to a one-click executable under 1MB!
Porffor has safe compilation as it is written in JS (preventing memory safety vulnerabilities) with 0 eval.
Porffor is written from scratch with ahead-of-time in mind allowing for previously impossible optimizations.
Porffor natively supports TypeScript, no build step: just give it a TS file.
Compile-time (developer's machine)
Traditional embedded compiler ┌──────────────┐ ┌────────────┐ │ │ │ │ │ JavaScript ├─────►│ Bytecode ├─────────────────────────────────► │ │ │ │ └──────────────┘ └────────────┘ Porffor (AOT compiler) ┌──────────────┐ ┌──────────────────────┐ │ │ │ │ │ JavaScript ├─────►│ Binary (Wasm/native) ├───────────────────────► │ │ │ │ └──────────────┘ └──────────────────────┘
Runtime (user's machine)
Interpreter ┌──────────────┐ ┌────────────┐ ┌─────────────┐ │ │ │ │ │ │ │ JavaScript ├─────►│ Bytecode ├─────►│ Evaluated │ │ │ │ │ │ │ └──────────────┘ └────────────┘ └─────────────┘ Just-in-time compiler (JIT) ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │ │ │ │ │ │ │ JavaScript ├─────►│ Machine code ├─────►│ Executed │ │ │ │ │ │ │ └──────────────┘ └──────────────┘ └────────────┘ Browser JS engine ┌──────────────┐ ┌─────────────┐ │ │ Interpreter │ │ │ JavaScript ├───────┬──────►│ Evaluated │ │ │ │ │ │ └──────────────┘ | └─────────────┘ │ │ ┌─────────────┐ │ JIT Tier 1 │ │ └───────┬─────►│ Evaluated │ │ │ │ | └─────────────┘ │ │ ┌─────────────┐ │ JIT Tier 2 │ │ └───────┬─────►│ Evaluated │ │ │ │ ... └─────────────┘ Traditional embedded interpreter ┌─────────────┐ │ │ │ Evaluated │ │ │ └─────────────┘ Wasm runtime or native machine ┌────────────┐ │ │ │ Executed │ │ │ └────────────┘
Instead of a slow interpreter or multiple JIT tiers carefully balancing compile speed (startup/loading time) and JS performance, compiling AOT allows you to compile first and run later. While compile speed for AOT remains important for DX, it no longer effects UX; allowing Porffor to perform static analysis for optimizations like C++ and Rust do today.
The main drawbacks of AOT is lack of dynamic JS evaluation (like eval
) and needing to reinvent the JS engine, so as Porffor is early a lot of JS doesn't work yet, but it is improving by the day:
Test262
Porffor is run against Test262, the official ECMAScript conformance test suite, every commit to track conformance progress.
Playground
You can try Porffor here or locally with npm i -g porffor@latest && porf