therubyracer 0.11.0beta8-x86-freebsd-9
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/.gitignore +23 -0
- data/.travis.yml +10 -0
- data/Changelog.md +242 -0
- data/Gemfile +16 -0
- data/README.md +185 -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/build.rb +52 -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 +25 -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 +31 -0
- data/ext/v8/init.cc +39 -0
- data/ext/v8/init.so +0 -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 +334 -0
- data/ext/v8/primitive.cc +8 -0
- data/ext/v8/rr.cc +83 -0
- data/ext/v8/rr.h +932 -0
- data/ext/v8/script.cc +80 -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/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 +245 -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 +166 -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 +70 -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 +52 -0
- data/spec/v8/context_spec.rb +19 -0
- data/spec/v8/conversion_spec.rb +52 -0
- data/spec/v8/error_spec.rb +165 -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 +20 -0
- metadata +164 -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
|
+
}
|