1
0
Fork 0
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:
Charles Lowell 2010-06-06 14:29:33 +03:00
parent da2c83e7ce
commit 5a89e05e38
5 changed files with 4 additions and 293 deletions

View file

@ -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;
}

View file

@ -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 */

View file

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

View file

@ -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;

View file

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