therubyracer 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of therubyracer might be problematic. Click here for more details.
- data/Manifest.txt +2 -0
- data/Rakefile +1 -0
- data/ext/v8/callbacks.cpp +25 -0
- data/ext/v8/callbacks.h +8 -0
- data/ext/v8/convert_ruby.h +0 -14
- data/ext/v8/convert_v8.h +34 -26
- data/ext/v8/converters.cpp +59 -2
- data/ext/v8/converters.h +6 -2
- data/ext/v8/v8.cpp +2 -0
- data/ext/v8/v8_cxt.cpp +8 -11
- data/ext/v8/v8_msg.cpp +7 -1
- data/ext/v8/v8_msg.h +1 -0
- data/ext/v8/v8_obj.cpp +4 -2
- data/ext/v8/v8_script.cpp +1 -2
- data/ext/v8/v8_template.cpp +2 -20
- data/lib/v8.rb +1 -1
- data/lib/v8/context.rb +8 -5
- data/spec/redjs/jsapi_spec.rb +1 -2
- data/therubyracer.gemspec +2 -2
- metadata +4 -2
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "callbacks.h"
|
4
|
+
#include "converters.h"
|
5
|
+
|
6
|
+
using namespace v8;
|
7
|
+
|
8
|
+
Handle<Value> RacerRubyInvocationCallback(const Arguments& args) {
|
9
|
+
VALUE code = (VALUE)External::Unwrap(args.Data());
|
10
|
+
if (NIL_P(code)) {
|
11
|
+
return Null();
|
12
|
+
} else {
|
13
|
+
VALUE* arguments = new VALUE[args.Length()];
|
14
|
+
for(int c=0;c<args.Length(); ++c) {
|
15
|
+
Handle<Value> val = args[c];
|
16
|
+
arguments[c] = V82RB(val);
|
17
|
+
}
|
18
|
+
|
19
|
+
VALUE result = rb_funcall2(code, rb_intern("call"), args.Length(), arguments);
|
20
|
+
delete [] arguments;
|
21
|
+
|
22
|
+
Handle<Value> convertedResult = RB2V8(result);
|
23
|
+
return convertedResult ;
|
24
|
+
}
|
25
|
+
}
|
data/ext/v8/callbacks.h
ADDED
data/ext/v8/convert_ruby.h
CHANGED
@@ -2,9 +2,6 @@
|
|
2
2
|
#define __convert_ruby_h__
|
3
3
|
|
4
4
|
#include <ruby.h>
|
5
|
-
#include <v8.h>
|
6
|
-
#include "v8_ref.h"
|
7
|
-
#include "v8_obj.h"
|
8
5
|
#include <string>
|
9
6
|
|
10
7
|
/**
|
@@ -44,13 +41,6 @@ template<class DEST, class RET> class RubyValueSource {
|
|
44
41
|
return dest.pushBool(true);
|
45
42
|
case T_FALSE:
|
46
43
|
return dest.pushBool(false);
|
47
|
-
case T_DATA:
|
48
|
-
VALUE clsProc = rb_eval("::Proc");
|
49
|
-
VALUE clsMethod = rb_eval("::Method");
|
50
|
-
VALUE smartMatch = rb_intern("===");
|
51
|
-
if (RTEST(rb_funcall(clsProc, smartMatch, value)) || RTEST(rbfuncall(clsMethod, smartMatch, value))) {
|
52
|
-
|
53
|
-
}
|
54
44
|
}
|
55
45
|
return dest.pushUndefined();
|
56
46
|
}
|
@@ -96,10 +86,6 @@ class RubyValueDest {
|
|
96
86
|
VALUE pushUndefined() {
|
97
87
|
return Qnil;
|
98
88
|
}
|
99
|
-
|
100
|
-
VALUE pushObject(v8::Handle<v8::Object>& value) {
|
101
|
-
return V8_Ref_Create(V8_C_Object, value);
|
102
|
-
}
|
103
89
|
};
|
104
90
|
|
105
91
|
|
data/ext/v8/convert_v8.h
CHANGED
@@ -15,57 +15,69 @@ template<class T, class R> class V8HandleSource {
|
|
15
15
|
V8HandleSource() {}
|
16
16
|
~V8HandleSource() {}
|
17
17
|
|
18
|
-
|
18
|
+
bool operator() (v8::Handle<v8::Value>& value, R& result) {
|
19
|
+
|
20
|
+
// a bit klunky, but alternative is to evaluate what type the
|
21
|
+
// object is twice, which is unappealing
|
19
22
|
|
20
23
|
if (value.IsEmpty()) {
|
21
|
-
|
24
|
+
result = dest.pushNull();
|
25
|
+
return true;
|
22
26
|
}
|
23
27
|
|
24
28
|
if (value->IsUndefined()) {
|
25
|
-
|
29
|
+
result = dest.pushNull();
|
30
|
+
return true;
|
26
31
|
}
|
27
32
|
|
28
33
|
if(value->IsNull()) {
|
29
|
-
|
34
|
+
result = dest.pushNull();
|
35
|
+
return true;
|
30
36
|
}
|
31
37
|
|
32
38
|
if(value->IsTrue()) {
|
33
|
-
|
39
|
+
result = dest.pushBool(true);
|
40
|
+
return true;
|
34
41
|
}
|
35
42
|
|
36
43
|
if(value->IsFalse()) {
|
37
|
-
|
44
|
+
result = dest.pushBool(false);
|
45
|
+
return true;
|
38
46
|
}
|
39
47
|
|
40
48
|
if(value->IsString()) {
|
41
49
|
v8::Local<v8::String> str = value->ToString();
|
42
|
-
|
43
|
-
|
44
|
-
std::string output(strlen, 0);
|
45
|
-
for (int total = 0; total < strlen;) {
|
46
|
-
int written = str->WriteAscii(buffer, total, 1024);
|
47
|
-
output.replace(total, written, buffer);
|
48
|
-
total += written;
|
49
|
-
}
|
50
|
-
return dest.pushString(output);
|
50
|
+
result = convertString(str);
|
51
|
+
return true;
|
51
52
|
}
|
52
53
|
|
53
54
|
if(value->IsInt32()) {
|
54
|
-
|
55
|
+
result = dest.pushInt(value->Int32Value());
|
56
|
+
return true;
|
55
57
|
}
|
56
58
|
|
57
59
|
if(value->IsNumber()) {
|
58
|
-
|
60
|
+
result = dest.pushDouble(value->NumberValue());
|
61
|
+
return true;
|
59
62
|
}
|
60
63
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
+
result = dest.pushNull();
|
65
|
+
return false;
|
66
|
+
}
|
67
|
+
|
68
|
+
R convertString(v8::Local<v8::String>& str) {
|
69
|
+
char buffer[1024];
|
70
|
+
int strlen = str->Length();
|
71
|
+
std::string output(strlen, 0);
|
72
|
+
for (int total = 0; total < strlen;) {
|
73
|
+
int written = str->WriteAscii(buffer, total, 1024);
|
74
|
+
output.replace(total, written, buffer);
|
75
|
+
total += written;
|
64
76
|
}
|
65
|
-
|
66
|
-
return dest.pushNull();
|
77
|
+
return dest.pushString(output);
|
67
78
|
}
|
68
79
|
|
80
|
+
|
69
81
|
};
|
70
82
|
|
71
83
|
/**
|
@@ -103,10 +115,6 @@ public:
|
|
103
115
|
v8::Local<v8::Value> pushUndefined() {
|
104
116
|
return v8::Local<v8::Value>::New(v8::Undefined());
|
105
117
|
}
|
106
|
-
|
107
|
-
// v8:Local<v8:Value> pushFunction(Function) {
|
108
|
-
//
|
109
|
-
// }
|
110
118
|
};
|
111
119
|
|
112
120
|
|
data/ext/v8/converters.cpp
CHANGED
@@ -1,4 +1,61 @@
|
|
1
1
|
#include "converters.h"
|
2
|
+
#include "callbacks.h"
|
3
|
+
#include "v8_ref.h"
|
4
|
+
#include "v8_obj.h"
|
2
5
|
|
3
|
-
|
4
|
-
|
6
|
+
using namespace v8;
|
7
|
+
|
8
|
+
namespace {
|
9
|
+
std::string UNDEFINED_STR("undefined");
|
10
|
+
}
|
11
|
+
|
12
|
+
VALUE V82RB(Handle<Value>& value) {
|
13
|
+
convert_v8_to_rb_t convert;
|
14
|
+
VALUE result;
|
15
|
+
if(convert(value, result)) {
|
16
|
+
return result;
|
17
|
+
}
|
18
|
+
|
19
|
+
if (value->IsObject()) {
|
20
|
+
Local<Object> object(Object::Cast(*value));
|
21
|
+
return V8_Ref_Create(V8_C_Object, value);
|
22
|
+
}
|
23
|
+
|
24
|
+
return Qnil;
|
25
|
+
}
|
26
|
+
|
27
|
+
Local<Value> RB2V8(VALUE value) {
|
28
|
+
|
29
|
+
VALUE valueClass = rb_class_of(value);
|
30
|
+
|
31
|
+
if(valueClass == rb_cProc || valueClass == rb_cMethod) {
|
32
|
+
Local<FunctionTemplate> t = FunctionTemplate::New(RacerRubyInvocationCallback, External::Wrap((void *)value));
|
33
|
+
return t->GetFunction();
|
34
|
+
}
|
35
|
+
|
36
|
+
convert_rb_to_v8_t convert;
|
37
|
+
return convert(value);
|
38
|
+
}
|
39
|
+
|
40
|
+
std::string RB2String(VALUE value) {
|
41
|
+
convert_rb_to_string_t convert;
|
42
|
+
return convert(value);
|
43
|
+
}
|
44
|
+
|
45
|
+
std::string V82String(Handle<Value>& value) {
|
46
|
+
convert_v8_to_string_t convert;
|
47
|
+
std::string result;
|
48
|
+
if(convert(value, result)) {
|
49
|
+
return result;
|
50
|
+
}
|
51
|
+
|
52
|
+
if (value->IsObject()) {
|
53
|
+
Local<Object> object(Object::Cast(*value));
|
54
|
+
Local<String> str = object->ToString();
|
55
|
+
if(convert(value, result)) {
|
56
|
+
return result;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
return UNDEFINED_STR;
|
61
|
+
}
|
data/ext/v8/converters.h
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
#include "convert_ruby.h"
|
5
5
|
#include "convert_string.h"
|
6
6
|
#include "convert_v8.h"
|
7
|
+
#include <cstring>
|
7
8
|
|
8
9
|
typedef RubyValueSource<V8LocalDest, v8::Local<v8::Value> > convert_rb_to_v8_t;
|
9
10
|
typedef V8HandleSource<RubyValueDest, VALUE> convert_v8_to_rb_t;
|
@@ -11,7 +12,10 @@ typedef V8HandleSource<RubyValueDest, VALUE> convert_v8_to_rb_t;
|
|
11
12
|
typedef RubyValueSource<StringDest, std::string> convert_rb_to_string_t;
|
12
13
|
typedef V8HandleSource<StringDest, std::string> convert_v8_to_string_t;
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
VALUE V82RB(v8::Handle<v8::Value>& value);
|
16
|
+
v8::Local<v8::Value> RB2V8(VALUE value);
|
17
|
+
|
18
|
+
std::string RB2String(VALUE value);
|
19
|
+
std::string V82String(v8::Handle<v8::Value>& value);
|
16
20
|
|
17
21
|
#endif
|
data/ext/v8/v8.cpp
CHANGED
@@ -65,6 +65,8 @@ extern "C" {
|
|
65
65
|
rb_define_method(V8_C_Object, "Set", (VALUE(*)(...))v8_Object_Set, 2);
|
66
66
|
|
67
67
|
V8_C_Message = rb_define_class_under(rb_mNative, "Message", rb_cObject);
|
68
|
+
rb_define_method(V8_C_Message, "Get", (VALUE(*)(...))v8_Message_Get, 0);
|
69
|
+
|
68
70
|
V8_C_Function = rb_define_class_under(rb_mNative, "Function", V8_C_Object);
|
69
71
|
}
|
70
72
|
}
|
data/ext/v8/v8_cxt.cpp
CHANGED
@@ -18,25 +18,17 @@ VALUE v8_Context_New(int argc, VALUE *argv, VALUE self) {
|
|
18
18
|
|
19
19
|
VALUE v8_cxt_Global(VALUE self) {
|
20
20
|
HandleScope handles;
|
21
|
-
convert_v8_to_rb_t v82rb;
|
22
21
|
Local<Context> cxt = V8_Ref_Get<Context>(self);
|
23
22
|
Local<Value> global = *cxt->Global();
|
24
|
-
return
|
23
|
+
return V82RB(global);
|
25
24
|
}
|
26
25
|
|
27
26
|
VALUE v8_cxt_open(VALUE self) {
|
28
27
|
HandleScope handles;
|
29
|
-
TryCatch exceptions;
|
30
28
|
Local<Context> cxt = V8_Ref_Get<Context>(self);
|
31
29
|
Context::Scope enter(cxt);
|
32
30
|
if (rb_block_given_p()) {
|
33
|
-
|
34
|
-
if (exceptions.HasCaught()) {
|
35
|
-
return V8_Wrap_Message(exceptions.Message());
|
36
|
-
} else {
|
37
|
-
return result;
|
38
|
-
}
|
39
|
-
return result;
|
31
|
+
return rb_yield(self);
|
40
32
|
} else {
|
41
33
|
return Qnil;
|
42
34
|
}
|
@@ -44,12 +36,17 @@ VALUE v8_cxt_open(VALUE self) {
|
|
44
36
|
|
45
37
|
VALUE v8_cxt_eval(VALUE self, VALUE source) {
|
46
38
|
HandleScope handles;
|
39
|
+
TryCatch exceptions;
|
47
40
|
Local<Context> cxt = V8_Ref_Get<Context>(self);
|
48
41
|
Context::Scope enter(cxt);
|
49
42
|
Local<Value> source_str = RB2V8(source);
|
50
43
|
Local<Script> script = Script::Compile(source_str->ToString());
|
51
44
|
Local<Value> result = script->Run();
|
52
|
-
|
45
|
+
if (exceptions.HasCaught()) {
|
46
|
+
return V8_Ref_Create(V8_C_Message, exceptions.Message());
|
47
|
+
} else {
|
48
|
+
return V82RB(result);
|
49
|
+
}
|
53
50
|
}
|
54
51
|
|
55
52
|
|
data/ext/v8/v8_msg.cpp
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
#include "converters.h"
|
2
2
|
#include "v8_msg.h"
|
3
3
|
#include "v8_ref.h"
|
4
4
|
|
@@ -8,4 +8,10 @@ VALUE V8_C_Message;
|
|
8
8
|
|
9
9
|
VALUE V8_Wrap_Message(Handle<v8::Message> msg) {
|
10
10
|
return V8_Ref_Create(V8_C_Message, msg);
|
11
|
+
}
|
12
|
+
|
13
|
+
VALUE v8_Message_Get(VALUE self) {
|
14
|
+
Local<Message> message = V8_Ref_Get<Message>(self);
|
15
|
+
Local<Value> str = message->Get();
|
16
|
+
return V82RB(str);
|
11
17
|
}
|
data/ext/v8/v8_msg.h
CHANGED
data/ext/v8/v8_obj.cpp
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
|
5
5
|
using namespace v8;
|
6
6
|
|
7
|
+
#include <cstdio>
|
8
|
+
|
7
9
|
VALUE V8_C_Object;
|
8
10
|
|
9
11
|
VALUE v8_Object_New(VALUE clazz) {
|
@@ -21,9 +23,9 @@ VALUE v8_Object_Get(VALUE self, VALUE key) {
|
|
21
23
|
|
22
24
|
VALUE v8_Object_Set(VALUE self, VALUE key, VALUE value) {
|
23
25
|
HandleScope handles;
|
24
|
-
convert_rb_to_v8_t rb2v8;
|
25
26
|
Local<Object> obj = V8_Ref_Get<Object>(self);
|
26
27
|
VALUE keystr = rb_funcall(key, rb_intern("to_s"), 0);
|
27
|
-
|
28
|
+
|
29
|
+
obj->Set(RB2V8(keystr), RB2V8(value));
|
28
30
|
return Qnil;
|
29
31
|
}
|
data/ext/v8/v8_script.cpp
CHANGED
@@ -15,7 +15,6 @@ VALUE v8_script_new(VALUE self, VALUE source) {
|
|
15
15
|
VALUE v8_script_Run(VALUE self) {
|
16
16
|
HandleScope handles;
|
17
17
|
Local<Script> script = V8_Ref_Get<Script>(self);
|
18
|
-
convert_v8_to_rb_t toValue;
|
19
18
|
Local<Value> result = script->Run();
|
20
|
-
return
|
19
|
+
return V82RB(result);
|
21
20
|
}
|
data/ext/v8/v8_template.cpp
CHANGED
@@ -4,27 +4,9 @@
|
|
4
4
|
#include "v8_func.h"
|
5
5
|
#include "v8_template.h"
|
6
6
|
#include "converters.h"
|
7
|
+
#include "callbacks.h"
|
7
8
|
|
8
9
|
using namespace v8;
|
9
|
-
|
10
|
-
Handle<Value> RubyInvocationCallback(const Arguments& args) {
|
11
|
-
VALUE code = (VALUE)External::Unwrap(args.Data());
|
12
|
-
if (NIL_P(code)) {
|
13
|
-
return Null();
|
14
|
-
} else {
|
15
|
-
VALUE* arguments = new VALUE[args.Length()];
|
16
|
-
for(int c=0;c<args.Length(); ++c) {
|
17
|
-
Handle<Value> val = args[c];
|
18
|
-
arguments[c] = V82RB(val);
|
19
|
-
}
|
20
|
-
|
21
|
-
VALUE result = rb_funcall2(code, rb_intern("call"), args.Length(), arguments);
|
22
|
-
delete [] arguments;
|
23
|
-
|
24
|
-
Handle<Value> convertedResult = RB2V8(result);
|
25
|
-
return convertedResult ;
|
26
|
-
}
|
27
|
-
}
|
28
10
|
|
29
11
|
VALUE v8_Template_Set(VALUE self, VALUE name, VALUE value) {
|
30
12
|
HandleScope handles;
|
@@ -43,7 +25,7 @@ VALUE v8_FunctionTemplate_New(int argc, VALUE *argv, VALUE self) {
|
|
43
25
|
VALUE code;
|
44
26
|
rb_scan_args(argc, argv, "00&", &code);
|
45
27
|
HandleScope handles;
|
46
|
-
Local<FunctionTemplate> t = FunctionTemplate::New(
|
28
|
+
Local<FunctionTemplate> t = FunctionTemplate::New(RacerRubyInvocationCallback, External::Wrap((void *)code));
|
47
29
|
return V8_Ref_Create(self,t,code);
|
48
30
|
}
|
49
31
|
|
data/lib/v8.rb
CHANGED
data/lib/v8/context.rb
CHANGED
@@ -6,14 +6,15 @@ module V8
|
|
6
6
|
|
7
7
|
def open(&block)
|
8
8
|
@native.open do
|
9
|
-
block.call(self)
|
10
|
-
raise JavascriptError.new(result) if result.kind_of?(C::Message)
|
11
|
-
end
|
9
|
+
block.call(self)
|
12
10
|
end if block_given?
|
13
11
|
end
|
14
12
|
|
15
13
|
def eval(javascript)
|
16
|
-
|
14
|
+
@native.eval(javascript).tap do |result|
|
15
|
+
raise JavascriptError.new(result) if result.kind_of?(C::Message)
|
16
|
+
return To.ruby(result)
|
17
|
+
end
|
17
18
|
end
|
18
19
|
|
19
20
|
def evaluate(*args)
|
@@ -36,6 +37,8 @@ module V8
|
|
36
37
|
class ContextError < StandardError
|
37
38
|
end
|
38
39
|
class JavascriptError < StandardError
|
39
|
-
|
40
|
+
def initialize(v8_message)
|
41
|
+
super(v8_message.Get())
|
42
|
+
end
|
40
43
|
end
|
41
44
|
end
|
data/spec/redjs/jsapi_spec.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require "#{File.dirname(__FILE__)}/../redjs_helper.rb"
|
3
2
|
|
4
3
|
describe "Ruby Javascript API" do
|
@@ -101,7 +100,7 @@ describe "Ruby Javascript API" do
|
|
101
100
|
|
102
101
|
it "can embed a closure into a context and call it" do
|
103
102
|
Context.open do |cxt|
|
104
|
-
cxt["say"] =
|
103
|
+
cxt["say"] = lambda {|word, times| word * times}
|
105
104
|
cxt.eval("say('Hello',2)").should == "HelloHello"
|
106
105
|
end
|
107
106
|
end
|
data/therubyracer.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{therubyracer}
|
5
|
-
s.version = "0.4.
|
5
|
+
s.version = "0.4.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Charles Lowell", "Bill Robertson"]
|
9
|
-
s.date = %q{
|
9
|
+
s.date = %q{2010-01-09}
|
10
10
|
s.description = %q{Embed the V8 Javascript interpreter into Ruby.}
|
11
11
|
s.email = ["cowboyd@thefrontside.net", "billrobertson42@gmail.com"]
|
12
12
|
s.extensions = ["ext/v8/extconf.rb"]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: therubyracer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Lowell
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date:
|
13
|
+
date: 2010-01-09 00:00:00 +02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -42,6 +42,8 @@ files:
|
|
42
42
|
- README.rdoc
|
43
43
|
- Rakefile
|
44
44
|
- docs/data_conversion.txt
|
45
|
+
- ext/v8/callbacks.cpp
|
46
|
+
- ext/v8/callbacks.h
|
45
47
|
- ext/v8/convert_ruby.cpp
|
46
48
|
- ext/v8/convert_ruby.h
|
47
49
|
- ext/v8/convert_string.cpp
|