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.

Files changed (92) hide show
  1. data/.gitignore +23 -0
  2. data/.travis.yml +10 -0
  3. data/Changelog.md +242 -0
  4. data/Gemfile +16 -0
  5. data/README.md +185 -0
  6. data/Rakefile +42 -0
  7. data/benchmarks.rb +218 -0
  8. data/ext/v8/accessor.cc +181 -0
  9. data/ext/v8/array.cc +26 -0
  10. data/ext/v8/backref.cc +45 -0
  11. data/ext/v8/build.rb +52 -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 +25 -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 +31 -0
  23. data/ext/v8/init.cc +39 -0
  24. data/ext/v8/init.so +0 -0
  25. data/ext/v8/invocation.cc +86 -0
  26. data/ext/v8/locker.cc +77 -0
  27. data/ext/v8/message.cc +51 -0
  28. data/ext/v8/object.cc +334 -0
  29. data/ext/v8/primitive.cc +8 -0
  30. data/ext/v8/rr.cc +83 -0
  31. data/ext/v8/rr.h +932 -0
  32. data/ext/v8/script.cc +80 -0
  33. data/ext/v8/signature.cc +18 -0
  34. data/ext/v8/stack.cc +76 -0
  35. data/ext/v8/string.cc +47 -0
  36. data/ext/v8/template.cc +175 -0
  37. data/ext/v8/trycatch.cc +87 -0
  38. data/ext/v8/v8.cc +87 -0
  39. data/ext/v8/value.cc +239 -0
  40. data/lib/v8.rb +30 -0
  41. data/lib/v8/access.rb +5 -0
  42. data/lib/v8/access/indices.rb +40 -0
  43. data/lib/v8/access/invocation.rb +47 -0
  44. data/lib/v8/access/names.rb +65 -0
  45. data/lib/v8/array.rb +26 -0
  46. data/lib/v8/context.rb +245 -0
  47. data/lib/v8/conversion.rb +36 -0
  48. data/lib/v8/conversion/array.rb +11 -0
  49. data/lib/v8/conversion/class.rb +119 -0
  50. data/lib/v8/conversion/code.rb +38 -0
  51. data/lib/v8/conversion/fixnum.rb +11 -0
  52. data/lib/v8/conversion/fundamental.rb +11 -0
  53. data/lib/v8/conversion/hash.rb +11 -0
  54. data/lib/v8/conversion/indentity.rb +31 -0
  55. data/lib/v8/conversion/method.rb +26 -0
  56. data/lib/v8/conversion/object.rb +28 -0
  57. data/lib/v8/conversion/primitive.rb +7 -0
  58. data/lib/v8/conversion/proc.rb +5 -0
  59. data/lib/v8/conversion/reference.rb +16 -0
  60. data/lib/v8/conversion/string.rb +12 -0
  61. data/lib/v8/conversion/symbol.rb +7 -0
  62. data/lib/v8/conversion/time.rb +13 -0
  63. data/lib/v8/error.rb +166 -0
  64. data/lib/v8/function.rb +28 -0
  65. data/lib/v8/object.rb +79 -0
  66. data/lib/v8/stack.rb +85 -0
  67. data/lib/v8/version.rb +3 -0
  68. data/lib/v8/weak.rb +70 -0
  69. data/spec/c/array_spec.rb +17 -0
  70. data/spec/c/constants_spec.rb +20 -0
  71. data/spec/c/exception_spec.rb +26 -0
  72. data/spec/c/external_spec.rb +9 -0
  73. data/spec/c/function_spec.rb +46 -0
  74. data/spec/c/handles_spec.rb +35 -0
  75. data/spec/c/locker_spec.rb +38 -0
  76. data/spec/c/object_spec.rb +46 -0
  77. data/spec/c/script_spec.rb +28 -0
  78. data/spec/c/string_spec.rb +16 -0
  79. data/spec/c/template_spec.rb +30 -0
  80. data/spec/c/trycatch_spec.rb +51 -0
  81. data/spec/mem/blunt_spec.rb +42 -0
  82. data/spec/redjs_spec.rb +10 -0
  83. data/spec/spec_helper.rb +45 -0
  84. data/spec/threading_spec.rb +52 -0
  85. data/spec/v8/context_spec.rb +19 -0
  86. data/spec/v8/conversion_spec.rb +52 -0
  87. data/spec/v8/error_spec.rb +165 -0
  88. data/spec/v8/function_spec.rb +9 -0
  89. data/spec/v8/object_spec.rb +15 -0
  90. data/thefrontside.png +0 -0
  91. data/therubyracer.gemspec +20 -0
  92. metadata +164 -0
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe V8::C::Template do
4
+
5
+ describe V8::C::FunctionTemplate do
6
+ it "can be created with no arguments" do
7
+ t = V8::C::FunctionTemplate::New()
8
+ t.GetFunction().Call(@cxt.Global(),[]).StrictEquals(@cxt.Global()).should be_true
9
+ end
10
+
11
+ it "can be created with a callback" do
12
+ receiver = V8::C::Object::New()
13
+ f = nil
14
+ callback = lambda do |arguments|
15
+ arguments.Length().should be(2)
16
+ arguments[0].Utf8Value().should eql 'one'
17
+ arguments[1].Utf8Value().should eql 'two'
18
+ arguments.Callee().StrictEquals(f).should be_true
19
+ arguments.This().StrictEquals(receiver).should be_true
20
+ arguments.Holder().StrictEquals(receiver).should be_true
21
+ arguments.IsConstructCall().should be_false
22
+ arguments.Data().Value().should be(42)
23
+ V8::C::String::New("result")
24
+ end
25
+ t = V8::C::FunctionTemplate::New(callback, V8::C::External::New(42))
26
+ f = t.GetFunction()
27
+ f.Call(receiver, [V8::C::String::New('one'), V8::C::String::New('two')]).Utf8Value().should eql "result"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe V8::C::External do
4
+
5
+ it "can catch javascript exceptions" do
6
+ V8::C::V8::SetCaptureStackTraceForUncaughtExceptions(true, 99, V8::C::StackTrace::kDetailed)
7
+ V8::C::TryCatch() do |trycatch|
8
+ source = V8::C::String::New(<<-JS)
9
+ function one() {
10
+ two()
11
+ }
12
+ function two() {
13
+ three()
14
+ }
15
+ function three() {
16
+ boom()
17
+ }
18
+ function boom() {
19
+ throw new Error('boom!')
20
+ }
21
+ eval('one()')
22
+ JS
23
+ filename = V8::C::String::New("<eval>")
24
+ script = V8::C::Script::New(source, filename)
25
+ result = script.Run()
26
+ trycatch.HasCaught().should be_true
27
+ trycatch.CanContinue().should be_true
28
+ exception = trycatch.Exception()
29
+ exception.should_not be_nil
30
+ exception.IsNativeError().should be_true
31
+ trycatch.StackTrace().Utf8Value().should match /boom.*three.*two.*one/m
32
+ message = trycatch.Message();
33
+ message.should_not be_nil
34
+ message.Get().Utf8Value().should eql "Uncaught Error: boom!"
35
+ message.GetSourceLine().Utf8Value().should eql " throw new Error('boom!')"
36
+ message.GetScriptResourceName().Utf8Value().should eql "<eval>"
37
+ message.GetLineNumber().should eql 11
38
+ stack = message.GetStackTrace()
39
+ stack.should_not be_nil
40
+ stack.GetFrameCount().should eql 6
41
+ frame = stack.GetFrame(0)
42
+ frame.GetLineNumber().should eql 11
43
+ frame.GetColumn().should eql 15
44
+ frame.GetScriptName().Utf8Value().should eql "<eval>"
45
+ frame.GetScriptNameOrSourceURL().Utf8Value().should eql "<eval>"
46
+ frame.IsEval().should be_false
47
+ stack.GetFrame(4).IsEval().should be_true
48
+ frame.IsConstructor().should be_false
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe "A Very blunt test to make sure that we aren't doing stupid leaks", :memory => true do
4
+ before do
5
+ if Object.const_defined?(:RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
6
+ pending 'need to figure out how to do memory sanity checks on rbx'
7
+ end
8
+ #allocate a single context to make sure that v8 loads its snapshot and
9
+ #we pay the overhead.
10
+ V8::Context.new
11
+ @start_memory = process_memory
12
+ GC.stress = true
13
+ end
14
+
15
+ after do
16
+ GC.stress = false
17
+ end
18
+ it "won't increase process memory by more than 50% no matter how many contexts we create" do
19
+ 500.times do
20
+ V8::Context.new
21
+ run_v8_gc
22
+ end
23
+ process_memory.should <= @start_memory * 1.5
24
+ end
25
+
26
+ it "can eval simple value passing statements repeatedly without significantly increasing memory" do
27
+ V8::C::Locker() do
28
+ cxt = V8::Context.new
29
+ 500.times do
30
+ cxt.eval('7 * 6')
31
+ run_v8_gc
32
+ end
33
+ end
34
+ process_memory.should <= @start_memory * 1.1
35
+ end
36
+
37
+ def process_memory
38
+ /\w*[ ]*#{Process.pid}[ ]*([.,\d]*)[ ]*([.,\d]*)[ ]*([\d]*)[ ]*([\d]*)/.match(`ps aux`)[4].to_i
39
+ end
40
+
41
+ end
42
+
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'redjs/load_specs'
3
+ module RedJS
4
+ Context = V8::Context
5
+ Error = V8::Error
6
+ end
7
+ describe V8::Context do
8
+ pending "not ready for prime-time"
9
+ #it_behaves_like 'RedJS::Context'
10
+ end
@@ -0,0 +1,45 @@
1
+ require 'v8'
2
+
3
+ def run_v8_gc
4
+ V8::C::V8::LowMemoryNotification()
5
+ while !V8::C::V8::IdleNotification() do
6
+ end
7
+ end
8
+
9
+ def rputs(msg)
10
+ puts "<pre>#{ERB::Util.h(msg)}</pre>"
11
+ $stdout.flush
12
+ end
13
+
14
+ module ExplicitScoper;end
15
+ module Autoscope
16
+ def instance_eval(*args, &block)
17
+ return super unless low_level_c_spec? && !explicitly_defines_scope?
18
+ V8::C::Locker() do
19
+ V8::C::HandleScope() do
20
+ @cxt = V8::C::Context::New()
21
+ begin
22
+ @cxt.Enter()
23
+ super(*args, &block)
24
+ ensure
25
+ @cxt.Exit()
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def low_level_c_spec?
32
+ return false unless described_class
33
+ described_class.name =~ /^V8::C::/
34
+ end
35
+
36
+ def explicitly_defines_scope?
37
+ is_a?(ExplicitScoper)
38
+ end
39
+ end
40
+
41
+ RSpec.configure do |c|
42
+ c.before(:each) do
43
+ extend Autoscope
44
+ end
45
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe "using v8 from multiple threads", :threads => true do
4
+
5
+ it "creates contexts from within threads" do
6
+ 10.times.collect do
7
+ Thread.new do
8
+ V8::Context.new
9
+ end
10
+ end.each {|t| t.join}
11
+ V8::Context.new
12
+ end
13
+
14
+ it "executes codes on multiple threads simultaneously" do
15
+ 5.times.collect{V8::Context.new}.collect do |ctx|
16
+ Thread.new do
17
+ ctx['x'] = 99
18
+ while ctx['x'] > 0
19
+ ctx.eval 'for (i=10000;i;i--){};--x'
20
+ end
21
+ end
22
+ end.each {|t| t.join}
23
+ end
24
+
25
+ it "can access the current thread id" do
26
+ V8::C::Locker() do
27
+ V8::C::V8::GetCurrentThreadId().should_not be_nil
28
+ end
29
+ end
30
+
31
+ it "can pre-empt a running JavaScript thread" do
32
+ pending "need to release the GIL while executing V8 code"
33
+ begin
34
+ V8::C::Locker::StartPreemption(2)
35
+ thread_id = nil
36
+ Thread.new do
37
+ loop until thread_id
38
+ puts "thread id: #{thread_id}"
39
+ V8::C::V8::TerminateExecution(thread_id)
40
+ end
41
+ Thread.new do
42
+ V8::C::Locker() do
43
+ thread_id = V8::C::V8::GetCurrentThreadId()
44
+ V8::Context.new {|cxt| cxt.eval('while (true) {}')}
45
+ end
46
+ end
47
+ V8::C::V8::TerminateExecution(thread_id)
48
+ ensure
49
+ V8::C::Locker::StopPreemption()
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe V8::Context do
4
+ it "can be disposed of" do
5
+ cxt = V8::Context.new
6
+ cxt.enter do
7
+ cxt['object'] = V8::Object.new
8
+ end
9
+ cxt.dispose()
10
+
11
+ lambda {cxt.eval('1 + 1')}.should raise_error
12
+ lambda {cxt['object']}.should raise_error
13
+ end
14
+
15
+ it "can be disposed of any number of times" do
16
+ cxt = V8::Context.new
17
+ 10.times {cxt.dispose()}
18
+ end
19
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'bigdecimal'
3
+ describe V8::Conversion do
4
+
5
+ let(:cxt) { V8::Context.new }
6
+
7
+ it "can embed BigDecimal values" do
8
+ cxt['big'] = BigDecimal.new('1.1')
9
+ cxt['big'].should eql BigDecimal.new('1.1')
10
+ end
11
+
12
+ it "doesn't try to use V8::Conversion::Class::* as root objects" do
13
+ klass = Class.new do
14
+ class << self
15
+ def test
16
+ Set.new
17
+ end
18
+ end
19
+ end
20
+
21
+ klass.test.should be_instance_of(::Set)
22
+ end
23
+
24
+ context "::Fixnum" do
25
+ context "for 32-bit numbers" do
26
+ it "should convert positive integer" do
27
+ cxt['fixnum_a'] = 123
28
+ cxt['fixnum_a'].should == 123
29
+ cxt['fixnum_a'].should be_instance_of(Fixnum)
30
+ end
31
+
32
+ it "should convert negative integer" do
33
+ cxt['fixnum_b'] = -123
34
+ cxt['fixnum_b'].should == -123
35
+ cxt['fixnum_b'].should be_instance_of(Fixnum)
36
+ end
37
+ end
38
+
39
+ context "for 64-bit numbers" do
40
+ it "should convert positive integer" do
41
+ cxt['fixnum_c'] = 0x100000000
42
+ cxt['fixnum_c'].should == 0x100000000
43
+ end
44
+
45
+ it "should convert negative integer" do
46
+ cxt['fixnum_d'] = -0x100000000
47
+ cxt['fixnum_d'].should == -0x100000000
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ describe V8::Error do
6
+
7
+ before do
8
+ @cxt = V8::Context.new
9
+ @cxt['one'] = lambda do
10
+ @cxt.eval('two()', 'one.js')
11
+ end
12
+ @cxt['two'] = lambda do
13
+ @cxt.eval('three()', 'two.js')
14
+ end
15
+ end
16
+
17
+ it "captures a message without over nesting when the error is an error" do
18
+ throw! do |e|
19
+ e.message.should == "BOOM!"
20
+ end
21
+ end
22
+
23
+ it "captures the js message without over nesting when the error is a normal object" do
24
+ throw!('{foo: "bar"}') do |e|
25
+ e.message.should == "[object Object]"
26
+ end
27
+ throw!('{message: "bar"}') do |e|
28
+ e.message.should == "bar"
29
+ end
30
+ end
31
+
32
+ it "captures a thrown value as the message" do
33
+ throw!('"BOOM!"') do |e|
34
+ e.message.should == "BOOM!"
35
+ end
36
+ throw!('6') do |e|
37
+ e.message.should == '6'
38
+ end
39
+ end
40
+
41
+ it "has a reference to the root javascript cause" do
42
+ throw!('"I am a String"') do |e|
43
+ e.should_not be_in_ruby
44
+ e.should be_in_javascript
45
+ e.value['message'].should == "I am a String"
46
+ end
47
+ end
48
+
49
+ it "has a reference to the root ruby cause if one exists" do
50
+ StandardError.new("BOOM!").tap do |bomb|
51
+ @cxt['boom'] = lambda do
52
+ raise bomb
53
+ end
54
+ lambda {
55
+ @cxt.eval('boom()', 'boom.js')
56
+ }.should(raise_error do |raised|
57
+ raised.should be_in_ruby
58
+ raised.should_not be_in_javascript
59
+ raised.root_cause.should be(bomb)
60
+ end)
61
+ end
62
+ end
63
+
64
+ describe "backtrace" do
65
+ it "is mixed with ruby and javascript" do
66
+ throw! do |e|
67
+ e.backtrace.first.should == "at three.js:1:7"
68
+ e.backtrace[1].should =~ /error_spec.rb/
69
+ e.backtrace[2].should == "at two.js:1:1"
70
+ e.backtrace[3].should =~ /error_spec.rb/
71
+ e.backtrace[4].should == "at one.js:1:1"
72
+ end
73
+ end
74
+
75
+ it "can be set to show only ruby frames" do
76
+ throw! do |e|
77
+ e.backtrace(:ruby).each do |frame|
78
+ frame.should =~ /(\.rb|):\d+/
79
+ end
80
+ end
81
+ end
82
+
83
+ it "can be set to show only javascript frames" do
84
+ throw! do |e|
85
+ e.backtrace(:javascript).each do |frame|
86
+ frame.should =~ /\.js:\d:\d/
87
+ end
88
+ end
89
+ end
90
+
91
+ it "includes a mystery marker when the original frame is unavailable because what got thrown wasn't an error" do
92
+ throw!("6") do |e|
93
+ e.backtrace.first.should == 'at three.js:1:1'
94
+ end
95
+ end
96
+
97
+ it "has a source name and line number when there is a javascript SyntaxError" do
98
+ lambda do
99
+ @cxt.eval(<<-INVALID, 'source.js')
100
+ "this line is okay";
101
+ "this line has a syntax error because it ends with a colon":
102
+ "this line is also okay";
103
+ "how do I find out that line 2 has the syntax error?";
104
+ INVALID
105
+ end.should raise_error(V8::JSError) {|error|
106
+ error.message.should eql 'Unexpected token : at source.js:2:61'
107
+ }
108
+ end
109
+
110
+ it "can start with ruby at the bottom" do
111
+ @cxt['boom'] = lambda do
112
+ raise StandardError, "Bif!"
113
+ end
114
+ lambda {
115
+ @cxt.eval('boom()', "boom.js")
116
+ }.should(raise_error {|e|
117
+ e.backtrace.first.should =~ /error_spec\.rb/
118
+ e.backtrace[1].should =~ /boom.js/
119
+ })
120
+ end
121
+ end
122
+
123
+
124
+ def throw!(js = "new Error('BOOM!')", &block)
125
+ @cxt['three'] = lambda do
126
+ @cxt.eval("throw #{js}", 'three.js')
127
+ end
128
+ lambda do
129
+ @cxt['one'].call()
130
+ end.should(raise_error(V8::JSError, &block))
131
+ end
132
+ end
133
+
134
+
135
+ # describe V8::Error do
136
+ # describe "A ruby exception thrown inside JavaScript" do
137
+ # before do
138
+ # @error = StandardError.new('potato')
139
+ # begin
140
+ # V8::Context.new do |cxt|
141
+ # cxt['one'] = lambda do
142
+ # cxt.eval('two()', 'one.js')
143
+ # end
144
+ # cxt['two'] = lambda do
145
+ # cxt.eval('three()', 'two.js')
146
+ # end
147
+ # cxt['three'] = lambda do
148
+ # raise @error
149
+ # end
150
+ # cxt.eval('one()')
151
+ # end
152
+ # rescue StandardError => e
153
+ # @thrown = e
154
+ # end
155
+ # end
156
+ # it "is raised up through the call stack" do
157
+ # @thrown.should be(@error)
158
+ # end
159
+ #
160
+ # it "shows both the javascript and the ruby callframes" do
161
+ # puts @error.backtrace.join('<br/>')
162
+ # end
163
+ #
164
+ # end
165
+ # end