From 222053b9015cef05cdbf47662c22a243cdfad49c Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Wed, 9 Jun 2010 00:59:22 +0300 Subject: [PATCH] ability to embed classes as constructors directly into the context. --- ext/v8/v8_template.cpp | 10 ++++++++++ lib/v8/access.rb | 38 ++++++++++++++++++++++---------------- spec/redjs | 2 +- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/ext/v8/v8_template.cpp b/ext/v8/v8_template.cpp index 52b2b52..ae5518c 100644 --- a/ext/v8/v8_template.cpp +++ b/ext/v8/v8_template.cpp @@ -169,6 +169,15 @@ namespace { rr_v8_ref_setref(ref, "code", code); return ref; } + 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)); + return Qnil; + } VALUE PrototypeTemplate(VALUE self) { HandleScope scope; return rr_v8_ref_create(ObjectTemplateClass, func(self)->PrototypeTemplate()); @@ -209,6 +218,7 @@ void rr_init_template() { 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_method(FunctionTemplateClass, "PrototypeTemplate", Func::PrototypeTemplate, 0); rr_define_method(FunctionTemplateClass, "InstanceTemplate", Func::InstanceTemplate, 0); rr_define_method(FunctionTemplateClass, "Inherit", Func::Inherit, 1); diff --git a/lib/v8/access.rb b/lib/v8/access.rb index f52c4a4..8a4c5da 100644 --- a/lib/v8/access.rb +++ b/lib/v8/access.rb @@ -1,5 +1,9 @@ require 'set' module V8 + + #TODO each context should get its own access rules instead of sharing them across + # contetxts + ###### --cowboyd 07/07/2010 class Access def self.[](cls) @access ||= Access.new @@ -29,7 +33,7 @@ module V8 NamedPropertyEnumerator ) if cls.name && cls.name =~ /(::)?(\w+?)$/ - t.SetClassName(C::String::NewSymbol($2)) + t.SetClassName(C::String::NewSymbol("rb::" + $2)) else t.SetClassName("Ruby") end @@ -65,25 +69,27 @@ module V8 class Constructors < Access def self.[](cls) - @constructors ||= Constructors.new - @constructors[cls] - end - - def template(cls) - t = C::FunctionTemplate::New() do |arguments| - rbargs = [] - for i in 0..arguments.Length() - 1 - rbargs << To.rb(arguments[i]) - end - instance = V8::Function.rubycall(cls.method(:new), *rbargs) - arguments.This().tap do |this| - this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), C::External::New(instance)) + Access[cls].tap do |template| + template.SetCallHandler() do |arguments| + wrap = nil + if arguments.Length() > 0 && arguments[0].kind_of?(C::External) + wrap = arguments[0] + else + rbargs = [] + for i in 0..arguments.Length() - 1 + rbargs << To.rb(arguments[i]) + end + instance = V8::Function.rubycall(cls.method(:new), *rbargs) + wrap = C::External::New(instance) + end + arguments.This().tap do |this| + this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), wrap) + end end end - t.Inherit(Access[cls]) - return t end end + class NamedPropertyGetter def self.call(property, info) name = To.rb(property) diff --git a/spec/redjs b/spec/redjs index 69c7cf3..43aaf4c 160000 --- a/spec/redjs +++ b/spec/redjs @@ -1 +1 @@ -Subproject commit 69c7cf355d38fda586f4eb1093b0043ecd9430c6 +Subproject commit 43aaf4c58cfa2c554a9975abd6f2a98faf0f504e