rubyjs / therubyrhino

Embed the Mozilla Rhino Javascript interpreter into Ruby
155 stars 40 forks source link

NativeDate broken implementation #27

Closed lucabelluccini closed 10 years ago

lucabelluccini commented 11 years ago

Hello, tried to do the following

require 'rhino'
o = Object.new
o.eval_js("new Date()")

Triggers

NoMethodError: undefined method `getJSTimeValue' for org.mozilla.javascript.NativeDate@7bb22a8c:Java::OrgMozillaJavascript::NativeDate
    from org/jruby/RubyBasicObject.java:1497:in `method_missing'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/rhino_ext.rb:126:in `method_missing'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/wormhole.rb:10:in `to_ruby'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/context.rb:139:in `eval'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/context.rb:260:in `do_open'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/context.rb:245:in `open'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/context.rb:133:in `eval'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/object.rb:13:in `eval_js'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/context.rb:260:in `do_open'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/context.rb:245:in `open'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/context.rb:43:in `open'
    from /home/admin/logstash/vendor/bundle/jruby/1.9/gems/therubyrhino-2.0.2/lib/rhino/object.rb:12:in `eval_js'
    from (irb):6:in `evaluate'
    from org/jruby/RubyKernel.java:1121:in `eval'
    from org/jruby/RubyKernel.java:1517:in `loop'
    from org/jruby/RubyKernel.java:1282:in `catch'
    from org/jruby/RubyKernel.java:1282:in `catch'
    from /home/admin/logstash/lib/logstash/runner.rb:168:in `run'
    from org/jruby/RubyProc.java:271:in `call'
    from /home/admin/logstash/lib/logstash/runner.rb:200:in `run'
    from /home/admin/logstash/lib/logstash/runner.rb:74:in `main'
    from /home/admin/logstash/lib/logstash/runner.rb:230

Same happens when sharing objects between Ruby (running on JRuby) and a Rhino Js context.

kares commented 11 years ago

Thanks Luca, but that probably means you have some weirdness at yours locally ... maybe using rhino's jar from CP. try: to_java.getClass.getResource('/org/mozilla/javascript/ScriptRuntime.class').toString

lucabelluccini commented 11 years ago

Hello, I am trying to embed this Javascript Engine in Ruby running on JRuby to enrich an existing tool.

