Skip to content

restsend/pipa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

150 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pipa (枇杷) - A fast, minimal ES2023 JavaScript runtime built in Rust.

Features

  • ES2023 compliant — implements the ECMAScript 2023 specification
  • Async/await built-in — first-class async/await support without transpilation
  • Bytecode support — compile JavaScript to .jsc bytecode files for fast loading and execution, with configurable optimization levels (-O0 through -O3)
  • Fast — outperforms QuickJS in benchmarks
  • Small — ~5.2 MB binary (with repl feature)
  • Zero-dependency built-in implementations for:
    • Regex/JSON/Base64/BigInt
    • Unicode
    • fetch (HTTP client), rusttls required
    • WebSocket
    • Server-Sent Events (SSE)

No external C libraries or system dependencies for the above — everything is implemented from scratch in Rust.

Benchmarks (2026-05-31)

V8 benchmark suite comparison (higher is better):

Benchmark qjs node boa pipa vs qjs
Richards 980 46846 133 895 -8.7%
DeltaBlue 951 94979 140 923 -2.9%
Crypto 1059 60072 125 993 -6.2%
RayTrace 1462 79697 315 965 -34.1%
EarleyBoyer 2107 95129 281 1307 -38.0%
RegExp 330 12703 41.6 1016 +207.9%
Splay 2405 48609 536 2904 +20.7%
NavierStokes 1793 56392 288 1825 +1.8%
SCORE (total) 1201 53836 184 1240 +3.2%

Ranking: #1 node (53836) · #2 pipa (1240) · #3 qjs (1201) · #4 boa (184)

test262 Compatibility (2026-05-31)

Tested against tc39/test262 (excluding intl402).

Category Tests Pass Rate Notes
Core Builtins
Math 324 100% (324/324)
Boolean 50 100% (50/50)
parseFloat 96 100% (96/96)
parseInt 104 100% (104/104)
Number 339 100% (339/339)
Object.is 21 100% (21/21)
Object.defineProperty 1131 98.8% (1118/1131)
Object.create 320 99.4% (318/320)
Object.getPrototypeOf 39 100% (39/39)
Date 594 93.6% (556/594)
global 29 96.6% (28/29)
Infinity 6 100% (6/6)
eval 10 80.0% (8/10)
URI encode/decode 118 77.9% (92/118)
Function 507 85.2% (432/507)
Other Builtins
Symbol 98 73.5% (72/98)
JSON 165 50.9% (84/165)
Error 92 44.6% (41/92)
RegExp 1878 42.3% (794/1878)
String 301 17.0% (51/301)
Reflect 153 20.9% (32/153)
Map 203 21.2% (43/203)
Set 382 18.3% (70/382)
BigInt 77 23.4% (18/77)
Promise 676 5.5% (37/676) Limited async support
Proxy 311 0% (0/311) Not yet implemented

Usage

cargo install pipa-js
# Run a script
pipa script.js

# Run precompiled bytecode
pipa script.jsc

# Compile JavaScript to bytecode
pipa -compile input.js output.jsc

# Disassemble bytecode (debugging)
pipa -diss script.jsc

# Specify optimization level (default: -O2)
pipa -O3 script.js

# Start REPL (requires the repl feature)
pipa

Embedding in Rust

Use pipa-js as a library to embed JavaScript in your Rust project:

[dependencies]
pipa-js = "0.1.2"

Evaluate JavaScript

use pipa::{JSRuntime, eval};

let mut rt = JSRuntime::new();
let mut ctx = rt.new_context();

let val = eval(&mut ctx, "1 + 2").unwrap();
assert_eq!(val.get_int(), 3);

Read strings & values from JavaScript

use pipa::{JSRuntime, eval};

let mut rt = JSRuntime::new();
let mut ctx = rt.new_context();

eval(&mut ctx, r#"
    function greet(name) {
        return "Hello, " + name + "!";
    }
"#).unwrap();

let val = eval(&mut ctx, r#"greet("world")"#).unwrap();
assert!(val.is_string());
let s = ctx.get_atom_str(val.get_atom());
assert_eq!(s, "Hello, world!");

Call custom Rust functions from JavaScript

use pipa::{JSRuntime, eval, JSValue};

fn js_print(ctx: &mut pipa::JSContext, args: &[JSValue]) -> JSValue {
    for arg in args {
        if arg.is_string() {
            print!("{}", ctx.get_atom_str(arg.get_atom()));
        } else if arg.is_int() {
            print!("{}", arg.get_int());
        }
    }
    println!();
    JSValue::undefined()
}

let mut rt = JSRuntime::new();
let mut ctx = rt.new_context();

ctx.register_global_builtin("print", 1, js_print);
eval(&mut ctx, r#"print("hello from Rust!")"#).unwrap();

Async/await with event loop

use pipa::{JSRuntime, eval, eval_async};

let mut rt = JSRuntime::new();
let mut ctx = rt.new_context();

eval_async(&mut ctx, r#"
    var result = null;
    (async () => {
        result = await fetch("https://httpbin.org/json");
    })();
"#).unwrap();

let val = eval(&mut ctx, "JSON.stringify(result)").unwrap();
println!("{}", ctx.get_atom_str(val.get_atom()));

Requires the fetch feature (enabled by default). eval_async is eval + run_event_loop in one call.

Bytecode compilation

use pipa::{JSRuntime, eval, compile_to_register_bytecode};

let mut rt = JSRuntime::new();
let mut ctx = rt.new_context();

// Compile JavaScript to register-based bytecode
let (code, constants) = compile_to_register_bytecode(
    &mut ctx,
    "function fib(n) { return n < 2 ? n : fib(n-1) + fib(n-2); } fib(20)",
).unwrap();

// code: Vec<u8>, constants: Vec<JSValue>
assert!(!code.is_empty());

Build

# Default build (includes REPL, fetch, and process support)
cargo build --release

# Minimal build (no REPL, no fetch, no process)
cargo build --release --no-default-features

If using pipa as a library dependency and you don't need REPL/fetch/process features, add it with default-features = false:

[dependencies]
pipa-js = { version = "0.1.1", default-features = false }

License

MIT

About

A fast, minimal ES2023 JavaScript runtime built in Rust.

Topics

Resources

Stars

Watchers

Forks

Contributors

Languages