New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

ruby-wasm-wasi

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ruby-wasm-wasi

WebAssembly port of CRuby with WASI

latest
Source
npmnpm
Version
0.2.0
Version published
Maintainers
1
Created
Source

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

Keywords

wasm

FAQs

Package last updated on 16 Mar 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts