From 85363d2f14c69147669928eab1800b53acb3bc17 Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Mon, 17 May 2010 18:30:31 +0300 Subject: [PATCH] expose the array object as a subclass of function --- ext/v8/v8_array.cpp | 47 ++++++++++++++++++++++++++++++++++++++------- ext/v8/v8_obj.cpp | 31 ++++++++++++++++++------------ lib/v8.rb | 1 + lib/v8/array.rb | 11 +++++++++++ lib/v8/to.rb | 1 + 5 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 lib/v8/array.rb diff --git a/ext/v8/v8_array.cpp b/ext/v8/v8_array.cpp index bd32316..7a2845e 100644 --- a/ext/v8/v8_array.cpp +++ b/ext/v8/v8_array.cpp @@ -1,18 +1,51 @@ #include "v8_array.h" +#include "v8_ref.h" +#include "v8_obj.h" using namespace v8; -void rr_init_v8_array() { + +namespace { + VALUE ArrayClass; + + Local unwrap(VALUE self) { + return V8_Ref_Get(self); + } + + VALUE New(int argc, VALUE *argv, VALUE self) { + VALUE length; + rb_scan_args(argc, argv, "0", &length); + if (NIL_P(length)) { + length = INT2FIX(0); + } + return V8_Ref_Create(self, Array::New(NUM2INT(length))); + } + + VALUE Length(VALUE self) { + return rr_v82rb(unwrap(self)->Length()); + } + + VALUE CloneElementAt(VALUE self, VALUE index) { + return rr_v82rb(unwrap(self)->CloneElementAt(NUM2UINT(index))); + } +} + +void rr_init_v8_array() { + ArrayClass = rr_define_class("Array", rr_cV8_C_Object); + rr_define_singleton_method(ArrayClass, "New", New, -1); + rr_define_method(ArrayClass, "Length", Length, 0); + rr_define_method(ArrayClass, "CloneElementAt", CloneElementAt, 1); } VALUE rr_reflect_v8_array(Handle value) { Local array(Array::Cast(*value)); - VALUE rb_array = rb_ary_new2(array->Length()); - for (unsigned int i = 0; i < array->Length(); i++) { - Local value = array->Get(Integer::New(i)); - rb_ary_push(rb_array, rr_v82rb(value)); + Local peer = array->GetHiddenValue(String::New("TheRubyRacer::RubyObject")); + if (peer.IsEmpty()) { + VALUE arr = V8_Ref_Create(ArrayClass, array); + rb_iv_set(arr, "@context", rr_v82rb(Context::GetEntered())); + return arr; + } else { + return (VALUE)External::Unwrap(peer); } - return rb_array; - } \ No newline at end of file diff --git a/ext/v8/v8_obj.cpp b/ext/v8/v8_obj.cpp index 33efe10..fcdfb9d 100644 --- a/ext/v8/v8_obj.cpp +++ b/ext/v8/v8_obj.cpp @@ -10,11 +10,28 @@ using namespace v8; VALUE rr_cV8_C_Object; +namespace { + + Local unwrap(VALUE robj) { + return V8_Ref_Get(robj); + } + + VALUE Get(VALUE self, VALUE key) { + HandleScope handles; + Local obj(unwrap(self)); + if (rb_obj_is_kind_of(key, rb_cNumeric)) { + return rr_v82rb(obj->Get(NUM2UINT(key))); + } else { + return rr_v82rb(obj->Get(rr_rb2v8(rb_str_to_str(key)))); + } + } +} + void rr_init_obj() { rr_cV8_C_Object = rr_define_class("Object", rr_cV8_C_Value); rb_define_attr(rr_cV8_C_Object, "context", 1, 0); rr_define_singleton_method(rr_cV8_C_Object, "new", v8_Object_New, 0); - rr_define_method(rr_cV8_C_Object, "Get", v8_Object_Get, 1); + rr_define_method(rr_cV8_C_Object, "Get", Get, 1); rr_define_method(rr_cV8_C_Object, "Set", v8_Object_Set, 2); rr_define_method(rr_cV8_C_Object, "GetPropertyNames", v8_Object_GetPropertyNames, 0); rr_define_method(rr_cV8_C_Object, "ToString", v8_Object_ToString, 0); @@ -32,6 +49,7 @@ VALUE rr_reflect_v8_object(Handle value) { } } + v8::Handle rr_reflect_rb_object(VALUE value) { Local o = Racer_Create_V8_ObjectTemplate(value)->NewInstance(); o->SetHiddenValue(String::New("TheRubyRacer::RubyObject"), External::Wrap((void *) value)); @@ -39,9 +57,6 @@ v8::Handle rr_reflect_rb_object(VALUE value) { } namespace { - Local unwrap(VALUE robj) { - return V8_Ref_Get(robj); - } } VALUE v8_Object_New(VALUE clazz) { @@ -49,14 +64,6 @@ VALUE v8_Object_New(VALUE clazz) { return V8_Ref_Create(clazz, Object::New()); } -VALUE v8_Object_Get(VALUE self, VALUE key) { - HandleScope handles; - Local obj = unwrap(self); - VALUE keystr = rb_str_to_str(key); - Local value = obj->Get(rr_rb2v8(keystr)); - return rr_v82rb(value); -} - VALUE v8_Object_Set(VALUE self, VALUE key, VALUE value) { HandleScope handles; Local obj = unwrap(self); diff --git a/lib/v8.rb b/lib/v8.rb index ead59b5..5ce3999 100644 --- a/lib/v8.rb +++ b/lib/v8.rb @@ -7,6 +7,7 @@ module V8 require 'v8/to' require 'v8/context' require 'v8/object' + require 'v8/array' require 'v8/function' require 'v8/tap' end \ No newline at end of file diff --git a/lib/v8/array.rb b/lib/v8/array.rb new file mode 100644 index 0000000..b19f1f3 --- /dev/null +++ b/lib/v8/array.rb @@ -0,0 +1,11 @@ + +module V8 + class Array < V8::Object + + def each + for i in 0..(@native.Length() - 1) + yield To.ruby(@native.Get(i)) + end + end + end +end \ No newline at end of file diff --git a/lib/v8/to.rb b/lib/v8/to.rb index 3e37e3d..1b7beaa 100644 --- a/lib/v8/to.rb +++ b/lib/v8/to.rb @@ -5,6 +5,7 @@ module V8 def ruby(value) case value when V8::C::Function then V8::Function.new(value) + when V8::C::Array then V8::Array.new(value) when V8::C::Object then V8::Object.new(value) when V8::C::String then value.Utf8Value() else