mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
native C objects now have a reference to the context that created them. Add identity/equality check for C::Context
This commit is contained in:
parent
40282449dd
commit
56c5558be7
11 changed files with 111 additions and 19 deletions
|
@ -2,6 +2,7 @@
|
|||
#include "callbacks.h"
|
||||
#include "v8_ref.h"
|
||||
#include "v8_obj.h"
|
||||
#include "v8_cxt.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
|
@ -32,7 +33,9 @@ VALUE V82RB(Handle<Value>& value) {
|
|||
Local<Object> object(Object::Cast(*value));
|
||||
Local<Value> peer = object->GetHiddenValue(String::New("TheRubyRacer::RubyObject"));
|
||||
if (peer.IsEmpty()) {
|
||||
return V8_Ref_Create(V8_C_Object, value);
|
||||
VALUE context_ref = V8_Ref_Create(V8_C_Context, Context::GetCurrent());
|
||||
object->SetHiddenValue(String::New("TheRubyRacer::Context"), External::Wrap((void *)context_ref));
|
||||
return V8_Ref_Create(V8_C_Object, value, context_ref);
|
||||
} else {
|
||||
return (VALUE)External::Unwrap(peer);
|
||||
}
|
||||
|
|
|
@ -37,12 +37,15 @@ extern "C" {
|
|||
VALUE rb_mNative = rb_define_module_under(rb_mModule, "C");
|
||||
|
||||
//native context
|
||||
VALUE V8__C__Context = rb_define_class_under(rb_mNative, "Context", rb_cObject);
|
||||
rb_define_singleton_method(V8__C__Context, "new", (VALUE(*)(...)) v8_Context_New, -1);
|
||||
rb_define_singleton_method(V8__C__Context, "InContext", (VALUE(*)(...)) v8_Context_InContext, 0);
|
||||
rb_define_method(V8__C__Context, "Global", (VALUE(*)(...)) v8_cxt_Global, 0);
|
||||
rb_define_method(V8__C__Context, "open", (VALUE(*)(...)) v8_cxt_open, 0);
|
||||
rb_define_method(V8__C__Context, "eval", (VALUE(*)(...)) v8_cxt_eval, 1);
|
||||
V8_C_Context = rb_define_class_under(rb_mNative, "Context", rb_cObject);
|
||||
rb_define_singleton_method(V8_C_Context, "new", (VALUE(*)(...)) v8_Context_New, -1);
|
||||
rb_define_singleton_method(V8_C_Context, "InContext", (VALUE(*)(...)) v8_Context_InContext, 0);
|
||||
rb_define_singleton_method(V8_C_Context, "GetCurrent", (VALUE(*)(...)) v8_Context_GetCurrent, 0);
|
||||
rb_define_method(V8_C_Context, "Global", (VALUE(*)(...)) v8_cxt_Global, 0);
|
||||
rb_define_method(V8_C_Context, "open", (VALUE(*)(...)) v8_cxt_open, 0);
|
||||
rb_define_method(V8_C_Context, "eval", (VALUE(*)(...)) v8_cxt_eval, 1);
|
||||
rb_define_method(V8_C_Context, "eql?", (VALUE(*)(...)) v8_cxt_eql, 1);
|
||||
rb_define_method(V8_C_Context, "==", (VALUE(*)(...)) v8_cxt_eql, 1);
|
||||
|
||||
//native String
|
||||
VALUE V8__C__String = rb_define_class_under(rb_mNative, "String", rb_cObject);
|
||||
|
@ -68,6 +71,7 @@ extern "C" {
|
|||
rb_define_method(V8_C_Object, "Get", (VALUE(*)(...))v8_Object_Get, 1);
|
||||
rb_define_method(V8_C_Object, "Set", (VALUE(*)(...))v8_Object_Set, 2);
|
||||
rb_define_method(V8_C_Object, "GetPropertyNames", (VALUE(*)(...)) v8_Object_GetPropertyNames, 0);
|
||||
rb_define_method(V8_C_Object, "context", (VALUE(*)(...)) v8_Object_context, 0);
|
||||
|
||||
V8_C_Message = rb_define_class_under(rb_mNative, "Message", rb_cObject);
|
||||
rb_define_method(V8_C_Message, "Get", (VALUE(*)(...))v8_Message_Get, 0);
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
using namespace v8;
|
||||
|
||||
VALUE V8_C_Context;
|
||||
|
||||
//TODO: rename everything to Context_
|
||||
//TODO: do the object init from within here
|
||||
|
||||
|
@ -24,7 +26,17 @@ VALUE v8_Context_New(int argc, VALUE *argv, VALUE self) {
|
|||
}
|
||||
|
||||
VALUE v8_Context_InContext(VALUE self) {
|
||||
return Context::InContext() ? Qtrue : Qnil;
|
||||
return Context::InContext() ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
VALUE v8_Context_GetCurrent(VALUE self) {
|
||||
HandleScope handles;
|
||||
if (Context::InContext()) {
|
||||
Local<Context> current = Context::GetCurrent();
|
||||
return V8_Ref_Create(self, current);
|
||||
} else {
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
VALUE v8_cxt_Global(VALUE self) {
|
||||
|
@ -60,4 +72,16 @@ VALUE v8_cxt_eval(VALUE self, VALUE source) {
|
|||
}
|
||||
}
|
||||
|
||||
VALUE v8_cxt_eql(VALUE self, VALUE other) {
|
||||
HandleScope handles;
|
||||
if (RTEST(CLASS_OF(other) != V8_C_Context)) {
|
||||
return Qnil;
|
||||
} else {
|
||||
Local<Context> cxt = V8_Ref_Get<Context>(self);
|
||||
Local<Context> that = V8_Ref_Get<Context>(other);
|
||||
return cxt == that ? Qtrue : Qfalse;
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,11 +7,14 @@
|
|||
|
||||
extern VALUE rb_cV8;
|
||||
extern VALUE V8_C_Object;
|
||||
extern VALUE V8_C_Context;
|
||||
|
||||
VALUE v8_Context_New(int argc, VALUE *argv, VALUE self);
|
||||
VALUE v8_Context_InContext(VALUE self);
|
||||
VALUE v8_Context_GetCurrent(VALUE self);
|
||||
VALUE v8_cxt_Global(VALUE self);
|
||||
VALUE v8_cxt_open(VALUE self);
|
||||
VALUE v8_cxt_eval(VALUE self, VALUE source);
|
||||
VALUE v8_cxt_eql(VALUE self, VALUE other);
|
||||
|
||||
#endif
|
|
@ -42,3 +42,10 @@ VALUE v8_Object_GetPropertyNames(VALUE self) {
|
|||
Local<Value> names = object->GetPropertyNames();
|
||||
return V82RB(names);
|
||||
}
|
||||
|
||||
VALUE v8_Object_context(VALUE self) {
|
||||
HandleScope handles;
|
||||
Local<Object> object = unwrap(self);
|
||||
Local<Value> cxt = object->GetHiddenValue(String::New("TheRubyRacer::Context"));
|
||||
return cxt.IsEmpty() ? Qnil : (VALUE)External::Unwrap(cxt);
|
||||
}
|
||||
|
|
|
@ -9,4 +9,5 @@ VALUE v8_Object_New(VALUE clazz);
|
|||
VALUE v8_Object_Get(VALUE self, VALUE key);
|
||||
VALUE v8_Object_Set(VALUE self, VALUE key, VALUE value);
|
||||
VALUE v8_Object_GetPropertyNames(VALUE self);
|
||||
VALUE v8_Object_context(VALUE self);
|
||||
#endif
|
|
@ -7,9 +7,15 @@ module V8
|
|||
end
|
||||
|
||||
def open(&block)
|
||||
@native.open do
|
||||
block.call(self)
|
||||
end if block_given?
|
||||
if block_given?
|
||||
unless @native == C::Context::GetCurrent()
|
||||
@native.open do
|
||||
block.call(self)
|
||||
end
|
||||
else
|
||||
block.call(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def eval(javascript, sourcename = '<eval>', line = 1)
|
||||
|
@ -33,15 +39,17 @@ module V8
|
|||
end
|
||||
|
||||
def [](key)
|
||||
ContextError.check_open('V8::Context#[]')
|
||||
To.ruby(@native.Global().Get(key.to_s))
|
||||
open do
|
||||
To.ruby(@native.Global().Get(key.to_s))
|
||||
end
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
ContextError.check_open('V8::Context#[]=')
|
||||
value.tap do
|
||||
@native.Global().tap do |scope|
|
||||
scope.Set(key.to_s, value)
|
||||
open do
|
||||
@native.Global().tap do |scope|
|
||||
scope.Set(key.to_s, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,12 +8,16 @@ module V8
|
|||
end
|
||||
|
||||
def [](key)
|
||||
To.ruby(@native.Get(key.to_s))
|
||||
@native.context.open do
|
||||
To.ruby(@native.Get(key.to_s))
|
||||
end
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
value.tap do
|
||||
@native.Set(key.to_s, value)
|
||||
@native.context.open do
|
||||
@native.Set(key.to_s, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
25
spec/ext/cxt_spec.rb
Normal file
25
spec/ext/cxt_spec.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
require "#{File.dirname(__FILE__)}/../spec_helper.rb"
|
||||
|
||||
include V8
|
||||
|
||||
describe C::Context do
|
||||
|
||||
it "should not have a current context if no context is open" do
|
||||
C::Context::GetCurrent().should be_nil
|
||||
end
|
||||
|
||||
it "can determine if there is a current context" do
|
||||
C::Context::InContext().should be(false)
|
||||
C::Context.new.open do |cxt|
|
||||
C::Context::InContext().should be(true)
|
||||
end
|
||||
end
|
||||
|
||||
it "returns the currently open context" do
|
||||
C::Context.new.open do |cxt|
|
||||
cxt.should be_eql(C::Context::GetCurrent())
|
||||
cxt.should == C::Context::GetCurrent()
|
||||
end
|
||||
end
|
||||
end
|
13
spec/ext/obj_spec.rb
Normal file
13
spec/ext/obj_spec.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
require "#{File.dirname(__FILE__)}/../spec_helper.rb"
|
||||
|
||||
include V8
|
||||
|
||||
describe C::Object do
|
||||
it "has a reference to its calling context" do
|
||||
C::Context.new.open do |cxt|
|
||||
o = cxt.eval('new Object()');
|
||||
o.context.should == cxt
|
||||
o.context.should be_eql(cxt)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1 +1 @@
|
|||
Subproject commit 915d20496c7af6bbc1c9f2ae4c794fd5031cd56c
|
||||
Subproject commit 260ff99e34670cedbd03867a6da6f581512cc2cc
|
Loading…
Reference in a new issue