Webruby

Now you can write your favorite Ruby code for the browser!

Xuejie "Rafael" Xiao / @defmacro

What is webruby?

  • Ruby implementation that runs in the browser
  • Based on mruby
  • Calling JavaScript directly from Ruby

Demos

IRB(by Joshua Nussbaum)

WebGL

How webruby works?

mruby

  • Matz's embeddable minimal implementation of Ruby language
  • Written in C99
  • Minimal, Embeddable, Modular, Configurable
  • Targeting Mobile device/Robots/Digital appliances/Games

What about the Web?

emscripten

  • LLVM-to-JavaScript compiler
  • Generated JS code runs very fast, and gets faster every day
  • asm.js: subset of JavaScript used as low-level, efficient compiler target

Combine them together

mruby source

Running with node.js

Loading mode

run() load bytecode packed in generated JS file
run_bytecode(bytecode) load bytecode
run_source(src) parse and load Ruby source code on-the-fly

If we do not need run_source(src), we may be able to get rid of all the parsing code!

Load source on-the-fly


$(document).ready(function() {
  var src = "5.times { puts 'Ruby is awesome!' }";
  var w = WEBRUBY();

  w.run_source(src);
  w.close();
});
                  

Running in the browser

mruby test cases

Actually it may not be that slow because of JIT!

Okay, I can run Ruby in the browser.

But how can I access DOM/my fancy JavaScript library?

mruby-js

  • Grouped as a mruby gem
  • DOM access
  • Type conversion between Ruby and JavaScript
  • JavaScript method invoking
  • Callback handling(JavaScript functions and Ruby procs)

Example to use


# gets window object
window = MrubyJs.window

# gets jQuery selected object, this is a function call!
# you can also use jQuery.invoke("#container")
container = window.jQuery["#container"]

# appends new tag
# another way of writing this: container.append["content"]
container.append("

This is inserted using run_source()!

")
Demo

DOM access

DOM is a tree!

Type conversion

Ruby type Direction JavaScript type
42 ←→ 42
3.14 ←→ 3.14
true ←→ true
nil ←→ undefined
"String" ←→ "String"
:symbol "symbol"
Proc.new { ... } function() { ... }
[ ... ] [ ... ]
{ ... } { ... }

Object encapsulation

Method calling

Wrap using instance_eval


MrubyJs.window.instance_eval do
 if confirm("continue?")
    console.log "you chose continue"
    food = prompt("What's your favourite food?")
    alert "Really?? #{food}?\nThat's gross."
    jQuery('body').prepend("

Likes #{food}

") else console.log "you chose not to coninue" end end

mruby-js limitations

JavaScript Ruby
foo.bar() foo.bar.invoke or foo.bar[]
new bar("foo") bar.invoke_new("foo")
var a = bar; a(2); a = window.bar; a[2]

When should I use webruby?

Drawbacks

  • Giant webruby.js file
    Version Raw gzip -1
    non-asm.js 3.2M 691K
    asm.js 2.2M 661K
  • Slow startup time
  • Double GC(maybe asm.js can help with this?)

Places webruby might fit

  • Cross-platform games
    • Common game logic in Ruby
    • Web, iOS, Android, PlayStation...
    • OpenGL ES 2 as rendering API
  • Web apps
    • Business logic in Ruby
    • Interactions with jQuery, three.js, Backbone.js, Meteor...

Thank you!

Questions?

Fork me on GitHub