therubyracer-xcode 0.12.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.travis.yml +14 -0
- data/Changelog.md +263 -0
- data/Gemfile +12 -0
- data/README.md +227 -0
- data/Rakefile +42 -0
- data/benchmarks.rb +218 -0
- data/ext/v8/accessor.cc +181 -0
- data/ext/v8/array.cc +26 -0
- data/ext/v8/backref.cc +45 -0
- data/ext/v8/constants.cc +34 -0
- data/ext/v8/constraints.cc +52 -0
- data/ext/v8/context.cc +130 -0
- data/ext/v8/date.cc +18 -0
- data/ext/v8/exception.cc +38 -0
- data/ext/v8/extconf.rb +34 -0
- data/ext/v8/external.cc +43 -0
- data/ext/v8/function.cc +58 -0
- data/ext/v8/gc.cc +43 -0
- data/ext/v8/handles.cc +34 -0
- data/ext/v8/heap.cc +35 -0
- data/ext/v8/init.cc +39 -0
- data/ext/v8/invocation.cc +86 -0
- data/ext/v8/locker.cc +77 -0
- data/ext/v8/message.cc +51 -0
- data/ext/v8/object.cc +335 -0
- data/ext/v8/primitive.cc +8 -0
- data/ext/v8/rr.cc +83 -0
- data/ext/v8/rr.h +934 -0
- data/ext/v8/script.cc +115 -0
- data/ext/v8/signature.cc +18 -0
- data/ext/v8/stack.cc +76 -0
- data/ext/v8/string.cc +47 -0
- data/ext/v8/template.cc +175 -0
- data/ext/v8/trycatch.cc +87 -0
- data/ext/v8/v8.cc +87 -0
- data/ext/v8/value.cc +239 -0
- data/lib/therubyracer.rb +1 -0
- data/lib/v8/access/indices.rb +40 -0
- data/lib/v8/access/invocation.rb +47 -0
- data/lib/v8/access/names.rb +65 -0
- data/lib/v8/access.rb +5 -0
- data/lib/v8/array.rb +26 -0
- data/lib/v8/context.rb +258 -0
- data/lib/v8/conversion/array.rb +11 -0
- data/lib/v8/conversion/class.rb +119 -0
- data/lib/v8/conversion/code.rb +38 -0
- data/lib/v8/conversion/fixnum.rb +11 -0
- data/lib/v8/conversion/fundamental.rb +11 -0
- data/lib/v8/conversion/hash.rb +11 -0
- data/lib/v8/conversion/indentity.rb +31 -0
- data/lib/v8/conversion/method.rb +26 -0
- data/lib/v8/conversion/object.rb +28 -0
- data/lib/v8/conversion/primitive.rb +7 -0
- data/lib/v8/conversion/proc.rb +5 -0
- data/lib/v8/conversion/reference.rb +16 -0
- data/lib/v8/conversion/string.rb +12 -0
- data/lib/v8/conversion/symbol.rb +7 -0
- data/lib/v8/conversion/time.rb +13 -0
- data/lib/v8/conversion.rb +36 -0
- data/lib/v8/error.rb +169 -0
- data/lib/v8/function.rb +28 -0
- data/lib/v8/object.rb +79 -0
- data/lib/v8/stack.rb +85 -0
- data/lib/v8/version.rb +3 -0
- data/lib/v8/weak.rb +82 -0
- data/lib/v8.rb +30 -0
- data/spec/c/array_spec.rb +19 -0
- data/spec/c/constants_spec.rb +22 -0
- data/spec/c/exception_spec.rb +28 -0
- data/spec/c/external_spec.rb +11 -0
- data/spec/c/function_spec.rb +48 -0
- data/spec/c/handles_spec.rb +31 -0
- data/spec/c/locker_spec.rb +36 -0
- data/spec/c/object_spec.rb +47 -0
- data/spec/c/script_spec.rb +30 -0
- data/spec/c/string_spec.rb +18 -0
- data/spec/c/template_spec.rb +31 -0
- data/spec/c/trycatch_spec.rb +52 -0
- data/spec/mem/blunt_spec.rb +42 -0
- data/spec/redjs_spec.rb +10 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/threading_spec.rb +64 -0
- data/spec/v8/context_spec.rb +19 -0
- data/spec/v8/conversion_spec.rb +52 -0
- data/spec/v8/error_spec.rb +167 -0
- data/spec/v8/function_spec.rb +9 -0
- data/spec/v8/object_spec.rb +15 -0
- data/thefrontside.png +0 -0
- data/therubyracer.gemspec +22 -0
- metadata +186 -0
data/benchmarks.rb
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'v8'
|
4
|
+
require 'benchmark'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
OPTIONS = {
|
8
|
+
:times => 5,
|
9
|
+
:mode => :object,
|
10
|
+
:objects => 500
|
11
|
+
}
|
12
|
+
|
13
|
+
parser = OptionParser.new do |opts|
|
14
|
+
opts.on("-t", "--times [T]", Integer, "run benchmark N times") do |t|
|
15
|
+
OPTIONS[:times] = t
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on("-m", "--mode [MODE]", [:object, :function, :eval], "select the type of object access to stress test") do |mode|
|
19
|
+
mode = mode.to_sym
|
20
|
+
raise "unsupported mode #{mode}" unless [:object,:function,:eval].include?(mode)
|
21
|
+
OPTIONS[:mode] = mode
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-o", "--objects [N]", Integer, "create N objects for each iteration") do |n|
|
25
|
+
OPTIONS[:objects] = n
|
26
|
+
end
|
27
|
+
opts
|
28
|
+
end
|
29
|
+
|
30
|
+
parser.parse! ARGV
|
31
|
+
|
32
|
+
MODE = OPTIONS[:mode]
|
33
|
+
TIMES = OPTIONS[:times]
|
34
|
+
OBJECTS = OPTIONS[:objects]
|
35
|
+
|
36
|
+
puts "using #{OPTIONS[:mode]}"
|
37
|
+
if MODE==:object
|
38
|
+
def get(i)
|
39
|
+
@cxt["test"]["objects"][i]
|
40
|
+
end
|
41
|
+
elsif MODE==:function
|
42
|
+
def get(i)
|
43
|
+
@cxt["test"].getObject(i)
|
44
|
+
end
|
45
|
+
elsif MODE==:eval
|
46
|
+
def get(i)
|
47
|
+
@cxt.eval "test.getObject(#{i})"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
js= <<JS
|
52
|
+
|
53
|
+
function createTest()
|
54
|
+
{
|
55
|
+
var test = {};
|
56
|
+
test.objects = [];
|
57
|
+
test.seed = 49734321;
|
58
|
+
test.summ;
|
59
|
+
|
60
|
+
test.random = function()
|
61
|
+
{
|
62
|
+
// Robert Jenkins' 32 bit integer hash function.
|
63
|
+
test.seed = ((test.seed + 0x7ed55d16) + (test.seed << 12)) & 0xffffffff;
|
64
|
+
test.seed = ((test.seed ^ 0xc761c23c) ^ (test.seed >>> 19)) & 0xffffffff;
|
65
|
+
test.seed = ((test.seed + 0x165667b1) + (test.seed << 5)) & 0xffffffff;
|
66
|
+
test.seed = ((test.seed + 0xd3a2646c) ^ (test.seed << 9)) & 0xffffffff;
|
67
|
+
test.seed = ((test.seed + 0xfd7046c5) + (test.seed << 3)) & 0xffffffff;
|
68
|
+
test.seed = ((test.seed ^ 0xb55a4f09) ^ (test.seed >>> 16)) & 0xffffffff;
|
69
|
+
return (test.seed & 0xfffffff) / 0x10000000;
|
70
|
+
};
|
71
|
+
|
72
|
+
test.init = function()
|
73
|
+
{
|
74
|
+
test.objects = [];
|
75
|
+
for(var i=0; i<#{OBJECTS}; i++)
|
76
|
+
{
|
77
|
+
var hash = {};
|
78
|
+
for(var j=0; j<10; j++)
|
79
|
+
{
|
80
|
+
var isString = test.random();
|
81
|
+
var key = "str" + test.random();
|
82
|
+
var value;
|
83
|
+
if(isString < 0.5)
|
84
|
+
value = "str" + test.random();
|
85
|
+
else
|
86
|
+
value = test.random();
|
87
|
+
hash[key] = value;
|
88
|
+
}
|
89
|
+
test.objects[i] = hash;
|
90
|
+
}
|
91
|
+
return test.objects.length;
|
92
|
+
}
|
93
|
+
|
94
|
+
test.findSum = function()
|
95
|
+
{
|
96
|
+
test.summ = 0;
|
97
|
+
var length = test.objects.length;
|
98
|
+
for(var i=0; i<length; i++)
|
99
|
+
{
|
100
|
+
var hash = test.objects[i];
|
101
|
+
for (var k in hash)
|
102
|
+
{
|
103
|
+
if (hash.hasOwnProperty(k) && (typeof(hash[k]) == "number"))
|
104
|
+
{
|
105
|
+
test.summ += hash[k];
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
return test.summ;
|
110
|
+
};
|
111
|
+
|
112
|
+
test.finalCheck = function()
|
113
|
+
{
|
114
|
+
var summ = 0;
|
115
|
+
var length = test.objects.length;
|
116
|
+
for(var i=0; i<length; i++)
|
117
|
+
{
|
118
|
+
var hash = test.objects[i];
|
119
|
+
for (var k in hash)
|
120
|
+
{
|
121
|
+
if (hash.hasOwnProperty(k) && (typeof(hash[k]) == "number"))
|
122
|
+
{
|
123
|
+
summ += hash[k];
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
return summ ;
|
128
|
+
};
|
129
|
+
|
130
|
+
test.getObject = function(index)
|
131
|
+
{
|
132
|
+
if(!test.objects[index]) return {};
|
133
|
+
return test.objects[index];
|
134
|
+
}
|
135
|
+
|
136
|
+
test.setObject = function(index, object)
|
137
|
+
{
|
138
|
+
test.objects[index] = object;
|
139
|
+
}
|
140
|
+
|
141
|
+
return test;
|
142
|
+
}
|
143
|
+
|
144
|
+
JS
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
|
150
|
+
def profile
|
151
|
+
Benchmark.realtime do
|
152
|
+
yield
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_res result
|
157
|
+
result.to_f
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
|
164
|
+
puts "init js context..."
|
165
|
+
cxt = V8::Context.new
|
166
|
+
@cxt=cxt
|
167
|
+
cxt.eval(js)
|
168
|
+
|
169
|
+
cxt.eval('var test = createTest()')
|
170
|
+
|
171
|
+
puts "run init test"
|
172
|
+
result =profile do
|
173
|
+
TIMES.times do
|
174
|
+
cxt['test'].init()
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
puts "init time: #{get_res(result) / TIMES} sec."
|
179
|
+
sum1=sum2=0
|
180
|
+
puts "run findSum test"
|
181
|
+
|
182
|
+
result =profile do
|
183
|
+
TIMES.times do
|
184
|
+
sum1= cxt['test'].findSum
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
puts "findSum time: #{get_res(result) / TIMES} sec."
|
189
|
+
|
190
|
+
|
191
|
+
puts "run Objects inversion in ruby test"
|
192
|
+
result =profile do
|
193
|
+
TIMES.times do |j|
|
194
|
+
puts j
|
195
|
+
for i in 0..(OBJECTS-1) do
|
196
|
+
obj = get(i)
|
197
|
+
obj.each do |key, value|
|
198
|
+
if value.instance_of? Float
|
199
|
+
obj[key] = value * (-1)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
puts "Objects time: #{get_res(result) / TIMES} sec."
|
207
|
+
|
208
|
+
puts "run finalCheck test"
|
209
|
+
|
210
|
+
|
211
|
+
result =profile do
|
212
|
+
TIMES.times do
|
213
|
+
sum2= cxt['test'].findSum
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
puts "final check time: #{get_res(result) / TIMES} sec."
|
218
|
+
puts "#{sum1==sum2*(TIMES%2==0?1:-1) ? 'TEST PASS': 'TEST FAIL'}: Sum before inversions: #{sum1} / Sum after inversions: #{sum2}"
|
data/ext/v8/accessor.cc
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
#include "rr.h"
|
2
|
+
|
3
|
+
namespace rr {
|
4
|
+
|
5
|
+
VALUE Accessor::Info::Class;
|
6
|
+
|
7
|
+
void Accessor::Init() {
|
8
|
+
ClassBuilder("AccessorInfo").
|
9
|
+
defineMethod("This", &Info::This).
|
10
|
+
defineMethod("Holder", &Info::Holder).
|
11
|
+
defineMethod("Data", &Info::Data).
|
12
|
+
store(&Info::Class);
|
13
|
+
}
|
14
|
+
|
15
|
+
Accessor::Accessor(VALUE getter, VALUE setter, VALUE data_) : get(getter), set(setter), query(Qnil), deleter(Qnil), enumerator(Qnil), data(data_) {}
|
16
|
+
|
17
|
+
Accessor::Accessor(VALUE get, VALUE set, VALUE query, VALUE deleter, VALUE enumerator, VALUE data) {
|
18
|
+
this->get = get;
|
19
|
+
this->set = set;
|
20
|
+
this->query = query;
|
21
|
+
this->deleter = deleter;
|
22
|
+
this->enumerator = enumerator;
|
23
|
+
this->data = data;
|
24
|
+
}
|
25
|
+
|
26
|
+
Accessor::Accessor(v8::Handle<v8::Value> value) {
|
27
|
+
v8::Local<v8::Object> wrapper = value->ToObject();
|
28
|
+
this->get = unwrap(wrapper, 0);
|
29
|
+
this->set = unwrap(wrapper, 1);
|
30
|
+
this->query = unwrap(wrapper, 2);
|
31
|
+
this->deleter = unwrap(wrapper, 3);
|
32
|
+
this->enumerator = unwrap(wrapper, 4);
|
33
|
+
v8::Handle<v8::Value> data = wrapper->Get(5);
|
34
|
+
if (!data.IsEmpty() && !data->IsNull() && !data->IsUndefined()) {
|
35
|
+
this->data = Value(data);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
Accessor::operator v8::Handle<v8::Value>() {
|
40
|
+
v8::Local<v8::Object> wrapper = v8::Object::New();
|
41
|
+
wrap(wrapper, 0, this->get);
|
42
|
+
wrap(wrapper, 1, this->set);
|
43
|
+
wrap(wrapper, 2, this->query);
|
44
|
+
wrap(wrapper, 3, this->deleter);
|
45
|
+
wrap(wrapper, 4, this->enumerator);
|
46
|
+
if (RTEST(this->data)) {
|
47
|
+
wrapper->Set(5, Value(this->data));
|
48
|
+
}
|
49
|
+
return wrapper;
|
50
|
+
}
|
51
|
+
|
52
|
+
void Accessor::wrap(v8::Handle<v8::Object> wrapper, int index, VALUE value) {
|
53
|
+
if (RTEST(value)) {
|
54
|
+
wrapper->Set(index, External::wrap(value));
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
VALUE Accessor::unwrap(v8::Handle<v8::Object> wrapper, int index) {
|
59
|
+
v8::Handle<v8::Value> value = wrapper->Get(index);
|
60
|
+
if (value.IsEmpty() || !value->IsExternal()) {
|
61
|
+
return Qnil;
|
62
|
+
} else {
|
63
|
+
v8::Handle<v8::External> external(v8::External::Cast(*value));
|
64
|
+
return External::unwrap(external);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
VALUE Accessor::Info::This(VALUE self) {
|
70
|
+
return Object(Info(self)->This());
|
71
|
+
}
|
72
|
+
|
73
|
+
VALUE Accessor::Info::Holder(VALUE self) {
|
74
|
+
return Object(Info(self)->Holder());
|
75
|
+
}
|
76
|
+
|
77
|
+
VALUE Accessor::Info::Data(VALUE self) {
|
78
|
+
return Accessor(Info(self)->Data()).data;
|
79
|
+
}
|
80
|
+
|
81
|
+
v8::Handle<v8::Value> Accessor::AccessorGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
|
82
|
+
return Info(info).get(property);
|
83
|
+
}
|
84
|
+
|
85
|
+
void Accessor::AccessorSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
|
86
|
+
Info(info).set(property, value);
|
87
|
+
}
|
88
|
+
v8::Handle<v8::Value> Accessor::NamedPropertyGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
|
89
|
+
return Info(info).get(property);
|
90
|
+
}
|
91
|
+
v8::Handle<v8::Value> Accessor::NamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
|
92
|
+
return Info(info).set(property, value);
|
93
|
+
}
|
94
|
+
v8::Handle<v8::Integer> Accessor::NamedPropertyQuery(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
|
95
|
+
return Info(info).query(property);
|
96
|
+
}
|
97
|
+
v8::Handle<v8::Boolean> Accessor::NamedPropertyDeleter(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
|
98
|
+
return Info(info).remove(property);
|
99
|
+
}
|
100
|
+
v8::Handle<v8::Array> Accessor::NamedPropertyEnumerator(const v8::AccessorInfo& info) {
|
101
|
+
return Info(info).enumerateNames();
|
102
|
+
}
|
103
|
+
|
104
|
+
v8::Handle<v8::Value> Accessor::IndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) {
|
105
|
+
return Info(info).get(index);
|
106
|
+
}
|
107
|
+
v8::Handle<v8::Value> Accessor::IndexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
|
108
|
+
return Info(info).set(index, value);
|
109
|
+
}
|
110
|
+
v8::Handle<v8::Integer> Accessor::IndexedPropertyQuery(uint32_t index, const v8::AccessorInfo& info) {
|
111
|
+
return Info(info).query(index);
|
112
|
+
}
|
113
|
+
v8::Handle<v8::Boolean> Accessor::IndexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info) {
|
114
|
+
return Info(info).remove(index);
|
115
|
+
}
|
116
|
+
v8::Handle<v8::Array> Accessor::IndexedPropertyEnumerator(const v8::AccessorInfo& info) {
|
117
|
+
return Info(info).enumerateIndices();
|
118
|
+
}
|
119
|
+
|
120
|
+
Accessor::Info::Info(const v8::AccessorInfo& info) {
|
121
|
+
this->info = &info;
|
122
|
+
}
|
123
|
+
|
124
|
+
Accessor::Info::Info(VALUE value) {
|
125
|
+
Data_Get_Struct(value, class v8::AccessorInfo, info);
|
126
|
+
}
|
127
|
+
|
128
|
+
v8::Handle<v8::Value> Accessor::Info::get(v8::Local<v8::String> property) {
|
129
|
+
Accessor accessor(info->Data());
|
130
|
+
return Value(rb_funcall(accessor.get, rb_intern("call"), 2, (VALUE)String(property), (VALUE)*this));
|
131
|
+
}
|
132
|
+
|
133
|
+
v8::Handle<v8::Value> Accessor::Info::set(v8::Local<v8::String> property, v8::Local<v8::Value> value) {
|
134
|
+
Accessor accessor(info->Data());
|
135
|
+
return Value(rb_funcall(accessor.set, rb_intern("call"), 3, (VALUE)String(property), (VALUE)Value(value), (VALUE)*this));
|
136
|
+
}
|
137
|
+
|
138
|
+
v8::Handle<v8::Integer> Accessor::Info::query(v8::Local<v8::String> property) {
|
139
|
+
Accessor accessor(info->Data());
|
140
|
+
return v8::Integer::New(NUM2INT(rb_funcall(accessor.query, rb_intern("call"), 2, (VALUE)String(property), (VALUE)*this)));
|
141
|
+
}
|
142
|
+
|
143
|
+
v8::Handle<v8::Boolean> Accessor::Info::remove(v8::Local<v8::String> property) {
|
144
|
+
Accessor accessor(info->Data());
|
145
|
+
return v8::Boolean::New(Bool(rb_funcall(accessor.deleter, rb_intern("call"), 2, (VALUE)String(property), (VALUE)*this)));
|
146
|
+
}
|
147
|
+
|
148
|
+
v8::Handle<v8::Array> Accessor::Info::enumerateNames() {
|
149
|
+
Accessor accessor(info->Data());
|
150
|
+
return Array(rb_funcall(accessor.enumerator, rb_intern("call"), 1, (VALUE)*this));
|
151
|
+
}
|
152
|
+
|
153
|
+
v8::Handle<v8::Value> Accessor::Info::get(uint32_t index) {
|
154
|
+
Accessor accessor(info->Data());
|
155
|
+
return Value(rb_funcall(accessor.get, rb_intern("call"), 2, UINT2NUM(index), (VALUE)*this));
|
156
|
+
}
|
157
|
+
|
158
|
+
v8::Handle<v8::Value> Accessor::Info::set(uint32_t index, v8::Local<v8::Value> value) {
|
159
|
+
Accessor accessor(info->Data());
|
160
|
+
return Value(rb_funcall(accessor.set, rb_intern("call"), 3, UINT2NUM(index), (VALUE)Value(value), (VALUE)*this));
|
161
|
+
}
|
162
|
+
|
163
|
+
v8::Handle<v8::Integer> Accessor::Info::query(uint32_t index) {
|
164
|
+
Accessor accessor(info->Data());
|
165
|
+
return v8::Integer::New(NUM2INT(rb_funcall(accessor.query, rb_intern("call"), 2, UINT2NUM(index), (VALUE)*this)));
|
166
|
+
}
|
167
|
+
|
168
|
+
v8::Handle<v8::Boolean> Accessor::Info::remove(uint32_t index) {
|
169
|
+
Accessor accessor(info->Data());
|
170
|
+
return v8::Boolean::New(Bool(rb_funcall(accessor.deleter, rb_intern("call"), 2, UINT2NUM(index), (VALUE)*this)));
|
171
|
+
}
|
172
|
+
|
173
|
+
v8::Handle<v8::Array> Accessor::Info::enumerateIndices() {
|
174
|
+
Accessor accessor(info->Data());
|
175
|
+
return Array(rb_funcall(accessor.enumerator, rb_intern("call"), 1, (VALUE)*this));
|
176
|
+
}
|
177
|
+
|
178
|
+
Accessor::Info::operator VALUE() {
|
179
|
+
return Data_Wrap_Struct(Class, 0, 0, (void*)this->info);
|
180
|
+
}
|
181
|
+
}
|
data/ext/v8/array.cc
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#include "rr.h"
|
2
|
+
|
3
|
+
namespace rr {
|
4
|
+
|
5
|
+
void Array::Init() {
|
6
|
+
ClassBuilder("Array", Object::Class).
|
7
|
+
defineSingletonMethod("New", &New).
|
8
|
+
defineMethod("Length", &Length).
|
9
|
+
defineMethod("CloneElementAt", &CloneElementAt).
|
10
|
+
store(&Class);
|
11
|
+
}
|
12
|
+
|
13
|
+
VALUE Array::New(int argc, VALUE argv[], VALUE self) {
|
14
|
+
VALUE length; rb_scan_args(argc, argv, "01", &length);
|
15
|
+
return Array(v8::Array::New(RTEST(length) ? NUM2INT(length) : 0));
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE Array::Length(VALUE self) {
|
19
|
+
return UInt32(Array(self)->Length());
|
20
|
+
}
|
21
|
+
|
22
|
+
VALUE Array::CloneElementAt(VALUE self, VALUE index) {
|
23
|
+
return Object(Array(self)->CloneElementAt(UInt32(index)));
|
24
|
+
}
|
25
|
+
|
26
|
+
}
|
data/ext/v8/backref.cc
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#include "rr.h"
|
2
|
+
|
3
|
+
namespace rr {
|
4
|
+
|
5
|
+
VALUE Backref::Storage;
|
6
|
+
ID Backref::_new;
|
7
|
+
ID Backref::object;
|
8
|
+
|
9
|
+
void Backref::Init() {
|
10
|
+
Storage = rb_eval_string("V8::Weak::Ref");
|
11
|
+
rb_gc_register_address(&Storage);
|
12
|
+
_new = rb_intern("new");
|
13
|
+
object = rb_intern("object");
|
14
|
+
}
|
15
|
+
|
16
|
+
Backref::Backref(VALUE initial) {
|
17
|
+
set(initial);
|
18
|
+
rb_gc_register_address(&storage);
|
19
|
+
}
|
20
|
+
|
21
|
+
Backref::~Backref() {
|
22
|
+
rb_gc_unregister_address(&storage);
|
23
|
+
}
|
24
|
+
|
25
|
+
VALUE Backref::set(VALUE data) {
|
26
|
+
this->storage = rb_funcall(Storage, _new, 1, data);
|
27
|
+
return data;
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE Backref::get() {
|
31
|
+
return rb_funcall(storage, object, 0);
|
32
|
+
}
|
33
|
+
|
34
|
+
v8::Handle<v8::Value> Backref::toExternal() {
|
35
|
+
v8::Local<v8::Value> wrapper = v8::External::New(this);
|
36
|
+
v8::Persistent<v8::Value>::New(wrapper).MakeWeak(this, &release);
|
37
|
+
return wrapper;
|
38
|
+
}
|
39
|
+
|
40
|
+
void Backref::release(v8::Persistent<v8::Value> handle, void* data) {
|
41
|
+
handle.Dispose();
|
42
|
+
Backref* backref = (Backref*)data;
|
43
|
+
delete backref;
|
44
|
+
}
|
45
|
+
}
|
data/ext/v8/constants.cc
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#include "rr.h"
|
2
|
+
|
3
|
+
namespace rr {
|
4
|
+
VALUE Constants::_Undefined;
|
5
|
+
VALUE Constants::_Null;
|
6
|
+
VALUE Constants::_True;
|
7
|
+
VALUE Constants::_False;
|
8
|
+
void Constants::Init() {
|
9
|
+
ModuleBuilder("V8::C").
|
10
|
+
defineSingletonMethod("Undefined", &Undefined).
|
11
|
+
defineSingletonMethod("Null", &Null).
|
12
|
+
defineSingletonMethod("True", &True).
|
13
|
+
defineSingletonMethod("False", &False);
|
14
|
+
|
15
|
+
_Undefined = _Null = _True = _False = Qnil;
|
16
|
+
rb_gc_register_address(&_Undefined);
|
17
|
+
rb_gc_register_address(&_Null);
|
18
|
+
rb_gc_register_address(&_True);
|
19
|
+
rb_gc_register_address(&_False);
|
20
|
+
}
|
21
|
+
|
22
|
+
VALUE Constants::Undefined(VALUE self) {
|
23
|
+
return cached<Primitive, v8::Primitive>(&_Undefined, v8::Undefined());
|
24
|
+
}
|
25
|
+
VALUE Constants::Null(VALUE self) {
|
26
|
+
return cached<Primitive, v8::Primitive>(&_Null, v8::Null());
|
27
|
+
}
|
28
|
+
VALUE Constants::True(VALUE self) {
|
29
|
+
return cached<Bool, v8::Boolean>(&_True, v8::True());
|
30
|
+
}
|
31
|
+
VALUE Constants::False(VALUE self) {
|
32
|
+
return cached<Bool, v8::Boolean>(&_False, v8::False());
|
33
|
+
}
|
34
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#include "rr.h"
|
2
|
+
|
3
|
+
namespace rr {
|
4
|
+
void ResourceConstraints::Init() {
|
5
|
+
ClassBuilder("ResourceConstraints").
|
6
|
+
defineSingletonMethod("new", &initialize).
|
7
|
+
defineMethod("max_young_space_size", &max_young_space_size).
|
8
|
+
defineMethod("set_max_young_space_size", &set_max_young_space_size).
|
9
|
+
defineMethod("max_old_space_size", &max_old_space_size).
|
10
|
+
defineMethod("set_max_old_space_size", &set_max_old_space_size).
|
11
|
+
defineMethod("max_executable_size", &set_max_executable_size).
|
12
|
+
defineMethod("set_max_executable_size", &set_max_executable_size).
|
13
|
+
store(&Class);
|
14
|
+
ModuleBuilder("V8::C").
|
15
|
+
defineSingletonMethod("SetResourceConstraints", &SetResourceConstraints);
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE ResourceConstraints::SetResourceConstraints(VALUE self, VALUE constraints) {
|
19
|
+
Void(v8::SetResourceConstraints(ResourceConstraints(constraints)));
|
20
|
+
}
|
21
|
+
|
22
|
+
VALUE ResourceConstraints::initialize(VALUE self) {
|
23
|
+
return ResourceConstraints(new v8::ResourceConstraints());
|
24
|
+
}
|
25
|
+
VALUE ResourceConstraints::max_young_space_size(VALUE self) {
|
26
|
+
return INT2FIX(ResourceConstraints(self)->max_young_space_size());
|
27
|
+
}
|
28
|
+
VALUE ResourceConstraints::set_max_young_space_size(VALUE self, VALUE value) {
|
29
|
+
Void(ResourceConstraints(self)->set_max_young_space_size(NUM2INT(value)));
|
30
|
+
}
|
31
|
+
VALUE ResourceConstraints::max_old_space_size(VALUE self) {
|
32
|
+
return INT2FIX(ResourceConstraints(self)->max_old_space_size());
|
33
|
+
}
|
34
|
+
VALUE ResourceConstraints::set_max_old_space_size(VALUE self, VALUE value) {
|
35
|
+
Void(ResourceConstraints(self)->set_max_old_space_size(NUM2INT(value)));
|
36
|
+
}
|
37
|
+
VALUE ResourceConstraints::max_executable_size(VALUE self) {
|
38
|
+
return INT2FIX(ResourceConstraints(self)->max_executable_size());
|
39
|
+
}
|
40
|
+
VALUE ResourceConstraints::set_max_executable_size(VALUE self, VALUE value) {
|
41
|
+
Void(ResourceConstraints(self)->set_max_executable_size(NUM2INT(value)));
|
42
|
+
}
|
43
|
+
|
44
|
+
// What do these even mean?
|
45
|
+
// uint32_t* stack_limit() const { return stack_limit_; }
|
46
|
+
// // Sets an address beyond which the VM's stack may not grow.
|
47
|
+
// void set_stack_limit(uint32_t* value) { stack_limit_ = value; }
|
48
|
+
|
49
|
+
template <> void Pointer<v8::ResourceConstraints>::unwrap(VALUE value) {
|
50
|
+
Data_Get_Struct(value, class v8::ResourceConstraints, pointer);
|
51
|
+
}
|
52
|
+
}
|
data/ext/v8/context.cc
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
#include "rr.h"
|
2
|
+
|
3
|
+
namespace rr {
|
4
|
+
|
5
|
+
void Context::Init() {
|
6
|
+
ClassBuilder("Context").
|
7
|
+
defineSingletonMethod("New", &New).
|
8
|
+
defineSingletonMethod("GetCurrent", &GetCurrent).
|
9
|
+
defineSingletonMethod("GetEntered", &GetEntered).
|
10
|
+
defineSingletonMethod("GetCalling", &GetCalling).
|
11
|
+
defineSingletonMethod("InContext", &InContext).
|
12
|
+
defineMethod("Dispose", &Dispose).
|
13
|
+
defineMethod("Global", &Global).
|
14
|
+
defineMethod("DetachGlobal", &Global).
|
15
|
+
defineMethod("ReattachGlobal", &ReattachGlobal).
|
16
|
+
defineMethod("SetSecurityToken", &SetSecurityToken).
|
17
|
+
defineMethod("UseDefaultSecurityToken", &UseDefaultSecurityToken).
|
18
|
+
defineMethod("GetSecurityToken", &GetSecurityToken).
|
19
|
+
defineMethod("HasOutOfMemoryException", &HasOutOfMemoryException).
|
20
|
+
defineMethod("SetEmbedderData", &SetEmbedderData).
|
21
|
+
defineMethod("GetEmbedderData", &GetEmbedderData).
|
22
|
+
defineMethod("AllowCodeGenerationFromStrings", &AllowCodeGenerationFromStrings).
|
23
|
+
defineMethod("IsCodeGenerationFromStringsAllowed", &IsCodeGenerationFromStringsAllowed).
|
24
|
+
defineMethod("Enter", &Enter).
|
25
|
+
defineMethod("Exit", &Exit).
|
26
|
+
store(&Class);
|
27
|
+
ClassBuilder("ExtensionConfiguration").
|
28
|
+
defineSingletonMethod("new", &ExtensionConfiguration::initialize).
|
29
|
+
store(&ExtensionConfiguration::Class);
|
30
|
+
}
|
31
|
+
|
32
|
+
VALUE Context::Dispose(VALUE self) {
|
33
|
+
Void(Context(self).dispose())
|
34
|
+
}
|
35
|
+
|
36
|
+
VALUE Context::Global(VALUE self) {
|
37
|
+
return Object(Context(self)->Global());
|
38
|
+
}
|
39
|
+
|
40
|
+
VALUE Context::DetachGlobal(VALUE self) {
|
41
|
+
Void(Context(self)->DetachGlobal());
|
42
|
+
}
|
43
|
+
|
44
|
+
VALUE Context::ReattachGlobal(VALUE self, VALUE global) {
|
45
|
+
Void(Context(self)->ReattachGlobal(Object(global)));
|
46
|
+
}
|
47
|
+
|
48
|
+
VALUE Context::GetEntered(VALUE self) {
|
49
|
+
return Context(v8::Context::GetEntered());
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE Context::GetCurrent(VALUE self) {
|
53
|
+
return Context(v8::Context::GetCurrent());
|
54
|
+
}
|
55
|
+
|
56
|
+
VALUE Context::GetCalling(VALUE self) {
|
57
|
+
return Context(v8::Context::GetCalling());
|
58
|
+
}
|
59
|
+
|
60
|
+
VALUE Context::SetSecurityToken(VALUE self, VALUE token) {
|
61
|
+
Void(Context(self)->SetSecurityToken(Value(token)));
|
62
|
+
}
|
63
|
+
|
64
|
+
VALUE Context::UseDefaultSecurityToken(VALUE self) {
|
65
|
+
Void(Context(self)->UseDefaultSecurityToken());
|
66
|
+
}
|
67
|
+
|
68
|
+
VALUE Context::GetSecurityToken(VALUE self) {
|
69
|
+
return Value(Context(self)->GetSecurityToken());
|
70
|
+
}
|
71
|
+
|
72
|
+
VALUE Context::HasOutOfMemoryException(VALUE self) {
|
73
|
+
return Bool(Context(self)->HasOutOfMemoryException());
|
74
|
+
}
|
75
|
+
|
76
|
+
VALUE Context::InContext(VALUE self) {
|
77
|
+
return Bool(v8::Context::InContext());
|
78
|
+
}
|
79
|
+
|
80
|
+
VALUE Context::SetEmbedderData(VALUE self, VALUE index, VALUE data) {
|
81
|
+
Void(Context(self)->SetEmbedderData(NUM2INT(index), Value(data)));
|
82
|
+
}
|
83
|
+
|
84
|
+
VALUE Context::GetEmbedderData(VALUE self, VALUE index) {
|
85
|
+
Void(Context(self)->GetEmbedderData(NUM2INT(index)));
|
86
|
+
}
|
87
|
+
|
88
|
+
VALUE Context::AllowCodeGenerationFromStrings(VALUE self, VALUE allow) {
|
89
|
+
Void(Context(self)->AllowCodeGenerationFromStrings(RTEST(allow)));
|
90
|
+
}
|
91
|
+
|
92
|
+
VALUE Context::IsCodeGenerationFromStringsAllowed(VALUE self) {
|
93
|
+
return Bool(Context(self)->IsCodeGenerationFromStringsAllowed());
|
94
|
+
}
|
95
|
+
|
96
|
+
VALUE ExtensionConfiguration::initialize(VALUE self, VALUE names) {
|
97
|
+
int length = RARRAY_LENINT(names);
|
98
|
+
const char* array[length];
|
99
|
+
for (int i = 0; i < length; i++) {
|
100
|
+
array[i] = RSTRING_PTR(rb_ary_entry(names, i));
|
101
|
+
}
|
102
|
+
return ExtensionConfiguration(new v8::ExtensionConfiguration(length, array));
|
103
|
+
}
|
104
|
+
|
105
|
+
VALUE Context::New(int argc, VALUE argv[], VALUE self) {
|
106
|
+
VALUE extension_configuration; VALUE global_template; VALUE global_object;
|
107
|
+
rb_scan_args(argc, argv, "03", &extension_configuration, &global_template, &global_object);
|
108
|
+
v8::Persistent<v8::Context> context(v8::Context::New(
|
109
|
+
ExtensionConfiguration(extension_configuration),
|
110
|
+
*ObjectTemplate(global_template),
|
111
|
+
*Object(global_object)
|
112
|
+
));
|
113
|
+
Context reference(context);
|
114
|
+
context.Dispose();
|
115
|
+
return reference;
|
116
|
+
}
|
117
|
+
|
118
|
+
VALUE Context::Enter(VALUE self) {
|
119
|
+
Void(Context(self)->Enter());
|
120
|
+
}
|
121
|
+
|
122
|
+
VALUE Context::Exit(VALUE self) {
|
123
|
+
Void(Context(self)->Exit());
|
124
|
+
}
|
125
|
+
|
126
|
+
template <> void Pointer<v8::ExtensionConfiguration>::unwrap(VALUE value) {
|
127
|
+
Data_Get_Struct(value, class v8::ExtensionConfiguration, pointer);
|
128
|
+
}
|
129
|
+
|
130
|
+
}
|