mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
Embed lambdas and procs into V8::Context
This adds the ability embed basic Ruby code blocks into a javascript context and invoke it. cxt = V8::Context.new cxt['twice'] = lambda {|str| "#{str}#{str}"} cxt.eval('twice("hi")') #=> "hihi" Note that error handling is not accounted for yet. If an exception happens inside the called proc, it will cause terrible, awful things to happen because portions of the C++ stack will not be unwound leaving the Isolate in an indeterminate state.
This commit is contained in:
parent
d4c68dfc62
commit
250b8e7d50
3 changed files with 67 additions and 31 deletions
|
@ -140,3 +140,28 @@ class Symbol
|
||||||
V8::C::Symbol::For(context.isolate.native, V8::C::String::NewFromUtf8(isolate, to_s))
|
V8::C::Symbol::For(context.isolate.native, V8::C::String::NewFromUtf8(isolate, to_s))
|
||||||
end
|
end
|
||||||
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
|
||||||
|
|
|
@ -43,7 +43,18 @@ class V8::Conversion
|
||||||
# First it checks to see if there is an entry in the id map for
|
# First it checks to see if there is an entry in the id map for
|
||||||
# this object. Otherwise, it will run the default conversion.
|
# this object. Otherwise, it will run the default conversion.
|
||||||
def to_v8(context, ruby_object)
|
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
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -93,12 +93,12 @@ describe "V8::Context" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# xit "unwraps ruby objects returned by embedded ruby code to maintain referential integrity" do
|
it "unwraps ruby objects returned by embedded ruby code to maintain referential integrity" do
|
||||||
# Object.new.tap do |o|
|
Object.new.tap do |o|
|
||||||
# @cxt['get'] = lambda {o}
|
@cxt['get'] = lambda {o}
|
||||||
# @cxt.eval('get()').should be(o)
|
@cxt.eval('get()').should be(o)
|
||||||
# end
|
end
|
||||||
# end
|
end
|
||||||
|
|
||||||
it "always returns the same ruby object for a single javascript object" do
|
it "always returns the same ruby object for a single javascript object" do
|
||||||
obj = @cxt.eval('obj = {}')
|
obj = @cxt.eval('obj = {}')
|
||||||
|
@ -133,25 +133,25 @@ describe "V8::Context" do
|
||||||
# end
|
# end
|
||||||
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
|
# @class = Class.new
|
||||||
# @instance = @class.new
|
# @instance = @class.new
|
||||||
# @cxt = V8::Context.new
|
@cxt = V8::Context.new
|
||||||
# @cxt['o'] = @instance
|
# @cxt['o'] = @instance
|
||||||
# end
|
end
|
||||||
|
|
||||||
# xit "can embed a closure into a context and call it" do
|
it "can embed a closure into a context and call it" do
|
||||||
# @cxt["say"] = lambda { |*args| args[-2] * args[-1] }
|
@cxt["say"] = lambda { |*args| args[-2] * args[-1] }
|
||||||
# @cxt.eval("say('Hello', 2)").should == "HelloHello"
|
@cxt.eval("say('Hello', 2)").should == "HelloHello"
|
||||||
# end
|
end
|
||||||
|
|
||||||
# xit "recognizes the same closure embedded into the same context as the same function object" do
|
it "recognizes the same closure embedded into the same context as the same function object" do
|
||||||
# @cxt['say'] = @cxt['declare'] = lambda { |*args| args }
|
@cxt['say'] = @cxt['declare'] = lambda { |*args| args }
|
||||||
# @cxt.eval('say == declare').should be(true)
|
@cxt.eval('say == declare').should be(true)
|
||||||
# @cxt.eval('say === declare').should be(true)
|
@cxt.eval('say === declare').should be(true)
|
||||||
# end
|
end
|
||||||
|
|
||||||
# xit "translates ruby Array to Javascript Array" do
|
# xit "translates ruby Array to Javascript Array" do
|
||||||
# class_eval do
|
# class_eval do
|
||||||
|
@ -275,17 +275,17 @@ describe "V8::Context" do
|
||||||
# @cxt.eval('typeof(RObject)').should == 'function'
|
# @cxt.eval('typeof(RObject)').should == 'function'
|
||||||
# end
|
# end
|
||||||
|
|
||||||
# xit "truncates lambda arguments passed in to match the arity of the function", :compat => '0.4.2' do
|
it "truncates lambda arguments passed in to match the arity of the function", :compat => '0.4.2' do
|
||||||
# @cxt['testing'] = lambda { |arg| arg }
|
@cxt['testing'] = lambda { |arg| arg }
|
||||||
# lambda {
|
lambda {
|
||||||
# @cxt.eval('testing(1,2,3)')
|
@cxt.eval('testing(1,2,3)')
|
||||||
# }.should_not raise_error
|
}.should_not raise_error
|
||||||
|
|
||||||
# @cxt['testing'] = lambda { }
|
@cxt['testing'] = lambda { }
|
||||||
# lambda {
|
lambda {
|
||||||
# @cxt.eval('testing(1,2,3)')
|
@cxt.eval('testing(1,2,3)')
|
||||||
# }.should_not raise_error
|
}.should_not raise_error
|
||||||
# end
|
end
|
||||||
|
|
||||||
# xit "truncates method arguments passed in to match the arity of the function", :compat => '0.4.3' do
|
# xit "truncates method arguments passed in to match the arity of the function", :compat => '0.4.3' do
|
||||||
# @instance.instance_eval do
|
# @instance.instance_eval do
|
||||||
|
@ -652,7 +652,7 @@ describe "V8::Context" do
|
||||||
# @class.class_eval &body
|
# @class.class_eval &body
|
||||||
# end
|
# end
|
||||||
|
|
||||||
# end
|
end
|
||||||
|
|
||||||
describe "Calling JavaScript Code From Within Ruby", :compat => '0.1.0' do
|
describe "Calling JavaScript Code From Within Ruby", :compat => '0.1.0' do
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue