This package has been deprecated

Author message:

This package is renamed to ruby-head-wasm-wasi to distinguish Ruby release channel by package name

ruby-wasm-wasi
TypeScript icon, indicating that this package has built-in type declarations

0.2.0 • Public • Published

ruby-wasm-wasi

WebAssembly port of CRuby with WASI.

The CRuby source code is available at a working branch.

Installation

For instaling ruby-wasm-wasi, just run this command in your shell:

Ruby head

$ npm install --save ruby-head-wasm-wasi

Quick Start (for Node.js)

See the example project for more details.

import fs from "fs/promises";
import { WASI } from "wasi";
import { RubyVM } from "ruby-head-wasm-wasi";

const main = async () => {
  const wasi = new WASI();
  const binary = await fs.readFile(
    "./node_modules/ruby-head-wasm-wasi/ruby.wasm"
  );
  const vm = new RubyVM();
  const imports = {
    wasi_snapshot_preview1: wasi.wasiImport,
  };

  // Add imports for WebAssembly instantiation
  vm.addToImports(imports);

  // Instantiate the WebAssembly module
  const { instance } = await WebAssembly.instantiate(binary.buffer, imports);

  // Set instance to vm
  await vm.setInstance(instance);

  // Initialize WASI application
  wasi.initialize(instance);

  // Initialize Ruby VM
  vm.initialize();

  vm.eval(`
    luckiness = ["Lucky", "Unlucky"].sample
    puts "You are #{luckiness}"
  `);
};

main();

Then you can run the example project in your terminal:

$ node --experimental-wasi-unstable-preview1 index.node.js

Quick Start (for Browser)

In browser, you need a WASI polyfill See the example project for more details.

import { WASI } from "@wasmer/wasi";
import { WasmFs } from "@wasmer/wasmfs";
import { RubyVM } from "ruby-head-wasm-wasi";

const main = async () => {
  // Setup WASI and FileSystem emulation
  const wasmFs = new WasmFs();
  const wasi = new WASI({
    bindings: {
      ...WASI.defaultBindings,
      fs: wasmFs.fs,
    },
  });

  // (Optional) Forward stdout/stderr to console
  const originalWriteSync = wasmFs.fs.writeSync.bind(wasmFs.fs);
  wasmFs.fs.writeSync = (fd, buffer, offset, length, position) => {
    const text = new TextDecoder("utf-8").decode(buffer);
    const handlers = {
      1: (line) => console.log(line),
      2: (line) => console.warn(line),
    };
    if (handlers[fd]) handlers[fd](text);
    return originalWriteSync(fd, buffer, offset, length, position);
  };

  // Fetch and instantiate WebAssembly binary
  const response = await fetch(
    "./node_modules/ruby-head-wasm-wasi/dist/ruby.wasm"
  );
  const buffer = await response.arrayBuffer();
  const vm = new RubyVM();

  const imports = {
    wasi_snapshot_preview1: wasi.wasiImport,
  };

  // Add imports for WebAssembly instantiation
  vm.addToImports(imports);

  // Instantiate the WebAssembly module
  const { instance } = await WebAssembly.instantiate(buffer, imports);

  // Set instance to vm
  await vm.setInstance(instance);

  // Initialize WASI application
  wasi.setMemory(instance.exports.memory);

  // Initialize Ruby VM
  vm.initialize();

  vm.eval(`
    require "js"
    luckiness = ["Lucky", "Unlucky"].sample
    JS::eval("document.body.innerText = '#{luckiness}'")
  `);
};

main();

APIs

Table of Contents

RubyVM

A Ruby VM instance

Examples

const wasi = new WASI();
const vm = new RubyVM();
const imports = {
  wasi_snapshot_preview1: wasi.wasiImport,
};

vm.addToImports(imports);

const instance = await WebAssembly.instantiate(rubyModule, imports);
await vm.setInstance(instance);
wasi.initialize(instance);

initialize

Initialize the Ruby VM with the given command line arguments

Parameters
  • args The command line arguments to pass to Ruby. Must be an array of strings starting with the Ruby program name. (optional, default ["ruby.wasm","--disable-gems","-e_=0"])

setInstance

Set a given instance to interact JavaScript and Ruby's WebAssembly instance. This method must be called before calling Ruby API.

Parameters
  • instance The WebAssembly instance to interact with. Must be instantiated from a Ruby built with JS extension, and built with Reactor ABI instead of command line.

addToImports

Add intrinsic import entries, which is necessary to interact JavaScript and Ruby's WebAssembly instance.

Parameters
  • imports The import object to add to the WebAssembly instance

printVersion

Print the Ruby version to stdout

eval

Runs a string of Ruby code from JavaScript

Parameters
  • code The Ruby code to run
Examples
vm.eval("puts 'hello world'");
const result = vm.eval("1 + 2");
console.log(result.toString()); // 3

Returns any the result of the last expression

RbValue

A RbValue is an object that represents a value in Ruby

Parameters

  • inner
  • vm
  • exporter

call

Call a given method with given arguments

Parameters
  • callee name of the Ruby method to call
  • args ...any arguments to pass to the method. Must be an array of RbValue
Examples
const ary = vm.eval("[1, 2, 3]");
ary.call("push", 4);
console.log(ary.call("sample").toString());

toPrimitive

Parameters
  • hint

toString

Returns a string representation of the value by calling to_s

toJS

Returns a JavaScript object representation of the value by calling to_js.

Returns null if the value is not convertible to a JavaScript object.

RbError

Extends Error

Error class thrown by Ruby execution

Parameters

  • message

Building the package from source

For building the package from source, you need to prepare a Ruby build produced by WASI SDK, and you need wit-bindgen and wasm-opt in your PATH.

The instructions for building a Ruby targeting WebAssembly are available at: TODO.

Then, you can run the following command in your shell:

# Check the directory structure of your Ruby build
$ tree -L 3 path/to/wasm32-unknown-wasi-full-js/
path/to/wasm32-unknown-wasi-full-js/
├── usr
│   └── local
│       ├── bin
│       ├── include
│       ├── lib
│       └── share
└── var
    └── lib
        └── gems
$ ./build-package.sh path/to/wasm32-unknown-wasi-full-js/
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-wasm-wasi/src/bindgen/intrinsics.js"
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts"
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js"
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts"
Generating "/Users/katei/.ghq/github.com/kateinoigakukun/ruby.wasm/packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js"

src/index.ts → dist/index.umd.js, dist/index.esm.js, dist/index.cjs.js...
created dist/index.umd.js, dist/index.esm.js, dist/index.cjs.js in 682ms

/ruby-wasm-wasi/

    Package Sidebar

    Install

    npm i ruby-wasm-wasi

    Weekly Downloads

    1

    Version

    0.2.0

    License

    MIT

    Unpacked Size

    11.1 MB

    Total Files

    22

    Last publish

    Collaborators

    • kateinoigakukun