therubyracer-discourse 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.travis.yml +11 -0
  4. data/Changelog.md +247 -0
  5. data/Gemfile +9 -0
  6. data/README.md +176 -0
  7. data/Rakefile +42 -0
  8. data/benchmarks.rb +218 -0
  9. data/ext/v8/accessor.cc +181 -0
  10. data/ext/v8/array.cc +26 -0
  11. data/ext/v8/backref.cc +45 -0
  12. data/ext/v8/constants.cc +34 -0
  13. data/ext/v8/constraints.cc +52 -0
  14. data/ext/v8/context.cc +130 -0
  15. data/ext/v8/date.cc +18 -0
  16. data/ext/v8/exception.cc +38 -0
  17. data/ext/v8/extconf.rb +34 -0
  18. data/ext/v8/external.cc +43 -0
  19. data/ext/v8/function.cc +58 -0
  20. data/ext/v8/gc.cc +43 -0
  21. data/ext/v8/handles.cc +34 -0
  22. data/ext/v8/heap.cc +35 -0
  23. data/ext/v8/init.cc +39 -0
  24. data/ext/v8/invocation.cc +86 -0
  25. data/ext/v8/locker.cc +77 -0
  26. data/ext/v8/message.cc +51 -0
  27. data/ext/v8/object.cc +335 -0
  28. data/ext/v8/primitive.cc +8 -0
  29. data/ext/v8/rr.cc +83 -0
  30. data/ext/v8/rr.h +934 -0
  31. data/ext/v8/script.cc +115 -0
  32. data/ext/v8/signature.cc +18 -0
  33. data/ext/v8/stack.cc +76 -0
  34. data/ext/v8/string.cc +47 -0
  35. data/ext/v8/template.cc +175 -0
  36. data/ext/v8/trycatch.cc +87 -0
  37. data/ext/v8/v8.cc +87 -0
  38. data/ext/v8/value.cc +239 -0
  39. data/lib/v8.rb +30 -0
  40. data/lib/v8/access.rb +5 -0
  41. data/lib/v8/access/indices.rb +40 -0
  42. data/lib/v8/access/invocation.rb +47 -0
  43. data/lib/v8/access/names.rb +65 -0
  44. data/lib/v8/array.rb +26 -0
  45. data/lib/v8/context.rb +256 -0
  46. data/lib/v8/conversion.rb +36 -0
  47. data/lib/v8/conversion/array.rb +11 -0
  48. data/lib/v8/conversion/class.rb +119 -0
  49. data/lib/v8/conversion/code.rb +38 -0
  50. data/lib/v8/conversion/fixnum.rb +11 -0
  51. data/lib/v8/conversion/fundamental.rb +11 -0
  52. data/lib/v8/conversion/hash.rb +11 -0
  53. data/lib/v8/conversion/indentity.rb +31 -0
  54. data/lib/v8/conversion/method.rb +26 -0
  55. data/lib/v8/conversion/object.rb +28 -0
  56. data/lib/v8/conversion/primitive.rb +7 -0
  57. data/lib/v8/conversion/proc.rb +5 -0
  58. data/lib/v8/conversion/reference.rb +16 -0
  59. data/lib/v8/conversion/string.rb +12 -0
  60. data/lib/v8/conversion/symbol.rb +7 -0
  61. data/lib/v8/conversion/time.rb +13 -0
  62. data/lib/v8/error.rb +169 -0
  63. data/lib/v8/function.rb +28 -0
  64. data/lib/v8/object.rb +79 -0
  65. data/lib/v8/stack.rb +85 -0
  66. data/lib/v8/version.rb +3 -0
  67. data/lib/v8/weak.rb +73 -0
  68. data/spec/c/array_spec.rb +17 -0
  69. data/spec/c/constants_spec.rb +20 -0
  70. data/spec/c/exception_spec.rb +26 -0
  71. data/spec/c/external_spec.rb +9 -0
  72. data/spec/c/function_spec.rb +46 -0
  73. data/spec/c/handles_spec.rb +35 -0
  74. data/spec/c/locker_spec.rb +38 -0
  75. data/spec/c/object_spec.rb +46 -0
  76. data/spec/c/script_spec.rb +28 -0
  77. data/spec/c/string_spec.rb +16 -0
  78. data/spec/c/template_spec.rb +30 -0
  79. data/spec/c/trycatch_spec.rb +51 -0
  80. data/spec/mem/blunt_spec.rb +42 -0
  81. data/spec/redjs_spec.rb +10 -0
  82. data/spec/spec_helper.rb +45 -0
  83. data/spec/threading_spec.rb +64 -0
  84. data/spec/v8/context_spec.rb +19 -0
  85. data/spec/v8/conversion_spec.rb +52 -0
  86. data/spec/v8/error_spec.rb +165 -0
  87. data/spec/v8/function_spec.rb +9 -0
  88. data/spec/v8/object_spec.rb +15 -0
  89. data/thefrontside.png +0 -0
  90. data/therubyracer.gemspec +21 -0
  91. metadata +163 -0
@@ -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
+
@@ -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}"
@@ -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
+ }
@@ -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
+ }