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

Create HandleScopes, Externals from Ruby.

This commit is contained in:
Charles Lowell 2012-05-08 15:11:50 -05:00
parent 28475caab3
commit 0800d82988
12 changed files with 155 additions and 24 deletions

32
ext/v8/external.cc Normal file
View file

@ -0,0 +1,32 @@
#include "rr.h"
namespace rr {
void External::Init() {
ClassBuilder("External", "Value").
defineSingletonMethod("New", &New).
defineMethod("Value", &Value);
}
VALUE External::New(VALUE self, VALUE data) {
Data* holder = new Data(data);
v8::Local<v8::External> ext = v8::External::New(holder);
v8::Persistent<v8::External>::New(ext).MakeWeak(holder, &release);
return External::create(ext, self);
}
VALUE External::Value(VALUE self) {
Data* data = (Data*)(External(self)->Value());
return data->value;
}
void External::release(v8::Persistent<v8::Value> handle, void* parameter) {
handle.Dispose();
Data* data = (Data*)parameter;
delete data;
}
External::Data::Data(VALUE data) {
this->value = data;
rb_gc_register_address(&value);
}
External::Data::~Data() {
rb_gc_unregister_address(&value);
}
}

34
ext/v8/handles.cc Normal file
View file

@ -0,0 +1,34 @@
#include "rr.h"
namespace rr {
void Handles::Init() {
VALUE v8 = rb_define_module("V8");
VALUE c = rb_define_module_under(v8, "C");
rb_define_singleton_method(c, "HandleScope", (VALUE (*)(...))&HandleScope, -1);
}
VALUE Handles::HandleScope(int argc, VALUE* argv, VALUE self) {
if (!rb_block_given_p()) {
return Qnil;
}
int state = 0;
VALUE code;
rb_scan_args(argc,argv,"00&", &code);
VALUE result = SetupAndCall(&state, code);
if (state != 0) {
rb_jump_tag(state);
}
return result;
}
VALUE Handles::SetupAndCall(int* state, VALUE code) {
v8::HandleScope scope;
return rb_protect(&DoCall, code, state);
}
VALUE Handles::DoCall(VALUE code) {
return rb_funcall(code, rb_intern("call"), 0);
}
}

View file

@ -10,10 +10,12 @@ extern "C" {
void Init_init() {
GC::Init();
V8::Init();
Handles::Init();
Context::Init();
Value::Init();
String::Init();
Object::Init();
External::Init();
Script::Init();
}
}

View file

@ -78,16 +78,17 @@ VALUE Object::ForceDelete(VALUE self, VALUE key) {
}
// VALUE Object::SetAccessor(int argc, VALUE* argv, VALUE self) {
// VALUE name; VALUE getter; VALUE setter; VALUE data; VALUE settings, VALUE attribs;
// rb_scan_args(argc, argv, "24", name, getter, setter, data, settings, attribs);
// return Convert(Object(self)->SetAccessor(String(name),
// AccessorGetter(getter),
// AccessorSetter(setter),
// Value(data),
// AccessControl(settings),
// PropertyAttribute(attribs)));
// }
VALUE Object::SetAccessor(int argc, VALUE* argv, VALUE self) {
VALUE name; VALUE getter; VALUE setter; VALUE data; VALUE settings; VALUE attribs;
rb_scan_args(argc, argv, "24", name, getter, setter, data, settings, attribs);
return Qfalse;
// return Convert(Object(self)->SetAccessor(String(name),
// AccessorGetter(getter),
// AccessorSetter(setter),
// Value(data),
// AccessControl(settings),
// PropertyAttribute(attribs)));
}
// V8EXPORT bool SetAccessor(Handle<String> name,
// AccessorGetter getter,
// AccessorSetter setter = 0,

View file

