mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
V8 callbacks are now in ruby. remove C++ callbacks.
This commit is contained in:
parent
da2c83e7ce
commit
5a89e05e38
5 changed files with 4 additions and 293 deletions
|
@ -1,185 +0,0 @@
|
|||
#include "rr.h"
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "converters.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
namespace {
|
||||
VALUE unwrap(const AccessorInfo& info) {
|
||||
return (VALUE)External::Unwrap(info.Data());
|
||||
}
|
||||
|
||||
//returns all the ruby methods that can be called from
|
||||
//this object.
|
||||
//1.8: public_methods() return strings
|
||||
//1.9: publi_methods() return symbols
|
||||
//convert them all into string
|
||||
|
||||
VALUE CALLABLE_METHODS(VALUE object) {
|
||||
VALUE methods = rb_funcall(object, rb_intern("public_methods"), 1, Qfalse);
|
||||
int length = RARRAY_LEN(methods);
|
||||
VALUE str_methods = rb_ary_new2(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
VALUE method = rb_ary_entry(methods, i);
|
||||
rb_ary_store(str_methods,i, rb_obj_as_string(method));
|
||||
}
|
||||
return str_methods;
|
||||
}
|
||||
|
||||
Local<Array> TO_ARRAY(Arguments& args) {
|
||||
Local<Array> array = Array::New(args.Length());
|
||||
for (int i = 0; i < args.Length(); i++) {
|
||||
array->Set(Integer::New(i), args[i]);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
Local<Value> Racer_Call_Ruby_Method(VALUE object, VALUE method, Local<Array> args) {
|
||||
VALUE * arguments = new VALUE[args->Length()];
|
||||
for (unsigned int i = 0; i < args->Length(); i++) {
|
||||
Handle<Value> val = args->Get(Integer::New(i));
|
||||
arguments[i] = V82RB(val);
|
||||
}
|
||||
VALUE result = rb_funcall2(object, rb_to_id(method), args->Length(), arguments);
|
||||
Local<Value> converted = RB2V8(result);
|
||||
return converted;
|
||||
}
|
||||
|
||||
Local<Value> Racer_Access_Ruby_Property(VALUE object, VALUE name) {
|
||||
VALUE method = rb_funcall(object, rb_intern("method"), 1, name);
|
||||
if (FIX2INT(rb_funcall(method, rb_intern("arity"), 0)) == 0) {
|
||||
return Racer_Call_Ruby_Method(object, name, Array::New(0));
|
||||
} else {
|
||||
//causes out of memory if we use rr_rb2v8
|
||||
return RB2V8(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Handle<Value> RacerRubyInvocationCallback(const Arguments& args) {
|
||||
VALUE code = (VALUE)External::Unwrap(args.Data());
|
||||
if (NIL_P(code)) {
|
||||
return Null();
|
||||
} else {
|
||||
VALUE* arguments = new VALUE[args.Length()];
|
||||
for(int c=0;c<args.Length(); ++c) {
|
||||
Handle<Value> val = args[c];
|
||||
// arguments[c] = rr_v82rb(val); // segfaults... why?
|
||||
arguments[c] = V82RB(val);
|
||||
}
|
||||
|
||||
VALUE result = rb_funcall2(code, rb_intern("call"), args.Length(), arguments);
|
||||
delete [] arguments;
|
||||
|
||||
Handle<Value> convertedResult = rr_rb2v8(result);
|
||||
return convertedResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* NamedProperty[Getter|Setter] are used as interceptors on object.
|
||||
* See ObjectTemplate::SetNamedPropertyHandler.
|
||||
*/
|
||||
|
||||
Handle<Value> RacerRubyNamedPropertyGetter(Local<String> property, const AccessorInfo& info) {
|
||||
// printf("Getter '%s'<br/>", *String::AsciiValue(property));
|
||||
if (property->Length() == 0) {
|
||||
return Handle<Value>();
|
||||
}
|
||||
VALUE object = unwrap(info);
|
||||
// VALUE camel_name = rr_v82rb(property); //segfaults. why??
|
||||
VALUE camel_name = V82RB((Local<Value>&)property);
|
||||
VALUE perl_name = rr_str_to_perl_case(camel_name);
|
||||
// VALUE perl_name = rb_funcall(V8_To, rb_intern("perl_case"), 1, camel_name);
|
||||
VALUE methods = CALLABLE_METHODS(object);
|
||||
|
||||
if (RTEST(rb_ary_includes(methods, perl_name))) {
|
||||
return Racer_Access_Ruby_Property(object, perl_name);
|
||||
}
|
||||
if (RTEST(rb_ary_includes(methods, camel_name))) {
|
||||
return Racer_Access_Ruby_Property(object, camel_name);
|
||||
}
|
||||
return Handle<Value>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value if the setter intercepts the request.
|
||||
* Otherwise, returns an empty handle.
|
||||
*/
|
||||
Handle<Value> RacerRubyNamedPropertySetter(Local<String> property, Local<Value> value, const AccessorInfo& info) {
|
||||
if (property->Length() == 0) {
|
||||
return Handle<Value>();
|
||||
}
|
||||
// printf("Setter: '%s'<br/>", *String::AsciiValue(property));
|
||||
std::string setter = V82String((Handle<Value>&)property);
|
||||
setter += "=";
|
||||
Local<String> setter_name = String::New(setter.c_str());
|
||||
VALUE object = unwrap(info);
|
||||
VALUE camel_name = V82RB((Local<Value>&)setter_name);
|
||||
VALUE perl_name = rr_str_to_perl_case(camel_name);
|
||||
// VALUE perl_name = rb_funcall(V8_To, rb_intern("perl_case"), 1, camel_name);
|
||||
VALUE methods = CALLABLE_METHODS(object);
|
||||
Local<Array> args = Array::New(1);
|
||||
args->Set(Integer::New(0), value);
|
||||
if (RTEST(rb_ary_includes(methods, perl_name))) {
|
||||
Racer_Call_Ruby_Method(object, perl_name, args);
|
||||
return value;
|
||||
}
|
||||
if (RTEST(rb_ary_includes(methods, camel_name))) {
|
||||
Racer_Call_Ruby_Method(object, camel_name, args);
|
||||
return value;
|
||||
}
|
||||
return Handle<Value>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-empty handle if the interceptor intercepts the request.
|
||||
* The result is true if the property exists and false otherwise.
|
||||
*/
|
||||
Handle<Boolean> RacerRubyNamedPropertyQuery(Local<String> property, const AccessorInfo& info) {
|
||||
// printf("Query: '%s'<br/>", *String::AsciiValue(property));
|
||||
if (property->Length() == 0) {
|
||||
return False();
|
||||
}
|
||||
VALUE object = unwrap(info);
|
||||
VALUE methods = CALLABLE_METHODS(object);
|
||||
VALUE attr_name = V82RB((Local<Value>&)property);
|
||||
// VALUE perl_name = rb_funcall(V8_To, rb_intern("perl_case"), 1, attr_name);
|
||||
VALUE perl_name = rr_str_to_perl_case(attr_name);
|
||||
|
||||
if (RTEST(rb_ary_includes(methods, attr_name)) || RTEST(rb_ary_includes(methods, perl_name))) {
|
||||
return True();
|
||||
} else {
|
||||
return Handle<Boolean>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-empty handle if the deleter intercepts the request.
|
||||
* The return value is true if the property could be deleted and false
|
||||
* otherwise.
|
||||
*/
|
||||
Handle<Boolean> RacerRubyNamedPropertyDeleter(Local<String> property, const AccessorInfo& info) {
|
||||
return False();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing the names of the properties the named
|
||||
* property getter intercepts.
|
||||
*/
|
||||
Handle<Array> RacerRubyNamedPropertyEnumerator(const AccessorInfo& info) {
|
||||
VALUE object = unwrap(info);
|
||||
VALUE methods = CALLABLE_METHODS(object);
|
||||
int length = RARRAY_LEN(methods);
|
||||
Local<Array> properties = Array::New(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
// VALUE camel_name = rb_funcall(V8_To, rb_intern("camel_case"), 1, rb_ary_entry(methods, i));
|
||||
VALUE camel_name = rr_str_to_camel_case(rb_ary_entry(methods, i));
|
||||
properties->Set(Integer::New(i), rr_rb2v8(camel_name));
|
||||
}
|
||||
return properties;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef CALLBACKS_H_8VK3LWBG
|
||||
#define CALLBACKS_H_8VK3LWBG
|
||||
|
||||
#include <v8.h>
|
||||
|
||||
v8::Handle<v8::Value> RacerRubyInvocationCallback(const v8::Arguments& args);
|
||||
|
||||
v8::Handle<v8::Value> RacerRubyNamedPropertyGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
|
||||
v8::Handle<v8::Value> RacerRubyNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
|
||||
v8::Handle<v8::Boolean> RacerRubyNamedPropertyQuery(v8::Local<v8::String> property, const v8::AccessorInfo& info);
|
||||
v8::Handle<v8::Boolean> RacerRubyNamedPropertyDeleter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
|
||||
v8::Handle<v8::Array> RacerRubyNamedPropertyEnumerator(const v8::AccessorInfo& info);
|
||||
|
||||
#endif /* end of include guard: CALLBACKS_H_8VK3LWBG */
|
|
@ -1,5 +1,4 @@
|
|||
#include "converters.h"
|
||||
#include "callbacks.h"
|
||||
#include "v8_ref.h"
|
||||
#include "v8_obj.h"
|
||||
#include "v8_cxt.h"
|
||||
|
@ -51,10 +50,10 @@ VALUE V82RB(Handle<Value>& value) {
|
|||
|
||||
Local<Value> RB2V8(VALUE value) {
|
||||
VALUE valueClass = rb_class_of(value);
|
||||
if(valueClass == rb_cProc || valueClass == rb_cMethod) {
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(RacerRubyInvocationCallback, rr_v8_external_create(value));
|
||||
return t->GetFunction();
|
||||
}
|
||||
// if(valueClass == rb_cProc || valueClass == rb_cMethod) {
|
||||
// Local<FunctionTemplate> t = FunctionTemplate::New(RacerRubyInvocationCallback, rr_v8_external_create(value));
|
||||
// return t->GetFunction();
|
||||
// }
|
||||
convert_rb_to_v8_t convert;
|
||||
Local<Value> result;
|
||||
if (convert(value, result)) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "v8_template.h"
|
||||
#include "v8_external.h"
|
||||
#include "v8_callbacks.h"
|
||||
#include "callbacks.h"
|
||||
#include "converters.h"
|
||||
|
||||
using namespace v8;
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
|
||||
module V8
|
||||
module C
|
||||
class MethodInfo
|
||||
|
||||
attr_reader :perl_methods, :camel_methods
|
||||
|
||||
def initialize(object)
|
||||
@object = object
|
||||
@methods = Set.new
|
||||
for name in object.public_methods(false) do
|
||||
@methods << name.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def find(name)
|
||||
for format in [name, To.perl_case(name), To.camel_case(name)]
|
||||
return @object.method(format) if @methods.include?(format)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class NamedPropertyGetter
|
||||
def self.call(property, info)
|
||||
methods = MethodInfo(To.rb(info.This()))
|
||||
|
||||
if method = methods.find(To.rb(property))
|
||||
if method.arity == 0
|
||||
To.v8(method.call)
|
||||
else
|
||||
To.v8(method)
|
||||
end
|
||||
else
|
||||
C::Empty
|
||||
end
|
||||
|
||||
# method_name = if methods.include?(name)
|
||||
# name
|
||||
# elsif methods.include?(perl_name)
|
||||
# perl_name
|
||||
# end
|
||||
# if method_name
|
||||
# method = obj.method(method_name)
|
||||
# if method.arity == 0
|
||||
# To.v8(method.call())
|
||||
# else
|
||||
# To.v8(method)
|
||||
# end
|
||||
# else
|
||||
# C::Empty
|
||||
# end
|
||||
# end
|
||||
end
|
||||
|
||||
class NamedPropertySetter
|
||||
def self.call(property, value, info)
|
||||
obj = To.rb(info.This())
|
||||
setter = To.rb(property) + "="
|
||||
camel_name = To.camel_case(setter)
|
||||
perl_name = To.perl_case(setter)
|
||||
methods = obj.public_methods(false).map(&:to_s)
|
||||
if methods.include?(perl_name)
|
||||
obj.send(perl_name, To.rb(value))
|
||||
elsif methods.include?(camel_name)
|
||||
obj.send(camel_name, To.rb(value))
|
||||
else
|
||||
C::Empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class NamedPropertyEnumerator
|
||||
def self.call(info)
|
||||
obj = To.rb(info.This())
|
||||
camel_methods = obj.public_methods(false).inject(Set.new) do |set, name|
|
||||
set.tap do
|
||||
set << To.camel_case(name)
|
||||
end
|
||||
end
|
||||
names = V8::C::Array::New(camel_methods.length)
|
||||
camel_methods.each_with_index do |name, i|
|
||||
names.Set(i, C::String::New(name))
|
||||
end
|
||||
return names
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue