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:
parent
3c2ca322c5
commit
451211fb72
9 changed files with 214 additions and 68 deletions
|
@ -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);
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -9,5 +9,7 @@ using namespace rr;
|
|||
extern "C" {
|
||||
void Init_init() {
|
||||
Context::Init();
|
||||
String::Init();
|
||||
Script::Init();
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
102
ext/v8/rr.h
102
ext/v8/rr.h
|
@ -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
24
ext/v8/script.cc
Normal 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
19
ext/v8/string.cc
Normal 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
86
ext/v8/value.cc
Normal 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();
|
||||
}
|
||||
}
|
|
@ -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
|
Loading…
Add table
Reference in a new issue