therubyracer-freebsd 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/.yardopts +1 -0
- data/Changelog.md +231 -0
- data/Gemfile +3 -0
- data/README.md +167 -0
- data/Rakefile +26 -0
- data/bin/therubyracer +11 -0
- data/ext/v8/extconf.rb +26 -0
- data/ext/v8/rr.cpp +189 -0
- data/ext/v8/rr.h +41 -0
- data/ext/v8/v8.cpp +48 -0
- data/ext/v8/v8_array.cpp +48 -0
- data/ext/v8/v8_array.h +8 -0
- data/ext/v8/v8_callbacks.cpp +81 -0
- data/ext/v8/v8_callbacks.h +8 -0
- data/ext/v8/v8_context.cpp +92 -0
- data/ext/v8/v8_context.h +6 -0
- data/ext/v8/v8_date.cpp +40 -0
- data/ext/v8/v8_date.h +6 -0
- data/ext/v8/v8_debug.cpp +17 -0
- data/ext/v8/v8_debug.h +6 -0
- data/ext/v8/v8_exception.cpp +133 -0
- data/ext/v8/v8_exception.h +11 -0
- data/ext/v8/v8_external.cpp +70 -0
- data/ext/v8/v8_external.h +8 -0
- data/ext/v8/v8_function.cpp +69 -0
- data/ext/v8/v8_function.h +11 -0
- data/ext/v8/v8_handle.cpp +186 -0
- data/ext/v8/v8_handle.h +48 -0
- data/ext/v8/v8_locker.cpp +139 -0
- data/ext/v8/v8_locker.h +6 -0
- data/ext/v8/v8_message.cpp +67 -0
- data/ext/v8/v8_message.h +10 -0
- data/ext/v8/v8_object.cpp +122 -0
- data/ext/v8/v8_object.h +10 -0
- data/ext/v8/v8_script.cpp +36 -0
- data/ext/v8/v8_script.h +8 -0
- data/ext/v8/v8_string.cpp +52 -0
- data/ext/v8/v8_string.h +9 -0
- data/ext/v8/v8_template.cpp +344 -0
- data/ext/v8/v8_template.h +8 -0
- data/ext/v8/v8_try_catch.cpp +70 -0
- data/ext/v8/v8_try_catch.h +5 -0
- data/ext/v8/v8_v8.cpp +34 -0
- data/ext/v8/v8_v8.h +6 -0
- data/ext/v8/v8_value.cpp +175 -0
- data/ext/v8/v8_value.h +10 -0
- data/ext/v8/v8_weakref.cpp +61 -0
- data/ext/v8/v8_weakref.h +29 -0
- data/lib/v8.rb +23 -0
- data/lib/v8/access.rb +92 -0
- data/lib/v8/array.rb +17 -0
- data/lib/v8/c/locker.rb +18 -0
- data/lib/v8/cli.rb +133 -0
- data/lib/v8/context.rb +111 -0
- data/lib/v8/error.rb +130 -0
- data/lib/v8/function.rb +44 -0
- data/lib/v8/object.rb +69 -0
- data/lib/v8/portal.rb +86 -0
- data/lib/v8/portal/caller.rb +37 -0
- data/lib/v8/portal/constructor.rb +98 -0
- data/lib/v8/portal/function.rb +63 -0
- data/lib/v8/portal/interceptors.rb +152 -0
- data/lib/v8/portal/proxies.rb +151 -0
- data/lib/v8/portal/templates.rb +73 -0
- data/lib/v8/stack.rb +66 -0
- data/lib/v8/tap.rb +9 -0
- data/lib/v8/version.rb +3 -0
- data/spec/ext/array_spec.rb +15 -0
- data/spec/ext/cxt_spec.rb +57 -0
- data/spec/ext/ext_spec_helper.rb +27 -0
- data/spec/ext/func_spec.rb +64 -0
- data/spec/ext/object_spec.rb +10 -0
- data/spec/ext/string_spec.rb +11 -0
- data/spec/ext/try_catch_spec.rb +60 -0
- data/spec/redjs_spec.rb +9 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/v8/error_spec.rb +131 -0
- data/spec/v8/portal/proxies_spec.rb +106 -0
- data/specmem/handle_memspec.rb +41 -0
- data/specmem/object_memspec.rb +14 -0
- data/specmem/proxies_memspec.rb +49 -0
- data/specmem/spec_helper.rb +24 -0
- data/specthread/spec_helper.rb +2 -0
- data/specthread/threading_spec.rb +13 -0
- data/thefrontside.png +0 -0
- data/therubyracer.gemspec +27 -0
- metadata +183 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper.rb"
|
2
|
+
|
3
|
+
include V8
|
4
|
+
|
5
|
+
describe C::TryCatch do
|
6
|
+
|
7
|
+
before {@lock = C::Locker.new;@cxt = C::Context::New();}
|
8
|
+
after {@cxt.Dispose(); @lock.delete}
|
9
|
+
|
10
|
+
it "does not allow instance creation by default" do
|
11
|
+
lambda {
|
12
|
+
C::TryCatch.new
|
13
|
+
}.should raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
it "will do nothing if not passed a block" do
|
17
|
+
C::TryCatch.try.should == nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it "executes a block in the context of a C++ stack frame" do
|
21
|
+
C::TryCatch.try do |catch|
|
22
|
+
catch.HasCaught().should be(false)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises an erro if you try to access it outside of its scope" do
|
27
|
+
tc = C::TryCatch.try do |catch|
|
28
|
+
catch.tap {}
|
29
|
+
end
|
30
|
+
lambda {
|
31
|
+
tc.HasCaught()
|
32
|
+
}.should raise_error(ScriptError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "doesn't segfault when an error is raised in a javascript function on a native prototype" do
|
36
|
+
constructor = Class.new
|
37
|
+
constructor.class_eval do
|
38
|
+
def detonate(*a)
|
39
|
+
raise "BOOM!"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
V8::Context.new do |cxt|
|
43
|
+
cxt['Boom'] = constructor
|
44
|
+
cxt['puts'] = method(:puts)
|
45
|
+
danger = <<-JS
|
46
|
+
Boom.prototype.boom = function() {
|
47
|
+
this.detonate()
|
48
|
+
}
|
49
|
+
var go = new(Boom)()
|
50
|
+
try {
|
51
|
+
go.boom()
|
52
|
+
} catch (e) {
|
53
|
+
}
|
54
|
+
go.boom()
|
55
|
+
JS
|
56
|
+
expect {cxt.eval(danger, 'danger.js')}.should raise_error(V8::JSError)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/spec/redjs_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe V8::JSError do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@cxt = V8::Context.new
|
7
|
+
@cxt['one'] = lambda do
|
8
|
+
@cxt.eval('two()', 'one.js')
|
9
|
+
end
|
10
|
+
@cxt['two'] = lambda do
|
11
|
+
@cxt.eval('three()', 'two.js')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "captures a message without over nesting when the error is an error" do
|
16
|
+
throw! do |e|
|
17
|
+
e.message.should == "BOOM!"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "captures the js message without over nesting when the error is a normal object" do
|
22
|
+
throw!('{foo: "bar"}') do |e|
|
23
|
+
e.message.should == "[object Object]"
|
24
|
+
end
|
25
|
+
throw!('{message: "bar"}') do |e|
|
26
|
+
e.message.should == "bar"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it "captures a thrown value as the message" do
|
31
|
+
throw!('"BOOM!"') do |e|
|
32
|
+
e.message.should == "BOOM!"
|
33
|
+
end
|
34
|
+
throw!('6') do |e|
|
35
|
+
e.message.should == '6'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "has a reference to the root javascript cause" do
|
40
|
+
throw!('"I am a String"') do |e|
|
41
|
+
e.should_not be_in_ruby
|
42
|
+
e.should be_in_javascript
|
43
|
+
e.value.should == "I am a String"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "has a reference to the root ruby cause if one exists" do
|
48
|
+
StandardError.new("BOOM!").tap do |bomb|
|
49
|
+
@cxt['boom'] = lambda do
|
50
|
+
raise bomb
|
51
|
+
end
|
52
|
+
lambda {
|
53
|
+
@cxt.eval('boom()', 'boom.js')
|
54
|
+
}.should(raise_error do |raised|
|
55
|
+
raised.should be_in_ruby
|
56
|
+
raised.should_not be_in_javascript
|
57
|
+
raised.value.should be(bomb)
|
58
|
+
end)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "backtrace" do
|
63
|
+
|
64
|
+
it "is mixed with ruby and javascript" do
|
65
|
+
throw! do |e|
|
66
|
+
e.backtrace.first.should == "at three.js:1:7"
|
67
|
+
e.backtrace[1].should =~ /error_spec.rb/
|
68
|
+
e.backtrace[2].should == "at two.js:1:1"
|
69
|
+
e.backtrace[3].should =~ /error_spec.rb/
|
70
|
+
e.backtrace[4].should == "at one.js:1:1"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can be set to show only ruby frames" do
|
75
|
+
throw! do |e|
|
76
|
+
e.backtrace(:ruby).each do |frame|
|
77
|
+
frame.should =~ /(\.rb|):\d+/
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "can be set to show only javascript frames" do
|
83
|
+
throw! do |e|
|
84
|
+
e.backtrace(:javascript).each do |frame|
|
85
|
+
frame.should =~ /\.js:\d:\d/
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it "includes a mystery marker when the original frame is unavailable because what got thrown wasn't an error" do
|
91
|
+
throw!("6") do |e|
|
92
|
+
e.backtrace.first.should == 'at three.js:1:1'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "has a source name and line number when there is a javascript SyntaxError" do
|
97
|
+
lambda do
|
98
|
+
@cxt.eval(<<-INVALID, 'source.js')
|
99
|
+
"this line is okay";
|
100
|
+
"this line has a syntax error because it ends with a colon":
|
101
|
+
"this line is also okay";
|
102
|
+
"how do I find out that line 2 has the syntax error?";
|
103
|
+
INVALID
|
104
|
+
end.should raise_error(V8::JSError) {|error|
|
105
|
+
error.backtrace.first.should == 'at source.js:2:60'
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
it "can start with ruby at the bottom" do
|
110
|
+
@cxt['boom'] = lambda do
|
111
|
+
raise StandardError, "Bif!"
|
112
|
+
end
|
113
|
+
lambda {
|
114
|
+
@cxt.eval('boom()', "boom.js")
|
115
|
+
}.should(raise_error {|e|
|
116
|
+
e.backtrace.first.should =~ /error_spec\.rb/
|
117
|
+
e.backtrace[1].should =~ /boom.js/
|
118
|
+
})
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def throw!(js = "new Error('BOOM!')", &block)
|
124
|
+
@cxt['three'] = lambda do
|
125
|
+
@cxt.eval("throw #{js}", 'three.js')
|
126
|
+
end
|
127
|
+
lambda do
|
128
|
+
@cxt['one'].call()
|
129
|
+
end.should(raise_error(V8::JSError, &block))
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::Portal::Proxies do
|
4
|
+
include V8::ExtSpec
|
5
|
+
|
6
|
+
|
7
|
+
context "for Ruby objects which are embedded into javascript" do
|
8
|
+
|
9
|
+
it "allows you to resolve the Ruby object's JavaScript proxy" do
|
10
|
+
js_proxy = c::Object::New()
|
11
|
+
rb_object = Object.new
|
12
|
+
subject.register_javascript_proxy js_proxy, :for => rb_object
|
13
|
+
subject.rb_object_2_js_proxy(rb_object).should be(js_proxy)
|
14
|
+
subject.js_proxy_2_rb_object(js_proxy).should be(rb_object)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "requires a Ruby object which is the actual object that is proxied" do
|
18
|
+
expect {subject.register_javascript_proxy c::Object::New()}.should raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can only register proxies which are low-level JavaScript objects" do
|
22
|
+
expect {subject.register_javascript_proxy Object.new, :for => Object.new}.should raise_error(ArgumentError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is only allowed to have a single JavaScript proxy" do
|
26
|
+
rb_object = Object.new
|
27
|
+
subject.register_javascript_proxy c::Object::New(), :for => rb_object
|
28
|
+
expect {subject.register_javascript_proxy c::Object::New(), :for => rb_object}.should raise_error(V8::Portal::Proxies::DoubleProxyError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "for a JavaScript objects which are embedded into Ruby" do
|
33
|
+
|
34
|
+
it "allows you to resolve the JavaScript object's Ruby proxy" do
|
35
|
+
rb_proxy = Object.new
|
36
|
+
js_object = c::Object::New()
|
37
|
+
subject.register_ruby_proxy rb_proxy, :for => js_object
|
38
|
+
subject.js_object_2_rb_proxy(js_object).should be(rb_proxy)
|
39
|
+
subject.rb_proxy_2_js_object(rb_proxy).should be(js_object)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "requires a JavaScript low level javascript object as the actual object that is proxied" do
|
43
|
+
expect {subject.register_javascript_proxy Object.new, :for => c::Object::New()}.should raise_error(ArgumentError)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "will not a proxy twice if the proxy creator block actually registers the proxy inside it" do
|
47
|
+
target = Object.new
|
48
|
+
proxy = c::Object::New()
|
49
|
+
expect {subject.rb2js(target) do |object|
|
50
|
+
subject.register_javascript_proxy(proxy, :for => object)
|
51
|
+
c::Object::New()
|
52
|
+
end}.should_not raise_error
|
53
|
+
subject.rb2js(target).should be(proxy)
|
54
|
+
end
|
55
|
+
|
56
|
+
context "looking up a Ruby object from a random JavaScript object" do
|
57
|
+
it "checks first if it's a native Ruby object with a javascript proxy" do
|
58
|
+
target = Object.new
|
59
|
+
proxy = c::Object::New()
|
60
|
+
subject.register_javascript_proxy proxy, :for => target
|
61
|
+
subject.js2rb(proxy).should be(target)
|
62
|
+
end
|
63
|
+
it "then sees if maybe it's a native JavaScript that has a Ruby proxy" do
|
64
|
+
target = c::Object::New()
|
65
|
+
proxy = Object.new
|
66
|
+
subject.register_ruby_proxy proxy, :for => target
|
67
|
+
subject.js2rb(target).should be(proxy)
|
68
|
+
end
|
69
|
+
it "will assume that it is a native JavaScript object that needs a Ruby proxy if no corresponding Ruby object can be found" do
|
70
|
+
js = c::Object::New()
|
71
|
+
proxy = subject.js2rb(js) do |target|
|
72
|
+
{:target => target}
|
73
|
+
end
|
74
|
+
subject.js2rb(js).should be(proxy)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "looking up a JavaScript object from a random Ruby object" do
|
79
|
+
it "checks first if it's a native JavaScript object with a Ruby proxy" do
|
80
|
+
target = c::Object::New()
|
81
|
+
proxy = Object.new
|
82
|
+
subject.register_ruby_proxy proxy, :for => target
|
83
|
+
subject.rb2js(proxy).should be(target)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "then sees if maybe it's a native Ruby object that has a JavaScript proxy" do
|
87
|
+
target = Object.new
|
88
|
+
proxy = c::Object::New()
|
89
|
+
subject.register_javascript_proxy proxy, :for => target
|
90
|
+
subject.rb2js(target).should be(proxy)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "assumes that it is a native Ruby object that needs a JavaScript proxy if no corresponding JavaScript object can be found" do
|
94
|
+
rb = Object.new
|
95
|
+
proxy = nil
|
96
|
+
js = subject.rb2js(rb) do |target|
|
97
|
+
target.should be(rb)
|
98
|
+
proxy = c::Object::New()
|
99
|
+
end
|
100
|
+
proxy.should_not be_nil
|
101
|
+
js.should be(proxy)
|
102
|
+
subject.rb2js(rb).should be(proxy)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe V8::C::Handle do
|
5
|
+
include V8::MemSpec
|
6
|
+
context "A JavaScript Object reflected into Ruby" do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@weakref_callback = WeakrefCallback.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has a strong reference from the ruby side, which is not released until the Ruby reference goes away" do
|
13
|
+
handle = c::Handle::New(object = c::Object::New())
|
14
|
+
handle.MakeWeak(nil, @weakref_callback)
|
15
|
+
ruby_gc do
|
16
|
+
v8_gc
|
17
|
+
@weakref_callback.should_not have_been_invoked
|
18
|
+
handle.should_not be_dead
|
19
|
+
end
|
20
|
+
ruby_gc do
|
21
|
+
object = nil
|
22
|
+
v8_gc
|
23
|
+
@weakref_callback.should have_been_invoked
|
24
|
+
handle.should be_dead
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
class WeakrefCallback
|
31
|
+
|
32
|
+
def call(value, parameters)
|
33
|
+
@invoked = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def has_been_invoked?
|
37
|
+
@invoked
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe V8::C::Object do
|
5
|
+
include V8::MemSpec
|
6
|
+
it "will return a new peer and not barf if the old peer has been garbage collected" do
|
7
|
+
v8_eval('var o = {foo: "bar"}')
|
8
|
+
old_id = v8_eval('o').object_id
|
9
|
+
ruby_gc do
|
10
|
+
v8_eval('o').Get(c::String::New("foo")).Utf8Value().should == "bar"
|
11
|
+
v8_eval('o').object_id.should_not be(old_id)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::Portal::Proxies do
|
4
|
+
include V8::MemSpec
|
5
|
+
|
6
|
+
context "A Ruby object embedded into JavaScript" do
|
7
|
+
it "holds a hard reference to any ruby object which is linked to a javascript proxy" do
|
8
|
+
subject.register_javascript_proxy c::Object::New(), :for => Object.new
|
9
|
+
ruby_gc do
|
10
|
+
subject.should_not be_empty
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "releases the hard reference if its corresponding javascript object has been garbage collected" do
|
15
|
+
ruby_gc do
|
16
|
+
rb_object = Object.new
|
17
|
+
js_proxy = c::Object::New()
|
18
|
+
subject.should be_empty
|
19
|
+
subject.register_javascript_proxy js_proxy, :for => rb_object
|
20
|
+
rb_object = nil
|
21
|
+
subject.should_not be_empty
|
22
|
+
v8_gc()
|
23
|
+
end
|
24
|
+
subject.should be_empty
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "A JavaScript object embedded into Ruby" do
|
29
|
+
it "holds a hard reference to any JavaScript object which is linked to a Ruby proxy" do
|
30
|
+
proxy = Object.new
|
31
|
+
subject.register_ruby_proxy proxy, :for => c::Object::New()
|
32
|
+
ruby_gc do
|
33
|
+
subject.should_not be_empty
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "clears any strong references to the JavaScript object when it's Ruby proxy is garbage collected" do
|
38
|
+
subject.register_ruby_proxy Object.new, :for => c::Object::New()
|
39
|
+
subject.should_not be_empty
|
40
|
+
ruby_gc do
|
41
|
+
v8_gc
|
42
|
+
GC.start
|
43
|
+
v8_gc
|
44
|
+
end
|
45
|
+
subject.should be_empty
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|