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:
parent
5c2c4b0b85
commit
707973b3e5
5 changed files with 65 additions and 47 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Add table
Reference in a new issue