mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
call JavaScript functions from Ruby
This commit is contained in:
parent
8be240196c
commit
e60b22f8d2
9 changed files with 86 additions and 4 deletions
|
@ -1,3 +1,6 @@
|
|||
=== Edge
|
||||
* 1 major enhancement
|
||||
* call JavaScript functions from Ruby
|
||||
=== 0.6.0 2010-03-31
|
||||
* 4 major enhancements
|
||||
* ruby 1.9 compatible
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "v8_ref.h"
|
||||
#include "v8_obj.h"
|
||||
#include "v8_cxt.h"
|
||||
#include "v8_func.h"
|
||||
#include "v8_template.h"
|
||||
|
||||
using namespace v8;
|
||||
|
@ -16,6 +17,7 @@ VALUE V8_To;
|
|||
VALUE V82RB(Handle<Value>& value) {
|
||||
convert_v8_to_rb_t convert;
|
||||
VALUE result;
|
||||
VALUE type = V8_C_Object;
|
||||
if(convert(value, result)) {
|
||||
return result;
|
||||
}
|
||||
|
@ -30,18 +32,21 @@ VALUE V82RB(Handle<Value>& value) {
|
|||
return rb_array;
|
||||
}
|
||||
|
||||
if (value->IsFunction()) {
|
||||
type = V8_C_Function;
|
||||
}
|
||||
|
||||
if (value->IsObject()) {
|
||||
Local<Object> object(Object::Cast(*value));
|
||||
Local<Value> peer = object->GetHiddenValue(String::New("TheRubyRacer::RubyObject"));
|
||||
if (peer.IsEmpty()) {
|
||||
VALUE context_ref = V8_Ref_Create(V8_C_Context, Context::GetCurrent());
|
||||
object->SetHiddenValue(String::New("TheRubyRacer::Context"), External::Wrap((void *)context_ref));
|
||||
return V8_Ref_Create(V8_C_Object, value, context_ref);
|
||||
return V8_Ref_Create(type, value, context_ref);
|
||||
} else {
|
||||
return (VALUE)External::Unwrap(peer);
|
||||
}
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,5 +86,6 @@ extern "C" {
|
|||
|
||||
|
||||
V8_C_Function = rb_define_class_under(rb_mNative, "Function", V8_C_Object);
|
||||
rb_define_method(V8_C_Function, "Call", (VALUE(*)(...))v8_C_Function_Call, -1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include "converters.h"
|
||||
#include "v8_func.h"
|
||||
|
||||
using namespace v8;
|
||||
|
@ -8,3 +9,20 @@ VALUE V8_C_Function;
|
|||
VALUE V8_Wrap_Function(Handle<Function> f) {
|
||||
return V8_Ref_Create(V8_C_Function, f);
|
||||
}
|
||||
|
||||
|
||||
VALUE v8_C_Function_Call(int argc, VALUE *argv, VALUE self) {
|
||||
HandleScope handles;
|
||||
VALUE recv; VALUE f_argv;
|
||||
rb_scan_args(argc, argv, "1*", &recv, &f_argv);
|
||||
|
||||
Local<Function> function = V8_Ref_Get<Function>(self);
|
||||
Local<Object> thisObject(Object::Cast(*RB2V8(recv)));
|
||||
int f_argc = argc - 1;
|
||||
Local<Value> arguments[f_argc];
|
||||
for (int i = 0; i < f_argc; i++) {
|
||||
arguments[i] = RB2V8(rb_ary_entry(f_argv,i));
|
||||
}
|
||||
Local<Value> result = function->Call(thisObject, f_argc, arguments);
|
||||
return V82RB(result);
|
||||
}
|
|
@ -8,4 +8,6 @@
|
|||
extern VALUE V8_C_Function;
|
||||
|
||||
VALUE V8_Wrap_Function(v8::Handle<v8::Function> f);
|
||||
|
||||
VALUE v8_C_Function_Call(int argc, VALUE *argv, VALUE self);
|
||||
#endif
|
|
@ -7,5 +7,6 @@ module V8
|
|||
require 'v8/to'
|
||||
require 'v8/context'
|
||||
require 'v8/object'
|
||||
require 'v8/function'
|
||||
require 'v8/tap'
|
||||
end
|
9
lib/v8/function.rb
Normal file
9
lib/v8/function.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
module V8
|
||||
class Function < V8::Object
|
||||
|
||||
def call(thisObject, *args)
|
||||
To.ruby(@native.Call(To.v8(thisObject), *args.map {|a| To.v8(a)}))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -4,6 +4,7 @@ module V8
|
|||
class << self
|
||||
def ruby(value)
|
||||
case value
|
||||
when V8::C::Function then V8::Function.new(value)
|
||||
when V8::C::Object then V8::Object.new(value)
|
||||
when V8::C::String then "Wonkers!"
|
||||
else
|
||||
|
|
42
spec/ext/func_spec.rb
Normal file
42
spec/ext/func_spec.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
require "#{File.dirname(__FILE__)}/../spec_helper.rb"
|
||||
|
||||
include V8
|
||||
|
||||
describe C::Function do
|
||||
it "is callable" do
|
||||
C::Context.new.open do |cxt|
|
||||
f = cxt.eval('(function() {return "Hello World"})', '<eval>');
|
||||
f.Call(cxt.Global).should == "Hello World"
|
||||
end
|
||||
end
|
||||
|
||||
it "receives proper argument length from ruby" do
|
||||
C::Context.new.open do |cxt|
|
||||
f = cxt.eval('(function() {return arguments.length})', 'eval')
|
||||
f.Call(nil,1, 2, 3).should == 3
|
||||
end
|
||||
end
|
||||
|
||||
it "maps all arguments from ruby" do
|
||||
C::Context.new.open do |cxt|
|
||||
f = cxt.eval('(function(one, two, three) {return one + two + three})', 'eval')
|
||||
f.Call(nil, 1,2,3).should == 6
|
||||
end
|
||||
end
|
||||
|
||||
it "properly maps ruby objects back and forth from arguments to return value" do
|
||||
C::Context.new.open do |cxt|
|
||||
Object.new.tap do |this|
|
||||
f = cxt.eval('(function() {return this})', 'eval')
|
||||
f.Call(this).should be(this)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "can be called outside of a context" do
|
||||
C::Context.new.open do |cxt|
|
||||
@f = cxt.eval('(function() {return "Call Me"})', 'eval')
|
||||
end
|
||||
@f.Call(nil).should == "Call Me"
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue