therubyracer-discourse 0.12.0
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 +11 -0
- data/Changelog.md +247 -0
- data/Gemfile +9 -0
- data/README.md +176 -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/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 +256 -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 +73 -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 +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 +21 -0
- metadata +163 -0
data/lib/v8/stack.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
|
2
|
+
module V8
|
3
|
+
|
4
|
+
class StackTrace
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize(native)
|
8
|
+
@context = V8::Context.current
|
9
|
+
@native = native
|
10
|
+
end
|
11
|
+
|
12
|
+
def length
|
13
|
+
@context.enter do
|
14
|
+
@native ? @native.GetFrameCount() : 0
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def each
|
19
|
+
return unless @native
|
20
|
+
@context.enter do
|
21
|
+
for i in 0..length - 1
|
22
|
+
yield V8::StackFrame.new(@native.GetFrame(i), @context)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
@native ? map(&:to_s).join("\n") : ""
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class StackFrame
|
33
|
+
|
34
|
+
def initialize(native, context)
|
35
|
+
@context = context
|
36
|
+
@native = native
|
37
|
+
end
|
38
|
+
|
39
|
+
def script_name
|
40
|
+
@context.enter do
|
41
|
+
@context.to_ruby(@native.GetScriptName())
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def function_name
|
46
|
+
@context.enter do
|
47
|
+
@context.to_ruby(@native.GetFunctionName())
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def line_number
|
52
|
+
@context.enter do
|
53
|
+
@native.GetLineNumber()
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def column
|
58
|
+
@context.enter do
|
59
|
+
@native.GetColumn()
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def eval?
|
64
|
+
@context.enter do
|
65
|
+
@native.IsEval()
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def constructor?
|
70
|
+
@context.enter do
|
71
|
+
@native.IsConstructor()
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_s
|
76
|
+
@context.enter do
|
77
|
+
"at " + if !function_name.empty?
|
78
|
+
"#{function_name} (#{script_name}:#{line_number}:#{column})"
|
79
|
+
else
|
80
|
+
"#{script_name}:#{line_number}:#{column}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/v8/version.rb
ADDED
data/lib/v8/weak.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module V8
|
2
|
+
module Weak
|
3
|
+
# weak refs are broken on MRI 1.9 and merely slow on 1.8
|
4
|
+
# so we mitigate this by using the 'ref' gem. However, this
|
5
|
+
# only mitigates the problem. Under heavy load, you will still
|
6
|
+
# get different or terminated objects being returned. bad stuff.
|
7
|
+
#
|
8
|
+
# If you are having problems with this, an upgrade to 2.0 is *highly*
|
9
|
+
# recommended.
|
10
|
+
#
|
11
|
+
# for other platforms we just use the stdlib 'weakref'
|
12
|
+
# implementation
|
13
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby' && RUBY_VERSION < '2.0.0'
|
14
|
+
require 'ref'
|
15
|
+
Ref = ::Ref::WeakReference
|
16
|
+
WeakValueMap = ::Ref::WeakValueMap
|
17
|
+
else
|
18
|
+
require 'weakref'
|
19
|
+
class Ref
|
20
|
+
def initialize(object)
|
21
|
+
@ref = ::WeakRef.new(object)
|
22
|
+
end
|
23
|
+
def object
|
24
|
+
@ref.__getobj__
|
25
|
+
rescue ::WeakRef::RefError
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class WeakValueMap
|
31
|
+
def initialize
|
32
|
+
@values = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](key)
|
36
|
+
if ref = @values[key]
|
37
|
+
ref.object
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def []=(key, value)
|
42
|
+
@values[key] = V8::Weak::Ref.new(value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module Cell
|
48
|
+
def weakcell(name, &block)
|
49
|
+
unless storage = instance_variable_get("@#{name}")
|
50
|
+
storage = instance_variable_set("@#{name}", Storage.new)
|
51
|
+
end
|
52
|
+
storage.access(&block)
|
53
|
+
end
|
54
|
+
class Storage
|
55
|
+
def access(&block)
|
56
|
+
if @ref
|
57
|
+
@ref.object || populate(block)
|
58
|
+
else
|
59
|
+
populate(block)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def populate(block)
|
66
|
+
occupant = block.call()
|
67
|
+
@ref = V8::Weak::Ref.new(occupant)
|
68
|
+
return occupant
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::C::Array do
|
4
|
+
it "can store and retrieve a value" do
|
5
|
+
o = V8::C::Object::New()
|
6
|
+
a = V8::C::Array::New()
|
7
|
+
a.Length().should eql 0
|
8
|
+
a.Set(0, o)
|
9
|
+
a.Length().should eql 1
|
10
|
+
a.Get(0).Equals(o).should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can be initialized with a length" do
|
14
|
+
a = V8::C::Array::New(5)
|
15
|
+
a.Length().should eql 5
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::C do
|
4
|
+
it "has constant methods for Undefined, Null, True and False" do
|
5
|
+
[:Undefined, :Null, :True, :False].each do |name|
|
6
|
+
constant = V8::C.send(name)
|
7
|
+
constant.should_not be_nil
|
8
|
+
V8::C.send(name).should be constant
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has a value for the Empty handle" do
|
13
|
+
V8::C::Value::Empty.should_not be_nil
|
14
|
+
V8::C::Value::Empty.should be V8::C::Value::Empty
|
15
|
+
end
|
16
|
+
|
17
|
+
it "can access the V8 version" do
|
18
|
+
V8::C::V8::GetVersion().should match /^3\.16/
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::C::Exception do
|
4
|
+
it "can be thrown from Ruby" do
|
5
|
+
t = V8::C::FunctionTemplate::New(method(:explode))
|
6
|
+
@cxt.Global().Set("explode", t.GetFunction())
|
7
|
+
script = V8::C::Script::New(<<-JS, '<eval>')
|
8
|
+
(function() {
|
9
|
+
try {
|
10
|
+
explode()
|
11
|
+
} catch (e) {
|
12
|
+
return e.message
|
13
|
+
}
|
14
|
+
})()
|
15
|
+
JS
|
16
|
+
result = script.Run()
|
17
|
+
result.should_not be_nil
|
18
|
+
result.should be_kind_of(V8::C::String)
|
19
|
+
result.Utf8Value().should eql 'did not pay syntax'
|
20
|
+
end
|
21
|
+
|
22
|
+
def explode(arguments)
|
23
|
+
error = V8::C::Exception::SyntaxError('did not pay syntax')
|
24
|
+
V8::C::ThrowException(error)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::C::Function do
|
4
|
+
it "can be called" do
|
5
|
+
fn = run '(function() {return "foo"})'
|
6
|
+
fn.Call(@cxt.Global(), []).Utf8Value().should eql "foo"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can be called with arguments and context" do
|
10
|
+
fn = run '(function(one, two, three) {this.one = one; this.two = two; this.three = three})'
|
11
|
+
one = V8::C::Object::New()
|
12
|
+
two = V8::C::Object::New()
|
13
|
+
fn.Call(@cxt.Global(), [one, two, 3])
|
14
|
+
@cxt.Global().Get("one").should eql one
|
15
|
+
@cxt.Global().Get("two").should eql two
|
16
|
+
@cxt.Global().Get("three").should eql 3
|
17
|
+
end
|
18
|
+
|
19
|
+
it "can be called as a constructor" do
|
20
|
+
fn = run '(function() {this.foo = "foo"})'
|
21
|
+
fn.NewInstance().Get(V8::C::String::New('foo')).Utf8Value().should eql "foo"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can be called as a constructor with arguments" do
|
25
|
+
fn = run '(function(foo) {this.foo = foo})'
|
26
|
+
object = fn.NewInstance([V8::C::String::New("bar")])
|
27
|
+
object.Get(V8::C::String::New('foo')).Utf8Value().should eql "bar"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "doesn't kill the world if invoking it throws a javascript exception" do
|
31
|
+
V8::C::TryCatch() do
|
32
|
+
fn = run '(function() { throw new Error("boom!")})'
|
33
|
+
fn.Call(@cxt.Global(), [])
|
34
|
+
fn.NewInstance([])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def run(source)
|
40
|
+
source = V8::C::String::New(source.to_s)
|
41
|
+
filename = V8::C::String::New("<eval>")
|
42
|
+
script = V8::C::Script::New(source, filename)
|
43
|
+
result = script.Run()
|
44
|
+
result.kind_of?(V8::C::String) ? result.Utf8Value() : result
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "setting up handles scopes" do
|
4
|
+
include ExplicitScoper
|
5
|
+
|
6
|
+
before do
|
7
|
+
def self.instance_eval(*args, &block)
|
8
|
+
V8::C::Locker() do
|
9
|
+
cxt = V8::C::Context::New()
|
10
|
+
begin
|
11
|
+
cxt.Enter()
|
12
|
+
super(*args, &block)
|
13
|
+
ensure
|
14
|
+
cxt.Exit()
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "can allocate handle scopes" do
|
21
|
+
V8::C::HandleScope() do
|
22
|
+
V8::C::Object::New()
|
23
|
+
end.class.should eql V8::C::Object
|
24
|
+
end
|
25
|
+
|
26
|
+
it "isn't the end of the world if a ruby exception is raised inside a HandleScope" do
|
27
|
+
begin
|
28
|
+
V8::C::HandleScope() do
|
29
|
+
raise "boom!"
|
30
|
+
end
|
31
|
+
rescue StandardError => e
|
32
|
+
e.message.should eql "boom!"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::C::Locker do
|
4
|
+
include ExplicitScoper
|
5
|
+
|
6
|
+
it "can lock and unlock the VM" do
|
7
|
+
V8::C::Locker::IsLocked().should be_false
|
8
|
+
V8::C::Locker() do
|
9
|
+
V8::C::Locker::IsLocked().should be_true
|
10
|
+
V8::C::Unlocker() do
|
11
|
+
V8::C::Locker::IsLocked().should be_false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
V8::C::Locker::IsLocked().should be_false
|
15
|
+
end
|
16
|
+
|
17
|
+
it "properly unlocks if an exception is thrown inside a lock block" do
|
18
|
+
begin
|
19
|
+
V8::C::Locker() do
|
20
|
+
raise "boom!"
|
21
|
+
end
|
22
|
+
rescue
|
23
|
+
V8::C::Locker::IsLocked().should be_false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "properly re-locks if an exception is thrown inside an un-lock block" do
|
28
|
+
V8::C::Locker() do
|
29
|
+
begin
|
30
|
+
V8::C::Unlocker() do
|
31
|
+
raise "boom!"
|
32
|
+
end
|
33
|
+
rescue
|
34
|
+
V8::C::Locker::IsLocked().should be_true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::C::Object do
|
4
|
+
|
5
|
+
it "can store and retrieve a value" do
|
6
|
+
o = V8::C::Object::New()
|
7
|
+
key = V8::C::String::New("foo")
|
8
|
+
value = V8::C::String::New("bar")
|
9
|
+
o.Set(key, value)
|
10
|
+
o.Get(key).Utf8Value().should eql "bar"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can retrieve all property names" do
|
14
|
+
o = V8::C::Object::New()
|
15
|
+
o.Set(V8::C::String::New("foo"), V8::C::String::New("bar"))
|
16
|
+
o.Set(V8::C::String::New("baz"), V8::C::String::New("bang"))
|
17
|
+
names = o.GetPropertyNames()
|
18
|
+
names.Length().should eql 2
|
19
|
+
names.Get(0).Utf8Value().should eql "foo"
|
20
|
+
names.Get(1).Utf8Value().should eql "baz"
|
21
|
+
end
|
22
|
+
it "can set an accessor from ruby" do
|
23
|
+
o = V8::C::Object::New()
|
24
|
+
property = V8::C::String::New("statement")
|
25
|
+
callback_data = V8::C::String::New("I am Legend")
|
26
|
+
left = V8::C::String::New("Yo! ")
|
27
|
+
getter = proc do |name, info|
|
28
|
+
info.This().StrictEquals(o).should be_true
|
29
|
+
info.Holder().StrictEquals(o).should be_true
|
30
|
+
V8::C::String::Concat(left, info.Data())
|
31
|
+
end
|
32
|
+
setter = proc do |name, value, info|
|
33
|
+
left = value
|
34
|
+
end
|
35
|
+
o.SetAccessor(property, getter, setter, callback_data)
|
36
|
+
o.Get(property).Utf8Value().should eql "Yo! I am Legend"
|
37
|
+
o.Set(property, V8::C::String::New("Bro! "))
|
38
|
+
o.Get(property).Utf8Value().should eql "Bro! I am Legend"
|
39
|
+
end
|
40
|
+
it "always returns the same ruby object for the same V8 object" do
|
41
|
+
one = V8::C::Object::New()
|
42
|
+
two = V8::C::Object::New()
|
43
|
+
one.Set("two", two)
|
44
|
+
one.Get("two").should be two
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe V8::C::Script do
|
5
|
+
it "can run a script and return a polymorphic result" do
|
6
|
+
source = V8::C::String::New("(new Array())")
|
7
|
+
filename = V8::C::String::New("<eval>")
|
8
|
+
script = V8::C::Script::New(source, filename)
|
9
|
+
result = script.Run()
|
10
|
+
result.should be_kind_of V8::C::Array
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can accept precompiled script data" do
|
14
|
+
source = "7 * 6"
|
15
|
+
name = V8::C::String::New("<spec>")
|
16
|
+
origin = V8::C::ScriptOrigin.new(name)
|
17
|
+
data = V8::C::ScriptData::PreCompile(source, source.length)
|
18
|
+
data.HasError().should be_false
|
19
|
+
script = V8::C::Script::New(V8::C::String::New(source), origin, data)
|
20
|
+
script.Run().should eql 42
|
21
|
+
end
|
22
|
+
|
23
|
+
it "can detect errors in the script data" do
|
24
|
+
source = "^ = ;"
|
25
|
+
data = V8::C::ScriptData::PreCompile(source, source.length)
|
26
|
+
data.HasError().should be_true
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe V8::C::String do
|
4
|
+
it "can hold Unicode values outside the Basic Multilingual Plane" do
|
5
|
+
string = V8::C::String::New("\u{100000}")
|
6
|
+
string.Utf8Value().should eql "\u{100000}"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can naturally translate ruby strings into v8 strings" do
|
10
|
+
V8::C::String::Concat(V8::C::String::New("Hello "), "World").Utf8Value().should eql "Hello World"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can naturally translate ruby objects into v8 strings" do
|
14
|
+
V8::C::String::Concat(V8::C::String::New("forty two is "), 42).Utf8Value().should eql "forty two is 42"
|
15
|
+
end
|
16
|
+
end
|