Introduction
This was inspired by https://github.com/mavenlink/alaska Unfortunately, alaska was designed to run every new script in a new sandbox, thus things like require won't work. So we don't have access to all the power offered by nodejs
Out of our need to call javascript in a rapid fashion from javascript with minimal setup, we decided to rewrite alaska into ruby-await-node with the goal of efficiently execute sophisticated javascript code from ruby.
The key to the performance is to launch a nodejs webserver, then use such webserver to dangerously eval any given javascript part.
It's risky, we know. But with great power come great responsibility. You should be using this if you want to leverage the expertise of javascript where ruby fall short
TODO For ruby-await-node
- [x] Execute any javascript from ruby
- [x] Pass all test
- [x] Execute await/async method
Getting Started
gem 'ruby-await-node'
Or if you want to run the latest version
gem 'ruby-await-node', :git => '[email protected]:remitano/ruby-await-node.git'
Then to invoke some javascript
runtime = RubyAwaitNode::Runtime.new(debug: true)
context = RubyAwaitNode::Context.new(runtime)
entry_path = File.("entry.js", __dir__)
context.eval("global.actor = require(#{entry_path.to_json})")
result = context.eval("actor.method()")
Your entry.js may look like this:
const moment = require("moment")
module.exports = {
method: function() {
return something;
},
asyncMethod: async function() {
await operation;
return something;
}
}
Under the hood ruby-await-node will automatically wait for async method to complete
Examples
Load a javascript file
context.load(File.("entry.js", __dir__))
Warning: always pass the absolute path
Simple execution
context.eval("1.0 + 2.0")
context.eval("global.a = 1.0")
Calling function with arguments
context.call("(function(b) { return global.a * b })", 5)
This will be equivalent to execute this in nodejs
(function(b) { return a * b }).apply(this, [5])
Other examples
Look into spec/ for other potential examples