irb(main):001:0> to_java.getClass.getResource('/org/mozilla/javascript/ScriptRuntime.class').toString
NoMethodError: undefined method `toString' for nil:NilClass
    from (irb):3:in `evaluate'
    from org/jruby/RubyKernel.java:1121:in `eval'
    from org/jruby/RubyKernel.java:1517:in `loop'
    from org/jruby/RubyKernel.java:1282:in `catch'
    from org/jruby/RubyKernel.java:1282:in `catch'
    from /home/admin/logstash/lib/logstash/runner.rb:168:in `run'
    from org/jruby/RubyProc.java:271:in `call'
    from /home/admin/logstash/lib/logstash/runner.rb:200:in `run'
    from /home/admin/logstash/lib/logstash/runner.rb:74:in `main'
    from /home/admin/logstash/lib/logstash/runner.rb:230:in `(root)'

I tried to pack the tool (logstash) in a jar and I am unable to use Rhino due to missing jar, but this is another issue linked to the build.

kares commented 11 years ago

You won't be able to pack a jar inside another ... in that case you need to extract and re-pack the jar (therubyrhino needs the rhino.jar from _therubyrhinojar gem) ... I'm not sure what the issue is here but I'm pretty confident it's specific about your setup ( otherwise we would have heard of this a long time ago :) ... start with Java's class-path. Good luck!

lucabelluccini commented 11 years ago

Hello, thanks. It was linked to jruby gem installation. Best regards, Luca B.

lucabelluccini commented 11 years ago

Hello... I changed a little the structure of the code and I am no more able to convert Time to Javascript

jruby-1.7.8 :001 > require 'rhino'
 => true 
jruby-1.7.8 :002 > a = {}
 => {} 
jruby-1.7.8 :003 > a['@timestamp'] = Time.now
 => 2013-11-21 02:08:31 +0100 
jruby-1.7.8 :004 > a
 => {"@timestamp"=>2013-11-21 02:08:31 +0100} 
jruby-1.7.8 :005 > ctx = Rhino::Context.new
 => #<Rhino::Context:0x7d1050be @scope={}, @global={}, @native=#<Java::OrgMozillaJavascript::Context:0x43824d2c>> 
jruby-1.7.8 :006 > ctx.eval "function fun(par) { return par['@timestamp2'] = par['@timestamp'] }"
 => nil 
jruby-1.7.8 :007 > ctx
 => #<Rhino::Context:0x7d1050be @scope={"fun"=>org.mozilla.javascript.gen._eval__1@6517a4c6}, @global={"fun"=>org.mozilla.javascript.gen._eval__1@6517a4c6}, @native=#<Java::OrgMozillaJavascript::Context:0x43824d2c>> 
jruby-1.7.8 :008 > ctx['fun'].methodcall(a)
NoMethodError: undefined method `getDeclaredConstructor' for class org.mozilla.javascript.NativeObject:Java::JavaClass
    from /home/luca/.rvm/gems/jruby-1.7.8/gems/therubyrhino-2.0.2/lib/rhino/wormhole.rb:85:in `time_to_javascript'
    from /home/luca/.rvm/gems/jruby-1.7.8/gems/therubyrhino-2.0.2/lib/rhino/wormhole.rb:25:in `to_javascript'
    from /home/luca/.rvm/gems/jruby-1.7.8/gems/therubyrhino-2.0.2/lib/rhino/wormhole.rb:72:in `hash_to_javascript'
    from org/jruby/RubyHash.java:1363:in `each_pair'
    from /home/luca/.rvm/gems/jruby-1.7.8/gems/therubyrhino-2.0.2/lib/rhino/wormhole.rb:71:in `hash_to_javascript'
    from /home/luca/.rvm/gems/jruby-1.7.8/gems/therubyrhino-2.0.2/lib/rhino/wormhole.rb:24:in `to_javascript'
    from /home/luca/.rvm/gems/jruby-1.7.8/gems/therubyrhino-2.0.2/lib/rhino/rhino_ext.rb:227:in `apply'
    from (irb):8:in `evaluate'
    from org/jruby/RubyKernel.java:1123:in `eval'
    from org/jruby/RubyKernel.java:1519:in `loop'
    from org/jruby/RubyKernel.java:1284:in `catch'
    from org/jruby/RubyKernel.java:1284:in `catch'
    from /home/luca/.rvm/rubies/jruby-1.7.8/bin/irb:13:in `(root)'
lucabelluccini commented 11 years ago

To detail a little more: https://gist.github.com/lucabelluccini/5cfb3362de69e067bf7f

kares commented 11 years ago

ctx['fun'].call a or ctx['fun'].methodcall nil, a (first arg is this) ... do not expect a['@timestamp2''] to be than set on the Ruby side (or maybe I'm wrong can't remember) ... you've set it on the JavaScript side. there's also a bug in the end likely caused by newer JRuby the trace you've linked.

lucabelluccini commented 11 years ago

The only workaround to me now is the following:

require 'rhino'
ctx = Rhino::Context.new
ctx.eval <<EOS

function JsRule() {
}
JsRule.prototype.process = function(iEvent) {
        result['onedate'] = new Date();
        return result;
}
jsrule = new JsRule();
EOS

jsrule = ctx['jsrule']

event = {}
event['s'] = {}
event['g'] = {}
event['@timestamp'] = Time.new

raw_processed_event = jsrule.process(event)

#allows to convert NativeObject to Hash (!!! the timestamp will be still NativeDate)
processed_event = raw_processed_event.to_hash
processed_event['@timestamp'] = Rhino.to_ruby(processed_event['@timestamp'])
# at this moment, the @timestamp will be properly seen as Time
# onedate will be still NativeDate!

In the prevous post, I tried to do: ctx['fun'].methodcall(a.to_java) and the data conversion works.

If I try: jsrule.process(event.to_java) complains about passing 2 params instead of 1.

On JRuby via rvm, both 1.7.5 and 1.7.8 are impacted.

kares commented 10 years ago

it's in as https://github.com/cowboyd/therubyrhino/commit/cac2b9512a5d82579b5cdb7f1c677a0ae6b0d590 ... please note (once again) that you've not used the exposed API correctly (comments above) ... methodcall is similar to JS' apply thus first argument is always this while call acts with Ruby semantics (no need to pass context as your examples seem to show case that you do not intend to). thanks!