From a0af37906c70bbd5059c9b6e2abf707acf3ce0a2 Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Fri, 18 Dec 2009 09:48:06 +0200 Subject: [PATCH] start building out ruby interface --- ext/v8/convert_ruby.h | 5 +++-- ext/v8/convert_v8.h | 4 ++++ ext/v8/v8.cpp | 14 +++++++++++++- ext/v8/v8_cxt.cpp | 23 ++++++++++++++++++----- ext/v8/v8_cxt.h | 3 +++ ext/v8/v8_func.cpp | 10 ++++++++++ ext/v8/v8_func.h | 11 +++++++++++ ext/v8/v8_msg.cpp | 11 +++++++++++ ext/v8/v8_msg.h | 9 +++++++++ ext/v8/v8_obj.cpp | 31 +++++++++++++++++++++++++++++++ ext/v8/v8_obj.h | 11 +++++++++++ ext/v8/v8_template.cpp | 7 +++++++ ext/v8/v8_template.h | 1 + lib/v8.rb | 2 ++ lib/v8/context.rb | 29 ++++++++++++++++++++++------- lib/v8/object.rb | 12 ++++++++++++ lib/v8/to.rb | 23 +++++++++++++++++++++++ spec/redjs | 2 +- 18 files changed, 192 insertions(+), 16 deletions(-) create mode 100644 ext/v8/v8_func.cpp create mode 100644 ext/v8/v8_func.h create mode 100644 ext/v8/v8_msg.cpp create mode 100644 ext/v8/v8_msg.h create mode 100644 ext/v8/v8_obj.cpp create mode 100644 ext/v8/v8_obj.h create mode 100644 lib/v8/object.rb create mode 100644 lib/v8/to.rb diff --git a/ext/v8/convert_ruby.h b/ext/v8/convert_ruby.h index 55c7d30..37cf4f3 100644 --- a/ext/v8/convert_ruby.h +++ b/ext/v8/convert_ruby.h @@ -3,7 +3,8 @@ #include #include -#include +#include "v8_ref.h" +#include "v8_obj.h" #include /** @@ -94,7 +95,7 @@ class RubyValueDest { } VALUE pushObject(v8::Handle& value) { - return Qnil; + return V8_Ref_Create(V8_C_Object, value); } }; diff --git a/ext/v8/convert_v8.h b/ext/v8/convert_v8.h index e8e636b..88c7aaf 100644 --- a/ext/v8/convert_v8.h +++ b/ext/v8/convert_v8.h @@ -16,6 +16,10 @@ template class V8HandleSource { ~V8HandleSource() {} R operator() (v8::Handle& value) { + + if (value.IsEmpty()) { + return dest.pushNull(); + } if (value->IsUndefined()) { return dest.pushNull(); diff --git a/ext/v8/v8.cpp b/ext/v8/v8.cpp index 91bb97f..064c410 100644 --- a/ext/v8/v8.cpp +++ b/ext/v8/v8.cpp @@ -1,5 +1,8 @@ #include "v8_cxt.h" #include "v8_str.h" +#include "v8_obj.h" +#include "v8_msg.h" +#include "v8_func.h" #include "v8_script.h" #include "v8_template.h" #include "v8_standalone.h" @@ -51,6 +54,15 @@ extern "C" { rb_define_singleton_method(V8__C__ObjectTemplate, "new", (VALUE(*)(...))v8_ObjectTemplate_New, 0); VALUE V8__C__FunctionTemplate = rb_define_class_under(rb_mNative, "FunctionTemplate", V8__C__Template); - rb_define_singleton_method(V8__C__FunctionTemplate, "new", (VALUE(*)(...))v8_FunctionTemplate_New, -1); + rb_define_singleton_method(V8__C__FunctionTemplate, "new", (VALUE(*)(...))v8_FunctionTemplate_New, -1); + rb_define_method(V8__C__FunctionTemplate, "GetFunction", (VALUE(*)(...))v8_FunctionTemplate_GetFunction, 0); + + V8_C_Object = rb_define_class_under(rb_mNative, "Object", rb_cObject); + rb_define_singleton_method(V8_C_Object, "new", (VALUE(*)(...))v8_Object_New, 0); + rb_define_method(V8_C_Object, "Get", (VALUE(*)(...))v8_Object_Get, 1); + rb_define_method(V8_C_Object, "Set", (VALUE(*)(...))v8_Object_Set, 2); + + V8_C_Message = rb_define_class_under(rb_mNative, "Message", rb_cObject); + V8_C_Function = rb_define_class_under(rb_mNative, "Function", V8_C_Object); } } diff --git a/ext/v8/v8_cxt.cpp b/ext/v8/v8_cxt.cpp index b596865..fcdc40e 100644 --- a/ext/v8/v8_cxt.cpp +++ b/ext/v8/v8_cxt.cpp @@ -1,6 +1,6 @@ - #include "v8_cxt.h" -#include "ruby.h" +#include "v8_msg.h" +#include "converters.h" using namespace v8; @@ -17,18 +17,31 @@ VALUE v8_Context_New(int argc, VALUE *argv, VALUE self) { } VALUE v8_cxt_Global(VALUE self) { + HandleScope handles; + convert_v8_to_rb_t v82rb; Local cxt = V8_Ref_Get(self); - cxt->Global(); - return Qnil; + Local global = *cxt->Global(); + return v82rb(global); } VALUE v8_cxt_open(VALUE self) { HandleScope handles; + TryCatch exceptions; Local cxt = V8_Ref_Get(self); Context::Scope enter(cxt); if (rb_block_given_p()) { - return rb_yield(self); + printf("
About to execute Ruby Block
"); + VALUE result = rb_yield(self); + printf("
Ruby Block was executed
\n"); + if (exceptions.HasCaught()) { + return V8_Wrap_Message(exceptions.Message()); + } else { + printf("
No exception
"); + return result; + } + return result; } else { + printf("
No block given!
"); return Qnil; } } diff --git a/ext/v8/v8_cxt.h b/ext/v8/v8_cxt.h index 7c6159f..ac7bc78 100644 --- a/ext/v8/v8_cxt.h +++ b/ext/v8/v8_cxt.h @@ -5,6 +5,9 @@ #include "v8.h" #include "v8_ref.h" +extern VALUE rb_cV8; +extern VALUE V8_C_Object; + VALUE v8_Context_New(int argc, VALUE *argv, VALUE self); VALUE v8_cxt_Global(VALUE self); VALUE v8_cxt_open(VALUE self); diff --git a/ext/v8/v8_func.cpp b/ext/v8/v8_func.cpp new file mode 100644 index 0000000..c88b915 --- /dev/null +++ b/ext/v8/v8_func.cpp @@ -0,0 +1,10 @@ + +#include "v8_func.h" + +using namespace v8; + +VALUE V8_C_Function; + +VALUE V8_Wrap_Function(Handle f) { + return V8_Ref_Create(V8_C_Function, f); +} \ No newline at end of file diff --git a/ext/v8/v8_func.h b/ext/v8/v8_func.h new file mode 100644 index 0000000..e7f1379 --- /dev/null +++ b/ext/v8/v8_func.h @@ -0,0 +1,11 @@ +#ifndef _RUBY_V8_FUNCTION_ +#define _RUBY_V8_FUNCTION_ + +#include "v8.h" +#include "ruby.h" +#include "v8_ref.h" + +extern VALUE V8_C_Function; + +VALUE V8_Wrap_Function(v8::Handle f); +#endif \ No newline at end of file diff --git a/ext/v8/v8_msg.cpp b/ext/v8/v8_msg.cpp new file mode 100644 index 0000000..8622e0a --- /dev/null +++ b/ext/v8/v8_msg.cpp @@ -0,0 +1,11 @@ + +#include "v8_msg.h" +#include "v8_ref.h" + +using namespace v8; + +VALUE V8_C_Message; + +VALUE V8_Wrap_Message(Handle msg) { + return V8_Ref_Create(V8_C_Message, msg); +} \ No newline at end of file diff --git a/ext/v8/v8_msg.h b/ext/v8/v8_msg.h new file mode 100644 index 0000000..8408e20 --- /dev/null +++ b/ext/v8/v8_msg.h @@ -0,0 +1,9 @@ +#ifndef _RUBY_V8_MESSAGE_ +#define _RUBY_V8_MESSAGE_ + +#include "v8.h" +#include "ruby.h" + +extern VALUE V8_C_Message; +VALUE V8_Wrap_Message(v8::Handle msg); +#endif \ No newline at end of file diff --git a/ext/v8/v8_obj.cpp b/ext/v8/v8_obj.cpp new file mode 100644 index 0000000..4ae2a7f --- /dev/null +++ b/ext/v8/v8_obj.cpp @@ -0,0 +1,31 @@ +#include "v8_obj.h" +#include "v8_ref.h" +#include "converters.h" + +using namespace v8; + +VALUE V8_C_Object; + +VALUE v8_Object_New(VALUE clazz) { + HandleScope handles; + return V8_Ref_Create(clazz, Object::New()); +} + +VALUE v8_Object_Get(VALUE self, VALUE key) { + HandleScope handles; + convert_rb_to_v8_t rb2v8; + convert_v8_to_rb_t v82rb; + Local obj = V8_Ref_Get(self); + VALUE keystr = rb_funcall(key,rb_intern("to_s"), 0); + Local value = obj->Get(rb2v8(keystr)); + return v82rb(value); +} + +VALUE v8_Object_Set(VALUE self, VALUE key, VALUE value) { + HandleScope handles; + convert_rb_to_v8_t rb2v8; + Local obj = V8_Ref_Get(self); + VALUE keystr = rb_funcall(key, rb_intern("to_s"), 0); + obj->Set(rb2v8(keystr), rb2v8(value)); + return Qnil; +} diff --git a/ext/v8/v8_obj.h b/ext/v8/v8_obj.h new file mode 100644 index 0000000..7838f39 --- /dev/null +++ b/ext/v8/v8_obj.h @@ -0,0 +1,11 @@ +#ifndef _RUBY_V8_OBJECT_ +#define _RUBY_V8_OBJECT_ + +#include "ruby.h" + +extern VALUE V8_C_Object; + +VALUE v8_Object_New(VALUE clazz); +VALUE v8_Object_Get(VALUE self, VALUE key); +VALUE v8_Object_Set(VALUE self, VALUE key, VALUE value); +#endif \ No newline at end of file diff --git a/ext/v8/v8_template.cpp b/ext/v8/v8_template.cpp index 6a8ed6f..87080b3 100644 --- a/ext/v8/v8_template.cpp +++ b/ext/v8/v8_template.cpp @@ -1,6 +1,7 @@ #include #include #include "v8_ref.h" +#include "v8_func.h" #include "v8_template.h" #include "converters.h" @@ -49,3 +50,9 @@ VALUE v8_FunctionTemplate_New(int argc, VALUE *argv, VALUE self) { return V8_Ref_Create(self,t,code); } +VALUE v8_FunctionTemplate_GetFunction(VALUE self) { + HandleScope handles; + Local t = V8_Ref_Get(self); + return V8_Wrap_Function(t->GetFunction()); +} + diff --git a/ext/v8/v8_template.h b/ext/v8/v8_template.h index 7c09617..d05408e 100644 --- a/ext/v8/v8_template.h +++ b/ext/v8/v8_template.h @@ -6,5 +6,6 @@ VALUE v8_Template_Set(VALUE self, VALUE name, VALUE value); VALUE v8_ObjectTemplate_New(VALUE clazz); VALUE v8_FunctionTemplate_New(int argc, VALUE *argv, VALUE self); +VALUE v8_FunctionTemplate_GetFunction(VALUE self); #endif \ No newline at end of file diff --git a/lib/v8.rb b/lib/v8.rb index e570d13..a3ba7c8 100644 --- a/lib/v8.rb +++ b/lib/v8.rb @@ -4,5 +4,7 @@ $:.unshift(File.dirname(__FILE__)) unless module V8 VERSION = '0.4.0' require 'v8/v8' #native glue + require 'v8/to' require 'v8/context' + require 'v8/object' end \ No newline at end of file diff --git a/lib/v8/context.rb b/lib/v8/context.rb index 405b94f..9090678 100644 --- a/lib/v8/context.rb +++ b/lib/v8/context.rb @@ -8,24 +8,39 @@ module V8 def open(&block) @native.open do - block.call(self) if block + block.call(self).tap do |result| + # puts ERB::Util.h(result) + raise JavascriptError.new(result) if result.kind_of?(C::Message) + end end if block_given? end def eval(javascript) - self.open do - source = V8::C::String.new(javascript.to_s) - script = V8::C::Script.new(source) - script.Run() - end + source = V8::C::String.new(javascript.to_s) + script = V8::C::Script.new(source) + To.ruby(script.Run()) end def evaluate(*args) self.eval(*args) end + def []=(key, value) + value.tap do + @native.Global().tap do |scope| + scope.Set(key.to_s, To.v8(value)) + end + end + end + def self.open(&block) new.open(&block) - end + end + end + + class ContextError < StandardError + end + class JavascriptError < StandardError + end end \ No newline at end of file diff --git a/lib/v8/object.rb b/lib/v8/object.rb new file mode 100644 index 0000000..052d004 --- /dev/null +++ b/lib/v8/object.rb @@ -0,0 +1,12 @@ + +module V8 + class Object + def initialize(native) + @native = native + end + + def [](key) + To.ruby(@native.Get(To.v8(key))) + end + end +end \ No newline at end of file diff --git a/lib/v8/to.rb b/lib/v8/to.rb new file mode 100644 index 0000000..eb28c6d --- /dev/null +++ b/lib/v8/to.rb @@ -0,0 +1,23 @@ + +module V8 + module To + class << self + def ruby(value) + case value + when V8::C::Object then V8::Object.new(value) + else + value + end + end + + def v8(value) + case value + when String then C::String.new(value) + when Proc then C::FunctionTemplate.new(&value).GetFunction() + else + value + end + end + end + end +end \ No newline at end of file diff --git a/spec/redjs b/spec/redjs index 6dbd4cd..540f43d 160000 --- a/spec/redjs +++ b/spec/redjs @@ -1 +1 @@ -Subproject commit 6dbd4cd8edefb3e396dc6cdf90351f44f27297c9 +Subproject commit 540f43d897b928539bbb49243e899294dff9a0b5