1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

support for basic evaluation.

This commit is contained in:
Charles Lowell 2012-05-02 16:15:11 -07:00
parent 3c2ca322c5
commit 451211fb72
9 changed files with 214 additions and 68 deletions

View file

@ -1,7 +1,6 @@
#include "rr.h"
namespace rr {
VALUE ContextClass;
VALUE New(VALUE ContextClass) {
v8::Persistent<v8::Context> 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);

View file

@ -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')

View file

@ -9,5 +9,7 @@ using namespace rr;
extern "C" {
void Init_init() {
Context::Init();
String::Init();
Script::Init();
}
}

View file

@ -1,37 +0,0 @@
#include "rr.h"
namespace rr {
template<typename T>
Ref<T> Ref<T>::create(v8::Handle<T> handle, VALUE klass) {
return Ref<T>(new Holder(handle, klass));
}
template<typename T>
Ref<T>::Ref(Ref<T>::Holder* holder) {
this->holder = holder;
}
template<typename T>
Ref<T>::Ref(VALUE wrapper) {
Holder* holder = NULL;
Data_Get_Struct(wrapper, class Holder, holder) ;
this->holder = holder;
}
template<typename T>
Ref<T>::operator VALUE() {
return holder->value;
}
template<typename T>
Ref<T>::Holder::Holder(v8::Handle<T> handle, VALUE klass) {
this->handle = v8::Persistent<T>::New(handle);
this->value = Data_Wrap_Struct(klass, 0, &Holder::enqueue, this);
}
template<typename T>
Ref<T>::Holder::~Holder() {
this->handle.Dispose();
}
template<typename T>
void Ref<T>::Holder::enqueue(Holder* holder) {
holder->value = Qnil;
printf("enqueuing a reference for garbage collection (should actually do something)\n");
}
}

View file

@ -5,38 +5,86 @@
#include <ruby.h>
namespace rr {
/**
* A Reference to a V8 managed object
*/
template <class T> class Ref {
class Value {
public:
Value(v8::Handle<v8::Value> handle);
Value(VALUE value);
operator VALUE();
operator v8::Handle<v8::Value>();
static void Init();
protected:
v8::Handle<v8::Value> value;
VALUE object;
};
class String : public Value {
public:
String(VALUE value);
operator v8::Handle<v8::String>();
static void Init();
};
/**
* A Reference to a V8 managed object
*/
template <class T> class Ref {
public:
Ref<T>(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<T>() {
return holder->handle;
}
static Ref<T> create(v8::Handle<T> handle, VALUE klass) {
return Ref<T>(new Holder(handle, klass));
}
inline v8::Handle<T> operator->() const { return holder->handle; }
private:
class Holder {
friend class Ref;
public:
Ref<T>(VALUE wrapper);
virtual operator VALUE();
static Ref<T> create(v8::Handle<T> handle, VALUE klass);
inline v8::Handle<T> operator->() const { return holder->handle; }
private:
class Holder {
Holder(v8::Handle<T> handle, VALUE klass);
virtual ~Holder();
Holder(v8::Handle<T> handle, VALUE klass) {
this->handle = v8::Persistent<T>::New(handle);
this->value = Data_Wrap_Struct(klass, 0, &Holder::enqueue, this);
}
virtual ~Holder() {
handle.Dispose();
}
protected:
VALUE value;
v8::Persistent<T> handle;
VALUE value;
v8::Persistent<T> handle;
friend class Ref<T>;
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<v8::Context> {
public:
inline Context(VALUE value) : Ref<v8::Context>(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<v8::Context> {
public:
inline Context(VALUE value) : Ref<v8::Context>(value) {};
static void Init();
};
class Script : public Ref<v8::Script> {
public:
inline Script(VALUE value) : Ref<v8::Script>(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)

24
ext/v8/script.cc Normal file
View file

@ -0,0 +1,24 @@
#include "rr.h"
namespace rr {
namespace {
VALUE New(VALUE klass, VALUE source, VALUE filename) {
v8::HandleScope scope;
return Ref<v8::Script>::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);
}
}

19
ext/v8/string.cc Normal file
View file

@ -0,0 +1,19 @@
#include "rr.h"
namespace rr {
String::String(VALUE object) : Value(object) {}
String::operator v8::Handle<v8::String>() {
return v8::String::New(RSTRING_PTR(object), (int)RSTRING_LEN(object));
}
namespace {
VALUE New(VALUE StringClass, VALUE string) {
return Ref<v8::String>::create(String(string), StringClass);
}
}
void String::Init() {
VALUE StringClass = defineClass("String");
RR_DEFINE_SINGLETON_METHOD(StringClass, "New", &New, 1);
}
}

86
ext/v8/value.cc Normal file
View file

@ -0,0 +1,86 @@
#include "rr.h"
namespace rr {
Value::Value(v8::Handle<v8::Value> 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<v8::Value>() {
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<v8::String>)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<v8::Value>(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();
}
}

View file

@ -6,7 +6,11 @@ module V8
end
def eval(source, filename = '<eval>', line = 1)
nil
@native.Enter()
script = V8::C::Script::New(source.to_s, filename.to_s)
script.Run()
ensure
@native.Exit()
end
end
end