diff --git a/lib/v8/conversion.rb b/lib/v8/conversion.rb index 64f3fdf..6fb3af9 100644 --- a/lib/v8/conversion.rb +++ b/lib/v8/conversion.rb @@ -140,3 +140,28 @@ class Symbol V8::C::Symbol::For(context.isolate.native, V8::C::String::NewFromUtf8(isolate, to_s)) end end + +class Object + def to_v8(context) + V8::C::Object::New(context.isolate.native) + end +end + +class Proc + def to_v8(context) + isolate = context.isolate.native + callback = lambda do |info| + args = [] + arity = info.Length() + if self.arity > -1 + arity = self.arity + end + arity.times do |i| + args << context.to_ruby(info[i]) + end + result = context.to_v8 self.call(*args) + info.GetReturnValue().Set(result) + end + V8::C::Function::New(isolate, callback) + end +end diff --git a/lib/v8/conversion/fundamental.rb b/lib/v8/conversion/fundamental.rb index 9e780b8..9c9afd7 100644 --- a/lib/v8/conversion/fundamental.rb +++ b/lib/v8/conversion/fundamental.rb @@ -43,7 +43,18 @@ class V8::Conversion # First it checks to see if there is an entry in the id map for # this object. Otherwise, it will run the default conversion. def to_v8(context, ruby_object) - rb_idmap[ruby_object.object_id] || ruby_object.to_v8(context) + if v8_object = rb_idmap[ruby_object.object_id] + v8_object + else + v8_object = ruby_object.to_v8(context) + if v8_object.kind_of? V8::C::Object + v8_object.tap do + equate ruby_object, v8_object + end + else + v8_object + end + end end ## diff --git a/spec/v8/context_spec.rb b/spec/v8/context_spec.rb index 60f78a7..d441303 100644 --- a/spec/v8/context_spec.rb +++ b/spec/v8/context_spec.rb @@ -93,12 +93,12 @@ describe "V8::Context" do end end - # xit "unwraps ruby objects returned by embedded ruby code to maintain referential integrity" do - # Object.new.tap do |o| - # @cxt['get'] = lambda {o} - # @cxt.eval('get()').should be(o) - # end - # end + it "unwraps ruby objects returned by embedded ruby code to maintain referential integrity" do + Object.new.tap do |o| + @cxt['get'] = lambda {o} + @cxt.eval('get()').should be(o) + end + end it "always returns the same ruby object for a single javascript object" do obj = @cxt.eval('obj = {}') @@ -133,25 +133,25 @@ describe "V8::Context" do # end end -# describe "Calling Ruby Code From Within Javascript", :compat => '0.1.0' do + describe "Calling Ruby Code From Within Javascript" do -# before(:each) do + before(:each) do # @class = Class.new # @instance = @class.new -# @cxt = V8::Context.new + @cxt = V8::Context.new # @cxt['o'] = @instance -# end + end -# xit "can embed a closure into a context and call it" do -# @cxt["say"] = lambda { |*args| args[-2] * args[-1] } -# @cxt.eval("say('Hello', 2)").should == "HelloHello" -# end + it "can embed a closure into a context and call it" do + @cxt["say"] = lambda { |*args| args[-2] * args[-1] } + @cxt.eval("say('Hello', 2)").should == "HelloHello" + end -# xit "recognizes the same closure embedded into the same context as the same function object" do -# @cxt['say'] = @cxt['declare'] = lambda { |*args| args } -# @cxt.eval('say == declare').should be(true) -# @cxt.eval('say === declare').should be(true) -# end + it "recognizes the same closure embedded into the same context as the same function object" do + @cxt['say'] = @cxt['declare'] = lambda { |*args| args } + @cxt.eval('say == declare').should be(true) + @cxt.eval('say === declare').should be(true) + end # xit "translates ruby Array to Javascript Array" do # class_eval do @@ -275,17 +275,17 @@ describe "V8::Context" do # @cxt.eval('typeof(RObject)').should == 'function' # end -# xit "truncates lambda arguments passed in to match the arity of the function", :compat => '0.4.2' do -# @cxt['testing'] = lambda { |arg| arg } -# lambda { -# @cxt.eval('testing(1,2,3)') -# }.should_not raise_error + it "truncates lambda arguments passed in to match the arity of the function", :compat => '0.4.2' do + @cxt['testing'] = lambda { |arg| arg } + lambda { + @cxt.eval('testing(1,2,3)') + }.should_not raise_error -# @cxt['testing'] = lambda { } -# lambda { -# @cxt.eval('testing(1,2,3)') -# }.should_not raise_error -# end + @cxt['testing'] = lambda { } + lambda { + @cxt.eval('testing(1,2,3)') + }.should_not raise_error + end # xit "truncates method arguments passed in to match the arity of the function", :compat => '0.4.3' do # @instance.instance_eval do @@ -652,7 +652,7 @@ describe "V8::Context" do # @class.class_eval &body # end -# end + end describe "Calling JavaScript Code From Within Ruby", :compat => '0.1.0' do