A toy JavaScript engine implemented in Rust from scratch
Switch branches/tags
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci fix a bug of jit. llvm version reupgrade 4.0 -> 6.0 Sep 1, 2018
examples bug fix Dec 19, 2018
src bug fix Dec 19, 2018
.gitignore change gitignore Dec 16, 2018
Cargo.toml fix compiling error Dec 6, 2018
Dockerfile fix a bug of jit. llvm version reupgrade 4.0 -> 6.0 Sep 1, 2018
LICENSE Everything starts from here Jun 25, 2018
README.md update README.md Dec 11, 2018

README.md

Rapidus

CircleCI codecov

A toy JavaScript engine (now aiming for ES5)

Features

  • Small
  • Partly support for Tracing-JIT compiling
  • Simple REPL

Building from Source

Building on Linux

  1. Install Rust

Run the command below and follow the onscreen instructions.

curl https://sh.rustup.rs -sSf | sh
  1. Use Rust Nightly
rustup override set nightly
  1. Install dependencies
  • LLVM 6.0
  • (Other packages as necessary...)
# e.g. Ubuntu or Debian
apt-get install llvm-6.0
  1. Test
cargo test
  • If the compilation failed because of LLVM-related errors, the following command may help.
ln -sf /usr/bin/llvm-config-6.0 /usr/bin/llvm-config
  1. Build
cargo run --release
  1. Run
cargo run --release example/XXX.js

Building on other platforms

I don't know.

  • tips: If you are using macOS, you cannot use llvm installed with brew. You should use macports or docker instead. Now it works!

Use DLLs written in Rust

THIS FEATURE IS EXPERIMENTAL

  1. Make a cargo project in the directory rapidus' directory is located
$ cargo new hello --lib
$ ls
rapidus hello
  1. Edit Cargo.toml
$ cd hello
$ <YOUR EDITOR> Cargo.toml
# Add the followings to Cargo.toml

[dependencies]
rapidus = { path = "../rapidus" }
# other dependencies if you want...

[lib]
name = "hello"
crate_type = ["cdylib"] # try 'dylib' if it doesn't work.
  1. Edit src/lib.rs
$ <YOUR EDITOR> src/lib.rs
// src/lib.rs

#[macro_use]
extern crate rapidus;
use rapidus::{
   gc,
   vm::{callobj::CallObject, error::RuntimeError, value::*, vm::VM},
};

#[no_mangle]
fn initialize(vm: &mut VM, _: &Vec<Value>, _: &CallObject) -> Result<(), RuntimeError> {
    // make_object!() is useful
    let module_exports = make_object!(
        greet:   Value::default_builtin_function(greet),
        message: Value::string("hello".to_string())
    );

    vm.set_return_value(module_exports); // We have to return module.exports

    Ok(())
}

#[no_mangle]
fn greet(vm: &mut VM, _: &Vec<Value>, _: &CallObject) -> Result<(), RuntimeError> {
    println!("Hello World from Rust DLL!");

    vm.set_return_value(Value::undefined()); // Remember to return a value you want

    Ok(())
}
  1. Let's build
$ cargo build # --release as necessary
  1. Copy the generated DLL to rapidus' directory
$ cp ./target/debug/libhello.(so|dll|dylib) ../rapidus
$ cd ../rapidus
$ ls
libhello.(so|dll|dylib) etc...
  1. You're ready to use it from rapidus. Let's try from REPL.
$ cargo run
> var mod = require('hello')
> mod.greet()
Hello World from Rust DLL!
> mod.message
'hello'
  1. Now everything can be possible from Rust!

Use Dockerfile

  • Docker image: uint256/rapidus
$ docker build -t rapidus:0.1.1 .
$ docker run -it rapidus:0.1.1