diff --git a/chrome/content/main.js b/chrome/content/main.js index 5b61238..2611a1a 100644 --- a/chrome/content/main.js +++ b/chrome/content/main.js @@ -1,151 +1,42 @@ -Components.utils.import("resource://gre/modules/ctypes.jsm"); +var worker = new ChromeWorker("ruby_bridge.js"); + +var start = true +worker.onmessage = function(e){ + if (start){ + + document.getElementById('ruby_version').innerHTML = e.data + start = false + }else{ + if (e.data.lastIndexOf('test:', 0) === 0) + { + + alert(e.data) + } + else{ + document.getElementById('dispa').innerHTML = e.data + } + } +}; + + +function make_call_to_ruby() { + worker.postMessage(document.getElementById('scrtext').value); -var lib; -var script; -var mainrb; -(function() { - var cmdLine = window.arguments[0]; - cmdLine = cmdLine.QueryInterface(Components.interfaces.nsICommandLine); - var rubylib = cmdLine.handleFlagWithParam('rubylib', false); - lib = ctypes.open(rubylib); - mainrb = cmdLine.handleFlagWithParam('main', null); - script = cmdLine.handleFlagWithParam('script', null); -})(); -var ID = ctypes.uintptr_t; -var VALUE = ctypes.PointerType(ctypes.uintptr_t); -var VALUE_ARRAY = ctypes.ArrayType(VALUE); -var rb_intern = lib.declare("rb_intern", ctypes.default_abi, ID, ctypes.char.ptr); -var rb_eval_string = lib.declare("rb_eval_string", ctypes.default_abi, VALUE, ctypes.char.ptr); -var rb_const_get = lib.declare("rb_const_get", ctypes.default_abi, VALUE, VALUE, ID); -var rb_string_value_cstr = lib.declare("rb_string_value_cstr", ctypes.default_abi, ctypes.char.ptr, VALUE.ptr); -var rb_str_new_cstr = lib.declare("rb_str_new_cstr", ctypes.default_abi, VALUE, ctypes.char.ptr); -var rb_require = lib.declare("rb_require", ctypes.default_abi, VALUE, ctypes.char.ptr); -var rb_funcall = lib.declare("rb_funcallv", ctypes.default_abi, VALUE, VALUE, ID, ctypes.int, VALUE_ARRAY); -var rb_ull2inum = lib.declare("rb_ull2inum", ctypes.default_abi, VALUE, ctypes.uint64_t); -lib.declare("ruby_init", ctypes.default_abi, ctypes.void_t)(); -(function() { - var chararray = ctypes.ArrayType(ctypes.char.ptr); - var ruby_options = lib.declare("ruby_options", ctypes.default_abi, ctypes.void_t, ctypes.int, chararray); - var args = chararray(3); - args[0].value = ctypes.char.array()('dummy'); - args[1].value = ctypes.char.array()('-e'); - args[2].value = ctypes.char.array()(';'); - ruby_options(3, args); -})(); -rb_require(mainrb); -var obj_class = rb_eval_string("Object"); -var nil_object = rb_eval_string("nil"); -var no_args = VALUE_ARRAY(0); - -window.addEventListener('load', function() { - var vs = rb_eval_string('"#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} [#{RUBY_PLATFORM}]"'); - document.getElementById('ruby_version').innerHTML = rb_string_value_cstr(vs.address()).readString(); - if (script) { - rb_require(script); - } -}); - -function callRuby() { - var arg = VALUE_ARRAY(1); - arg[0] = rb_str_new_cstr(document.getElementById('scrtext').value); - var vs = rb_funcall(obj_class, rb_intern('eval_expression'), 1, arg) - document.getElementById('dispa').innerHTML = rb_string_value_cstr(vs.address()).readString(); -} - -var firedEvents = {}; -var xul_elements = {}; - -function getElement(id) { - return getElementFromString(id.readString()); -} -function getElementFromString(elem_id) { - if (xul_elements[elem_id]) { - return xul_elements[elem_id]; - } - if (elem_id === 'window') { - return window; - } else if (elem_id === 'document') { - return document; - } else if (elem_id.indexOf('frevent:') == 0) { - return firedEvents['ev' + elem_id.substring(8)]; - } - return document.getElementById(elem_id); -} - -function propSetter(id, args) { - var elem = getElement(id); - var argv = JSON.parse(args.readString()); - elem[argv.name] = argv.args[0]; } -function methodCaller(id, args) { - var elem = getElement(id); - var argv = JSON.parse(args.readString()); - var fun = elem[argv.name]; - var ret; - if (typeof fun === 'function') { - for (var i = 0; i < argv.args.length; i++) { - if (typeof argv.args[i] === 'string' - && argv.args[i].indexOf('_XUL::ELEMENT::') == 0) { - argv.args[i] = getElementFromString(argv.args[i].substring(15)); - } - } - ret = fun.apply(elem, argv.args); - } else if (fun) { - ret = fun; - } - if (typeof ret === 'undefined') { - ret = 'undefined'; - } else if (ret == null) { - ret = 'nil'; - } else { - if (typeof ret === 'object' && ret.toString() === '[object XULElement]') { - if (ret.id == '') { - ret.id = '#' + Math.random().toString(); - xul_elements[ret.id] = ret; - } - ret = '_XUL::ELEMENT::' + ret.id; - } else { - ret = ret.toString(); - } - } - return ctypes.char.array()(ret); -} - -function registerEvent(id, args) { - var elem = getElement(id); - var argv = JSON.parse(args.readString()) - elem['cb' + argv.key] = function(e) { - firedEvents['ev' + argv.key] = e; - var args = VALUE_ARRAY(1); - args[0].value = rb_str_new_cstr(argv.key); - rb_funcall(obj_class, rb_intern('notify_event'), 1, args); - firedEvents['ev' + argv.key] = null; - }; - elem.addEventListener(argv.name, elem['cb' + argv.key]); -} - -function removeEvent(id, args) { - var elem = getElement(id); - var argv = JSON.parse(args.readString()) - elem.removeEventListener(argv.name, elem['cb' + argv.key]); -} + +window.addEventListener('close', function () { + worker.postMessage('[[close]]') +}); -var funcPtrType = ctypes.FunctionType(ctypes.default_abi, ctypes.char.ptr, [ctypes.char.ptr, ctypes.char.ptr]).ptr; -var methodcaller = funcPtrType(methodCaller); -var procPtrType = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ctypes.char.ptr, ctypes.char.ptr]).ptr; -var propsetter = procPtrType(propSetter); -var regevent = procPtrType(registerEvent); -var removeevent = procPtrType(removeEvent); -(function() { - var args = VALUE_ARRAY(4); - args[0].value = rb_ull2inum(ctypes.cast(methodcaller, ctypes.uint64_t)); - args[1].value = rb_ull2inum(ctypes.cast(propsetter, ctypes.uint64_t)); - args[2].value = rb_ull2inum(ctypes.cast(regevent, ctypes.uint64_t)); - args[3].value = rb_ull2inum(ctypes.cast(removeevent, ctypes.uint64_t)); - rb_funcall(obj_class, rb_intern('init_fireruby'), args.length, args); -})(); +window.addEventListener('load', function() { + (function() { + var cmdLine = window.arguments[0]; + cmdLine = cmdLine.QueryInterface(Components.interfaces.nsICommandLine); + rubylib = cmdLine.handleFlagWithParam('rubylib', false); + mainrb = cmdLine.handleFlagWithParam('main', false); + script = cmdLine.handleFlagWithParam('script', false); + })(); + worker.postMessage({'command':'init', 'rubylib':rubylib, 'mainrb':mainrb}) -window.addEventListener('close', function () { - lib.close(); -}); \ No newline at end of file +}); diff --git a/chrome/content/main.rb b/chrome/content/main.rb index 8675145..40dd1db 100644 --- a/chrome/content/main.rb +++ b/chrome/content/main.rb @@ -1,18 +1,8 @@ # coding: utf-8 -require 'fiddle' -require 'json' -def init_fireruby(caller, setter, registerevent, removeevent) - caller_ptr = Fiddle::Pointer.new(caller) - $jsfun = Fiddle::Function.new(caller_ptr, [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP) - setter_ptr = Fiddle::Pointer.new(setter) - $jssetter = Fiddle::Function.new(setter_ptr, [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID) - reg_ptr = Fiddle::Pointer.new(registerevent) - $jsregevent = Fiddle::Function.new(reg_ptr, [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID) - rmv_ptr = Fiddle::Pointer.new(removeevent) - $jsrmvevent = Fiddle::Function.new(rmv_ptr, [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID) -end + +require 'fiddle' def eval_expression(str) begin @@ -22,112 +12,11 @@ def eval_expression(str) end end -$dom_events = {} - -def notify_event(e) - blk = $dom_events[e] - if blk - if blk.arity == 1 - blk.call(DOM.new("frevent:#{e}")) - else - blk.call() - end - end +def init_fireruby(param1, param2,param3) + puts "I'm in init_fireruby()" + puts "param1="+param1.to_s + puts "param2="+param2.to_s + puts "param3="+param3.to_s + caller_ptr = Fiddle::Pointer.new(param2) + $h = Fiddle::Function.new(caller_ptr, [ Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID) end - -class DOM - def initialize(id) - @id = id - end - def addEventListener(name, &block) - key = "#{@id}#{name}" - $dom_events[key] = block - $jsregevent.call(@id, JSON({'name' => name, 'key' => key })) - end - alias add_event_listener addEventListener - def removeEventListener(name) - # remove any block at this time - key = "#{@id}#{name}" - $dom_events.delete(key) - $jsrmvevent.call(@id, JSON({'name' => name, 'key' => key })) - end - def to_s - "_XUL::ELEMENT::#{@id}" - end - alias remove_event_listener removeEventListener - def method_missing(name, *args) - begin - param = {} - param['args'] = args - if name.to_s[-1, 1] == '=' - param['name'] = name.to_s[0...-1] - v = $jssetter.call(@id, JSON(param)).to_s - else - param['name'] = name.to_s - v = $jsfun.call(@id, JSON(param)).to_s - return DOM.new($1) if v =~ /\A_XUL::ELEMENT::(.+)\Z/ - end - return v - rescue - return 'error:' + $!.to_s - end - end -end - -$timer_events = {} -def timer_callback(key, cb) - blk = $timer_events[key] - if blk - blk.call() - if cb == 'setTimeout' - $timer_events.delete(key) - end - end -end - -class Window < DOM - def initialize(id) - super(id) - end - def set_timeout(msec, &blk) - timer_func('setTimeout', msec, blk) - end - def set_interval(msec, &blk) - timer_func('setInterval', msec, blk) - end - def clear_interval(id) - if id =~ /\A([^:]+):(.*)\Z/ - $timer_events.delete($2) - $jsfun.call('window', JSON({'name' => 'clearInterval', 'args' => [ $1 ] })) - end - '' - end - private - def timer_func(funname, msec, blk) - key = Random.rand.to_s - $timer_events[key] = blk - fun =< funname, - 'args' => [ fun, msec ]})).to_s + ':' + key - end -end - -class DOM - @@document = DOM.new('document') - @@window = Window.new('window') - def self.document() - @@document - end - def self.document=(xul) - @@document.write(xul) - end - def self.window() - @@window - end -end - diff --git a/chrome/content/main.xul b/chrome/content/main.xul index 3ac8a17..9f03cb5 100644 --- a/chrome/content/main.xul +++ b/chrome/content/main.xul @@ -8,7 +8,8 @@ -