therubyracer-tmpfork 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 +15 -0
- data/README.md +224 -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.rb +30 -0
- data/lib/v8/access.rb +5 -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/array.rb +26 -0
- data/lib/v8/context.rb +258 -0
- data/lib/v8/conversion.rb +36 -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/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/spec/c/array_spec.rb +17 -0
- data/spec/c/constants_spec.rb +20 -0
- data/spec/c/exception_spec.rb +26 -0
- data/spec/c/external_spec.rb +9 -0
- data/spec/c/function_spec.rb +46 -0
- data/spec/c/handles_spec.rb +35 -0
- data/spec/c/locker_spec.rb +38 -0
- data/spec/c/object_spec.rb +46 -0
- data/spec/c/script_spec.rb +28 -0
- data/spec/c/string_spec.rb +16 -0
- data/spec/c/template_spec.rb +30 -0
- data/spec/c/trycatch_spec.rb +51 -0
- data/spec/mem/blunt_spec.rb +42 -0
- data/spec/redjs_spec.rb +10 -0
- data/spec/spec_helper.rb +45 -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-tmpfork.gemspec +22 -0
- metadata +186 -0
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/setup'
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
|
5
|
+
task :clean do
|
6
|
+
sh "rm -rf lib/v8/init.bundle lib/v8/init.so"
|
7
|
+
sh "rm -rf pkg"
|
8
|
+
end
|
9
|
+
|
10
|
+
require "rake/extensiontask"
|
11
|
+
Rake::ExtensionTask.new("init", eval(File.read("therubyracer.gemspec"))) do |ext|
|
12
|
+
ext.ext_dir = "ext/v8"
|
13
|
+
ext.lib_dir = "lib/v8"
|
14
|
+
ext.source_pattern = "*.{cc,h}"
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'rspec/core/rake_task'
|
18
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
19
|
+
task.rspec_opts = '--tag ~memory --tag ~threads'
|
20
|
+
end
|
21
|
+
|
22
|
+
task :sanity => [:clean, :compile] do
|
23
|
+
sh %q{ruby -Ilib -e "require 'v8'"}
|
24
|
+
end
|
25
|
+
|
26
|
+
NativeGem = "pkg/therubyracer-#{V8::VERSION}-#{Gem::Platform.new(RUBY_PLATFORM)}.gem"
|
27
|
+
file NativeGem => :build do
|
28
|
+
require "rubygems/compiler"
|
29
|
+
compiler = Gem::Compiler.new("pkg/therubyracer-#{V8::VERSION}.gem", 'pkg')
|
30
|
+
compiler.compile
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Build #{NativeGem} into the pkg directory"
|
34
|
+
task "build:native" => NativeGem
|
35
|
+
|
36
|
+
desc "Build and install #{File.basename NativeGem} into system gems"
|
37
|
+
task "install:native" => "build:native" do
|
38
|
+
sh "gem install #{NativeGem}"
|
39
|
+
end
|
40
|
+
|
41
|
+
task :default => :spec
|
42
|
+
|
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
|
+
}
|