Tristan Cartledge 226aa9283a Initial commit: JavaScript to WebAssembly compilation comparison
- 5 different JS-to-WASM implementations analyzed
- QuickJS (283KB) and Javy Static (519KB) are Wasmer-compatible
- Comprehensive size analysis and runtime compatibility testing
- Complete documentation and build automation
- Wasmer v6.1.0-rc.2 dynamic linking analysis included
2025-08-18 13:51:20 +10:00

JavaScript to WebAssembly Compilation Comparison

A comprehensive analysis and comparison of different approaches to compile JavaScript to WebAssembly, with a focus on size optimization and runtime compatibility.

🎯 Overview

This repository explores 5 different JavaScript-to-WASM compilation approaches:

  1. QuickJS (Rust) - 283KB gzipped Recommended for Wasmer
  2. Javy Static - 519KB gzipped Wasmer Compatible
  3. Javy Dynamic - 488KB + 2KB per module (Node.js only)
  4. Porffor - 75KB gzipped (Node.js only)
  5. Go/TinyGo + Goja - 92KB-3.7MB gzipped (Browser/Node.js only)

🏆 Key Results

Wasmer Runtime Compatibility

  • QuickJS: Perfect compatibility, 283KB gzipped
  • Javy Static: Perfect compatibility, 519KB gzipped
  • All others: Require Node.js runtime or have compatibility issues

Size Comparison (Gzipped)

Implementation Size Runtime Wasmer Best For
QuickJS 283KB WASI Production Wasmer
Javy Static 519KB WASI Full JS Compatibility
Porffor 75KB Standard Size-critical Node.js
TinyGo Basic 92KB Go Runtime Browser applications
Javy Dynamic 490KB WASI Node.js multi-module
Goja 3.7MB Go Runtime Full JS engine in Go

🚀 Quick Start

Prerequisites

  • Go 1.21+
  • Rust with wasm32-wasip1 target
  • Node.js 18+
  • Javy
  • Porffor
  • Wasmer (optional, for testing)

Build All Implementations

# Install dependencies
make install-deps

# Build all implementations
make build-all

# Test all implementations
make test-all

# Test Wasmer compatibility
make test-wasmer

Build Individual Implementations

cd implementations/quickjs
cargo build --release --target wasm32-wasip1

Javy Static

cd implementations/javy
javy build -o transform.wasm transform.js

Porffor

cd implementations/porffor
porffor transform.js -o transform.wasm

📊 Detailed Analysis

Performance Characteristics

QuickJS

  • Cold start: ~5ms
  • Execution: ~1ms per operation
  • Memory: ~2MB baseline
  • Scaling: Excellent for multiple operations

Javy Static

  • Cold start: ~8ms
  • Execution: ~1ms per operation
  • Memory: ~3MB baseline
  • Scaling: Good for multiple operations

Runtime Compatibility

WASI Compatible (Wasmer Ready)

  • QuickJS: Perfect compatibility, uses standard WASI interfaces
  • Javy Static: Perfect compatibility, self-contained

Node.js/Browser Only

  • Porffor: Uses legacy WASM exceptions
  • Go/TinyGo: Requires wasm_exec.js runtime
  • Javy Dynamic: Needs dynamic linking support

🔧 Implementation Details

QuickJS Implementation

  • Language: Rust
  • Engine: QuickJS JavaScript engine
  • Target: wasm32-wasip1
  • Features: Full ECMAScript support, WASI I/O

Javy Implementation

  • Language: JavaScript
  • Engine: QuickJS (via Javy)
  • Target: WASI
  • Features: Bytecode Alliance quality, multiple build modes

Porffor Implementation

  • Language: JavaScript
  • Engine: AOT compiled
  • Target: Standard WASM
  • Features: Smallest size, compile-time optimization

📁 Repository Structure

├── implementations/
│   ├── quickjs/          # Rust + QuickJS (RECOMMENDED)
│   ├── javy/             # Javy static/dynamic builds
│   ├── porffor/          # Porffor AOT compilation
│   ├── goja/             # Go + Goja JavaScript engine
│   └── tinygo/           # TinyGo basic implementation
├── docs/
│   ├── BINARY_SIZES.md           # Detailed size analysis
│   ├── WASMER_COMPATIBILITY.md   # Runtime compatibility guide
│   ├── JAVY_WASMER_ANALYSIS.md   # Javy-specific analysis
│   └── FINAL_WASMER_SUMMARY.md   # Executive summary
├── tests/                # Test suites and benchmarks
├── Makefile             # Build automation
└── README.md           # This file

🧪 Testing

Unit Tests

npm test

Wasmer Compatibility Tests

make test-wasmer

Size Analysis

make measure-sizes

Performance Benchmarks

make benchmark

📖 Documentation

🔬 Research Findings

Wasmer v6.1.0-rc.2 Dynamic Linking

  • Introduces dynamic linking for WASIX/C++ libraries
  • Does NOT support WASM module import resolution
  • Javy dynamic builds still require Node.js runtime

Size Optimization Techniques

  • wasm-opt: 15-20% size reduction
  • Compression: 60-70% reduction with gzip
  • Dead code elimination: Significant impact on Go builds

Runtime Performance

  • WASI overhead: Minimal (~1ms)
  • JavaScript engine startup: 5-10ms
  • Execution performance: Comparable to native JavaScript

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add your implementation in implementations/
  4. Update documentation and tests
  5. Submit a pull request

📄 License

MIT License - see LICENSE for details.

🙏 Acknowledgments


For production Wasmer deployment, use QuickJS (283KB) for optimal size or Javy Static (519KB) for maximum JavaScript compatibility.

Description
No description provided
Readme MIT 1.6 MiB
Languages
JavaScript 47.8%
Shell 15.9%
Python 11.9%
TypeScript 11.1%
Go 6.8%
Other 6.5%