class Jass::Base
Public Class Methods
dependency(deps)
click to toggle source
# File lib/jass/base.rb, line 14 def dependency(deps) self.dependencies = dependencies + deps.map { |name, package| Dependency.new(name, package) } end
function(name, code)
click to toggle source
# File lib/jass/base.rb, line 18 def function(name, code) self.functions = functions + [Function.new(name, code)] define_method(name) { |*args| call_js_method(name, args) } end
generate_code()
click to toggle source
# File lib/jass/base.rb, line 23 def generate_code %{ function __handle_error__(error) { var errInfo = {}; if (error instanceof Error) { errInfo.name = error.name; Object.getOwnPropertyNames(error).reduce((obj, prop) => { obj[prop] = error[prop]; return obj }, errInfo); // process.stdout.write(JSON.stringify(['err', error.toString().replace(new RegExp('^' + error.name + ': '), ''), error.name])); } else { errInfo.name = error.toString(); } process.stdout.write(JSON.stringify(['err', errInfo])); process.stdout.write("\\n"); } try { #{dependencies.map(&:to_js).join} } catch (e) { __handle_error__(e); process.exit(1); } var __plugins__ = []; #{plugins.map(&:to_js).join} process.stdout.write("[\\"ok\\"]\\n"); var __methods__ = {}; #{functions.map(&:to_js).join} require('readline').createInterface({ input: process.stdin, terminal: false, }).on('line', function(line) { var input = JSON.parse(line); try { Promise.resolve(__methods__[input[0]].apply(null, input[1]) ).then(function (result) { process.stdout.write(JSON.stringify(['ok', result])); process.stdout.write("\\n"); }).catch(__handle_error__); } catch(error) { __handle_error__(error); } }); } end
new(root, env = {})
click to toggle source
# File lib/jass/base.rb, line 84 def initialize(root, env = {}) @node_root = root @node_env = env end
Protected Class Methods
finalize(stdin, stdout, stderr, process_thread)
click to toggle source
# File lib/jass/base.rb, line 73 def finalize(stdin, stdout, stderr, process_thread) proc do stdin.close stdout.close stderr.close Process.kill(0, process_thread.pid) process_thread.value end end
Public Instance Methods
pid()
click to toggle source
# File lib/jass/base.rb, line 89 def pid @node_process_thread && @node_process_thread.pid end
Private Instance Methods
call_js_method(method, args)
click to toggle source
# File lib/jass/base.rb, line 126 def call_js_method(method, args) ensure_process_is_spawned @node_stdin.puts JSON.dump([method, args]) input = @node_stdout.gets raise Errno::EPIPE, "Can't read from stdout" if input.nil? status, result = JSON.parse(input) return result if status == 'ok' raise Jass::JavaScriptError.new(result) rescue Errno::EPIPE, IOError # TODO(bouk): restart or something? If this happens the process is completely broken raise Jass::Error, "Node process failed:\n#{@node_stderr.read}" end
ensure_packages_are_initiated(stdin, stdout, stderr, process_thread)
click to toggle source
# File lib/jass/base.rb, line 107 def ensure_packages_are_initiated(stdin, stdout, stderr, process_thread) input = stdout.gets raise Jass::Error, "Failed to instantiate Node process:\n#{stderr.read}" if input.nil? result = JSON.parse(input) unless result[0] == 'ok' stdin.close stdout.close stderr.close process_thread.join error = result[1] if error.is_a?(Hash) raise Jass::DependencyError.new(error) elsif error.is_a?(String) raise Jass::Error, error end end end
ensure_process_is_spawned()
click to toggle source
# File lib/jass/base.rb, line 95 def ensure_process_is_spawned return if @node_process_thread spawn_process end
spawn_process()
click to toggle source
# File lib/jass/base.rb, line 100 def spawn_process process_data = Open3.popen3(@node_env, 'node', '-e', self.class.generate_code, chdir: @node_root) ensure_packages_are_initiated(*process_data) ObjectSpace.define_finalizer(self, self.class.send(:finalize, *process_data)) @node_stdin, @node_stdout, @node_stderr, @node_process_thread = process_data end