diff --git a/ext/v8/context.cc b/ext/v8/context.cc index edae705..809f9b8 100644 --- a/ext/v8/context.cc +++ b/ext/v8/context.cc @@ -1,7 +1,6 @@ #include "rr.h" namespace rr { - VALUE ContextClass; VALUE New(VALUE ContextClass) { v8::Persistent context = v8::Context::New(); @@ -21,7 +20,7 @@ namespace rr { } void Context::Init() { - ContextClass = defineClass("Context"); + VALUE ContextClass = defineClass("Context"); RR_DEFINE_SINGLETON_METHOD(ContextClass, "New", &New, 0); RR_DEFINE_METHOD(ContextClass, "Enter", &Enter, 0); RR_DEFINE_METHOD(ContextClass, "Exit", &Exit, 0); diff --git a/ext/v8/extconf.rb b/ext/v8/extconf.rb index 46cba61..b8cec01 100644 --- a/ext/v8/extconf.rb +++ b/ext/v8/extconf.rb @@ -13,7 +13,6 @@ have_library('objc') if RUBY_PLATFORM =~ /darwin/ #since find_header() does not actually work as advertized. #see https://github.com/cowboyd/therubyracer/issues/91 $INCFLAGS.insert 0, "#{libv8_include_flags} " - $CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall" $CPPFLAGS += " -g" unless $CPPFLAGS.split.include? "-g" $CPPFLAGS += " -rdynamic" unless $CPPFLAGS.split.include? "-rdynamic" @@ -24,5 +23,7 @@ $LIBS << ' -lpthread ' CONFIG['LDSHARED'] = '$(CXX) -shared' unless RUBY_PLATFORM =~ /darwin/ +CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '') +CONFIG['warnflags'].gsub!('-Wimplicit-function-declaration', '') create_makefile('init') diff --git a/ext/v8/init.cc b/ext/v8/init.cc index f76d310..16c0432 100644 --- a/ext/v8/init.cc +++ b/ext/v8/init.cc @@ -9,5 +9,7 @@ using namespace rr; extern "C" { void Init_init() { Context::Init(); + String::Init(); + Script::Init(); } } \ No newline at end of file diff --git a/ext/v8/ref.cc b/ext/v8/ref.cc deleted file mode 100644 index 22a5d45..0000000 --- a/ext/v8/ref.cc +++ /dev/null @@ -1,37 +0,0 @@ -#include "rr.h" - -namespace rr { - template - Ref Ref::create(v8::Handle handle, VALUE klass) { - return Ref(new Holder(handle, klass)); - } - template - Ref::Ref(Ref::Holder* holder) { - this->holder = holder; - } - template - Ref::Ref(VALUE wrapper) { - Holder* holder = NULL; - Data_Get_Struct(wrapper, class Holder, holder) ; - this->holder = holder; - } - template - Ref::operator VALUE() { - return holder->value; - } - template - Ref::Holder::Holder(v8::Handle handle, VALUE klass) { - this->handle = v8::Persistent::New(handle); - this->value = Data_Wrap_Struct(klass, 0, &Holder::enqueue, this); - } - template - Ref::Holder::~Holder() { - this->handle.Dispose(); - } - template - void Ref::Holder::enqueue(Holder* holder) { - holder->value = Qnil; - printf("enqueuing a reference for garbage collection (should actually do something)\n"); - } -} - diff --git a/ext/v8/rr.h b/ext/v8/rr.h index 5ad9a70..ea09f6d 100644 --- a/ext/v8/rr.h +++ b/ext/v8/rr.h @@ -5,38 +5,86 @@ #include namespace rr { - /** - * A Reference to a V8 managed object - */ - template class Ref { + +class Value { +public: + Value(v8::Handle handle); + Value(VALUE value); + operator VALUE(); + operator v8::Handle(); + static void Init(); +protected: + v8::Handle value; + VALUE object; +}; + +class String : public Value { +public: + String(VALUE value); + operator v8::Handle(); + static void Init(); +}; + +/** +* A Reference to a V8 managed object +*/ +template class Ref { +public: + Ref(VALUE wrapper) { + Holder* holder = NULL; + Data_Get_Struct(wrapper, class Holder, holder) ; + this->holder = holder; + } + virtual operator VALUE() { + return holder->value; + } + virtual operator v8::Handle() { + return holder->handle; + } + static Ref create(v8::Handle handle, VALUE klass) { + return Ref(new Holder(handle, klass)); + } + inline v8::Handle operator->() const { return holder->handle; } +private: + class Holder { + friend class Ref; public: - Ref(VALUE wrapper); - virtual operator VALUE(); - static Ref create(v8::Handle handle, VALUE klass); - inline v8::Handle operator->() const { return holder->handle; } - private: - class Holder { - Holder(v8::Handle handle, VALUE klass); - virtual ~Holder(); + Holder(v8::Handle handle, VALUE klass) { + this->handle = v8::Persistent::New(handle); + this->value = Data_Wrap_Struct(klass, 0, &Holder::enqueue, this); + } + virtual ~Holder() { + handle.Dispose(); + } + protected: + VALUE value; + v8::Persistent handle; - VALUE value; - v8::Persistent handle; - friend class Ref; - - static void enqueue(Holder* holder); - }; - Ref(Holder* holder); - Holder* holder; + static void enqueue(Holder* holder) { + holder->value = Qnil; + printf("enqueuing a reference for garbage collection (should actually do something)\n"); + } }; - - class Context : public Ref { - public: - inline Context(VALUE value) : Ref(value) {}; - static void Init(); + Ref(Holder* holder) { + this->holder = holder; }; + Holder* holder; +}; - VALUE defineClass(const char *name, VALUE superclass = rb_cObject); - VALUE defineModule(const char *name); +class Context : public Ref { +public: + inline Context(VALUE value) : Ref(value) {}; + static void Init(); +}; + +class Script : public Ref { +public: + inline Script(VALUE value) : Ref(value) {}; + static void Init(); +}; + +VALUE defineClass(const char *name, VALUE superclass = rb_cObject); +VALUE defineModule(const char *name); } #define RR_DEFINE_METHOD(klass, name, impl, argc) rb_define_method(klass, name, (VALUE(*)(...))impl, argc) diff --git a/ext/v8/script.cc b/ext/v8/script.cc new file mode 100644 index 0000000..768d25e --- /dev/null +++ b/ext/v8/script.cc @@ -0,0 +1,24 @@ +#include "rr.h" + +namespace rr { +namespace { + +VALUE New(VALUE klass, VALUE source, VALUE filename) { + v8::HandleScope scope; + return Ref::create(v8::Script::New(String(source), Value(filename)), klass); +} + +VALUE Run(VALUE self) { + v8::HandleScope scope; + return Value(Script(self)->Run()); +} + +} + +void Script::Init() { + VALUE ScriptClass = defineClass("Script"); + RR_DEFINE_SINGLETON_METHOD(ScriptClass, "New", &New, 2); + RR_DEFINE_METHOD(ScriptClass, "Run", &Run, 0); +} + +} \ No newline at end of file diff --git a/ext/v8/string.cc b/ext/v8/string.cc new file mode 100644 index 0000000..e29c387 --- /dev/null +++ b/ext/v8/string.cc @@ -0,0 +1,19 @@ +#include "rr.h" + +namespace rr { + String::String(VALUE object) : Value(object) {} + String::operator v8::Handle() { + return v8::String::New(RSTRING_PTR(object), (int)RSTRING_LEN(object)); + } + +namespace { + VALUE New(VALUE StringClass, VALUE string) { + return Ref::create(String(string), StringClass); + } +} + +void String::Init() { + VALUE StringClass = defineClass("String"); + RR_DEFINE_SINGLETON_METHOD(StringClass, "New", &New, 1); +} +} \ No newline at end of file diff --git a/ext/v8/value.cc b/ext/v8/value.cc new file mode 100644 index 0000000..34b9a83 --- /dev/null +++ b/ext/v8/value.cc @@ -0,0 +1,86 @@ +#include "rr.h" + +namespace rr { + Value::Value(v8::Handle value) { + this->value = value; + } + Value::Value(VALUE object) { + this->object = object; + } + Value::operator VALUE() { + if (value.IsEmpty() || value->IsUndefined() || value->IsNull()) { + return Qnil; + } + if (value->IsExternal()) { + return Qnil; + } + if (value->IsUint32()) { + return UINT2NUM(value->Uint32Value()); + } + if (value->IsInt32()) { + return INT2FIX(value->Int32Value()); + } + if (value->IsBoolean()) { + return value->BooleanValue() ? Qtrue : Qfalse; + } + if (value->IsNumber()) { + return rb_float_new(value->NumberValue()); + } + if (value->IsString()) { + return String::Value(value); + } + if (value->IsFunction()) { + // return Function(value); + } + if (value->IsArray()) { + // return Array(value); + } + if (value->IsDate()) { + // return rr_reflect_v8_date(value); + } + if (value->IsObject()) { + // return Object(value); + } + return Qnil; + } + Value::operator v8::Handle() { + switch (TYPE(object)) { + case T_FIXNUM: + // TODO: use this conversion if value will fit in 32 bits. + // return Integer::New(FIX2LONG(value)); + case T_FLOAT: + // return Number::New(NUM2DBL(value)); + case T_STRING: + return (v8::Handle)String(object); + case T_NIL: + return v8::Null(); + case T_TRUE: + return v8::True(); + case T_FALSE: + return v8::False(); + case T_DATA: + return Ref(object); + case T_OBJECT: + case T_CLASS: + case T_ICLASS: + case T_MODULE: + case T_REGEXP: + case T_MATCH: + case T_ARRAY: + case T_HASH: + case T_STRUCT: + case T_BIGNUM: + case T_FILE: + case T_SYMBOL: + // case T_BLKTAG: (not in 1.9) + case T_UNDEF: + // case T_VARMAP: (not in 1.9) + // case T_SCOPE: (not in 1.9) + case T_NODE: + default: + rb_warn("unknown conversion to V8 for: %s", RSTRING_PTR(rb_inspect(object))); + return v8::String::New("Undefined Conversion"); + } + return v8::Undefined(); + } +} \ No newline at end of file diff --git a/lib/v8/context.rb b/lib/v8/context.rb index 9f54f07..4f962dc 100644 --- a/lib/v8/context.rb +++ b/lib/v8/context.rb @@ -6,7 +6,11 @@ module V8 end def eval(source, filename = '', line = 1) - nil + @native.Enter() + script = V8::C::Script::New(source.to_s, filename.to_s) + script.Run() + ensure + @native.Exit() end end end \ No newline at end of file