@ -94,6 +94,15 @@ public:
Holder* holder;
};
class Handles {
public:
static void Init();
static VALUE HandleScope(int argc, VALUE* argv, VALUE self);
private:
static VALUE SetupAndCall(int* state, VALUE code);
static VALUE DoCall(VALUE code);
};
class Phantom : public Ref<void> {
public:
inline Phantom(void* reference) : Ref<void>((Ref<void>::Holder*)reference) {}
@ -116,6 +125,21 @@ private:
inline Context(VALUE value) : Ref<v8::Context>(value) {}
};
class External: public Ref<v8::External> {
public:
inline External(VALUE value) : Ref<v8::External>(value) {}
static void Init();
static VALUE New(VALUE self, VALUE data);
static VALUE Value(VALUE self);
private:
static void release(v8::Persistent<v8::Value> object, void* parameter);
struct Data {
Data(VALUE data);
~Data();
VALUE value;
};
};
class Script : public Ref<v8::Script> {
public:
static void Init();

View file

@ -9,12 +9,10 @@ void Script::Init() {
}
VALUE Script::New(VALUE klass, VALUE source, VALUE filename) {
v8::HandleScope scope;
return Script::create(v8::Script::New(String(source), Value(filename)), klass);
}
VALUE Script::Run(VALUE self) {
v8::HandleScope scope;
return Convert(Script(self)->Run());
}

View file

@ -12,12 +12,10 @@ void String::Init() {
}
VALUE String::New(VALUE StringClass, VALUE string) {
v8::HandleScope h;
return String::Convert(v8::String::New(RSTRING_PTR(string), (int)RSTRING_LEN(string)));
}
VALUE String::Utf8Value(VALUE self) {
v8::HandleScope h;
String str(self);
return rb_str_new(*v8::String::Utf8Value(str.GetHandle()), str->Utf8Length());
}

View file

@ -7,11 +7,13 @@ module V8
def eval(source, filename = '<eval>', line = 1)
@native.Enter()
source = V8::C::String::New(source.to_s)
filename = V8::C::String::New(filename.to_s)
script = V8::C::Script::New(source, filename)
result = script.Run()
result.kind_of?(V8::C::String) ? result.Utf8Value() : result
V8::C::HandleScope() do
source = V8::C::String::New(source.to_s)
filename = V8::C::String::New(filename.to_s)
script = V8::C::Script::New(source, filename)
result = script.Run()
result.kind_of?(V8::C::String) ? result.Utf8Value() : result
end
ensure
@native.Exit()
end

18
spec/c/external_spec.rb Normal file
View file

@ -0,0 +1,18 @@
require 'spec_helper'
describe V8::C::External do
before do
@cxt = V8::C::Context::New()
@cxt.Enter()
end
after do
@cxt.Exit()
end
it "can store and retrieve a value" do
V8::C::HandleScope() do
o = Object.new
external = V8::C::External::New(o)
external.Value().should be(o)
end
end
end

22
spec/c/handles_spec.rb Normal file
View file

@ -0,0 +1,22 @@
require 'spec_helper'
describe "setting up handles scopes" do
before {@cxt = V8::C::Context::New()}
before {@cxt.Enter()}
after {@cxt.Exit()}
it "can allocate handle scopes" do
V8::C::HandleScope() do
V8::C::Object::New()
end.class.should eql V8::C::Object
end
it "isn't the end of the world if a ruby exception is raised inside a HandleScope" do
begin
V8::C::HandleScope() do
raise "boom!"
end
rescue StandardError => e
e.message.should eql "boom!"
end
end
end

View file

@ -15,7 +15,7 @@ describe "A Very blunt test to make sure that we aren't doing stupid leaks" do
it "won't increase process memory by more than 20% no matter how many contexts we create" do
5000.times do
V8::Context.new
gc_completely
run_v8_gc
end
process_memory.should <= @start_memory * 1.2
end
@ -24,9 +24,5 @@ describe "A Very blunt test to make sure that we aren't doing stupid leaks" do
/\w*[ ]*#{Process.pid}[ ]*([.,\d]*)[ ]*([.,\d]*)[ ]*([\d]*)[ ]*([\d]*)/.match(`ps aux`)[4].to_i
end
def gc_completely
loop while !V8::C::V8::IdleNotification()
end
end

View file

@ -1,5 +1,9 @@
require 'v8'
def run_v8_gc
loop while !V8::C::V8::IdleNotification()
end
def rputs(msg)
puts "<pre>#{ERB::Util.h(msg)}</pre>"
$stdout.flush