1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

bring low-level function template callbacks more in line with the way V8 does it.

This commit is contained in:
Charles Lowell 2011-04-25 21:24:05 -05:00
parent 5c2c4b0b85
commit 707973b3e5
5 changed files with 65 additions and 47 deletions

View file

@ -86,7 +86,7 @@ namespace {
return rr_v82rb(args(self)->isConstructCall);
}
VALUE _Data(VALUE self) {
return rr_v82rb(info(self)->data);
return rb_iv_get(self, "data");
}
struct WrapAccessorInfo : Wrap {

View file

@ -39,10 +39,17 @@ namespace {
}
Handle<Value> RubyInvocationCallback(const Arguments& args) {
VALUE code = (VALUE)External::Unwrap(args.Data());
VALUE v8_data = (VALUE)External::Unwrap(args.Data());
VALUE handler = rb_hash_lookup(v8_data, "handler");
VALUE data = rb_hash_lookup(v8_data, "data");
VALUE rb_args = rr_v82rb(args);
VALUE result = rb_funcall(code, rb_intern("call"), 1, rb_args);
rb_iv_set(rb_args, "data", data);
if (RTEST(handler)) {
VALUE result = rb_funcall(handler, rb_intern("call"), 1, rb_args);
return rr_rb2v8(result);
} else {
return Handle<Value>();
}
}
namespace Obj {
@ -259,26 +266,25 @@ namespace {
namespace Func {
VALUE New(VALUE function_template) {
HandleScope handles;
VALUE code = rb_block_proc();
if (NIL_P(code)) {
return Qnil;
Handle<Value> make_v8_data(int argc, VALUE *argv, const char* argf) {
VALUE handler; VALUE data;
rb_scan_args(argc, argv, argf, &handler, &data);
VALUE v8_data = rb_hash_new();
rb_hash_aset(v8_data, "handler", handler);
rb_hash_aset(v8_data, "data", data);
return rr_v8_external_create(v8_data);
}
Local<FunctionTemplate> templ = FunctionTemplate::New(RubyInvocationCallback, rr_v8_external_create(code));
VALUE ref = rr_v8_handle_new(function_template,templ);
//TODO: make sure that this reference is retained, if necessary.
// rr_v8_ref_setref(ref, "code", code);
return ref;
VALUE New(int argc, VALUE *argv, VALUE self) {
HandleScope h;
Handle<Value> v8_data = make_v8_data(argc, argv, "02");
Local<FunctionTemplate> t = FunctionTemplate::New(RubyInvocationCallback, v8_data);
return rr_v8_handle_new(self,t);
}
VALUE SetCallHandler(VALUE self) {
HandleScope handles;
VALUE code = rb_block_proc();
if (NIL_P(code)) {
return Qnil;
}
func(self)->SetCallHandler(RubyInvocationCallback, rr_v8_external_create(code));
VALUE SetCallHandler(int argc, VALUE *argv, VALUE self) {
HandleScope h;
Handle<Value> v8_data = make_v8_data(argc, argv, "11");
func(self)->SetCallHandler(RubyInvocationCallback, v8_data);
return Qnil;
}
VALUE PrototypeTemplate(VALUE self) {
@ -322,8 +328,8 @@ void rr_init_template() {
rr_define_method(ObjectTemplateClass, "SetCallAsFunctionHandler", Obj::SetCallAsFunctionHandler, 0);
FunctionTemplateClass = rr_define_class("FunctionTemplate", Template);
rr_define_singleton_method(FunctionTemplateClass, "New", Func::New, 0);
rr_define_method(FunctionTemplateClass, "SetCallHandler", Func::SetCallHandler, 0);
rr_define_singleton_method(FunctionTemplateClass, "New", Func::New, -1);
rr_define_method(FunctionTemplateClass, "SetCallHandler", Func::SetCallHandler, -1);
rr_define_method(FunctionTemplateClass, "PrototypeTemplate", Func::PrototypeTemplate, 0);
rr_define_method(FunctionTemplateClass, "InstanceTemplate", Func::InstanceTemplate, 0);
rr_define_method(FunctionTemplateClass, "Inherit", Func::Inherit, 1);

View file

@ -11,7 +11,7 @@ module V8
constructor = nil
template = if with
constructor = @to.js_constructor_for(with.class)
constructor.SetCallHandler(&method(:tmp))
constructor.SetCallHandler(method(:tmp))
template = constructor.InstanceTemplate()
else
C::ObjectTemplate::New()
@ -20,13 +20,14 @@ module V8
@native.enter do
@global = @native.Global()
@to.proxies.register_javascript_proxy @global, :for => with if with
constructor.SetCallHandler(&@to.method(:invoke_non_callable_constructor)) if constructor
constructor.SetCallHandler(@to.method(:invoke_non_callable_constructor)) if constructor
@scope = @to.rb(@global)
@global.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext"), C::External::New(self))
end
yield(self) if block_given?
end
#TODO: get rid of this.
def tmp(arguments)
return arguments.This()
end

View file

@ -28,13 +28,16 @@ module V8
for i in 0..arguments.Length() - 1
rbargs << rb(arguments[i])
end
cls = arguments.Data()
instance = rubysend(cls, :new, *rbargs)
end
@proxies.register_javascript_proxy arguments.This(), :for => instance
rescue StandardError => e
warn e
end
def make_js_constructor(cls)
template = C::FunctionTemplate::New(&method(:invoke_non_callable_constructor))
template = C::FunctionTemplate::New(method(:invoke_non_callable_constructor))
setuptemplate(template.InstanceTemplate())
if cls != ::Object && cls.superclass != ::Object && cls.superclass != ::Class
template.Inherit(js_constructor_for(cls.superclass))
@ -52,11 +55,11 @@ module V8
constructor = js_constructor_for(ruby_class)
function = constructor.GetFunction()
unless constructor.respond_to?(:embedded)
constructor.SetCallHandler(&method(:invoke_callable_constructor))
constructor.SetCallHandler(method(:invoke_callable_constructor), ruby_class)
#create a prototype so that this constructor also acts like a ruby object
prototype = rubytemplate.NewInstance()
#set *that* object's prototype to an empty function so that it will look and behave like a function.
prototype.SetPrototype(C::FunctionTemplate::New() {}.GetFunction())
prototype.SetPrototype(C::FunctionTemplate::New().GetFunction())
function.SetPrototype(prototype)
def constructor.embedded?;true;end
end

View file

@ -11,21 +11,34 @@ module V8
end
def Proc(p)
#TODO: check this for memory leaks
@procs[p] ||= begin
template = C::FunctionTemplate::New() do |arguments|
rbargs = []
for i in 0..arguments.Length() - 1
rbargs << @portal.rb(arguments[i])
end
@portal.rubycall(p, *rbargs)
end
template = C::FunctionTemplate::New(method(:callproc), p)
template.GetFunction()
end
end
def UnboundMethod(method)
#TODO: check this for memory leaks.
@methods[method.to_s] ||= begin
template = C::FunctionTemplate::New() do |arguments|
template = C::FunctionTemplate::New(method(:callmethod), method)
template.GetFunction()
end
end
alias_method :Method, :Proc
def callproc(arguments)
proc = arguments.Data()
rbargs = []
for i in 0..arguments.Length() - 1
rbargs << @portal.rb(arguments[i])
end
@portal.rubycall(proc, *rbargs)
end
def callmethod(arguments)
method = arguments.Data()
rbargs = []
for i in 0..arguments.Length() - 1
rbargs << @portal.rb(arguments[i])
@ -35,11 +48,6 @@ module V8
method.bind(this).call(*rbargs)
end
end
template.GetFunction()
end
end
alias_method :Method, :Proc
end
end
end