therubyracer 0.10.2 → 0.11.0beta1
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 +21 -11
- data/.travis.yml +2 -1
- data/Changelog.md +46 -0
- data/Gemfile +16 -1
- data/README.md +31 -13
- data/Rakefile +42 -23
- data/benchmarks.rb +217 -0
- data/ext/v8/accessor.cc +181 -0
- data/ext/v8/array.cc +26 -0
- data/ext/v8/backref.cc +56 -0
- data/ext/v8/build.rb +51 -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 +14 -18
- 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/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 +878 -36
- data/ext/v8/script.cc +80 -0
- data/ext/v8/signature.cc +18 -0
- data/ext/v8/stack.cc +75 -0
- data/ext/v8/string.cc +47 -0
- data/ext/v8/template.cc +175 -0
- data/ext/v8/trycatch.cc +86 -0
- data/ext/v8/v8.cc +87 -0
- data/ext/v8/value.cc +239 -0
- data/lib/v8.rb +30 -22
- data/lib/v8/access.rb +5 -87
- 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 +19 -10
- data/lib/v8/context.rb +85 -78
- data/lib/v8/conversion.rb +35 -0
- data/lib/v8/conversion/array.rb +11 -0
- data/lib/v8/conversion/class.rb +120 -0
- data/lib/v8/conversion/code.rb +38 -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 +18 -123
- data/lib/v8/error/protect.rb +20 -0
- data/lib/v8/error/try.rb +15 -0
- data/lib/v8/function.rb +18 -34
- data/lib/v8/object.rb +48 -52
- data/lib/v8/util/weakcell.rb +29 -0
- data/lib/v8/version.rb +2 -2
- 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 +40 -4
- data/spec/threading_spec.rb +52 -0
- data/spec/v8/context_spec.rb +19 -0
- data/spec/v8/conversion_spec.rb +9 -0
- data/spec/v8/error_spec.rb +15 -125
- data/spec/v8/function_spec.rb +9 -0
- data/therubyracer.gemspec +15 -24
- metadata +102 -135
- data/.gitmodules +0 -3
- data/.rspec +0 -1
- data/.yardopts +0 -1
- data/bin/therubyracer +0 -11
- data/ext/v8/rr.cpp +0 -189
- data/ext/v8/v8.cpp +0 -48
- data/ext/v8/v8_array.cpp +0 -48
- data/ext/v8/v8_array.h +0 -8
- data/ext/v8/v8_callbacks.cpp +0 -81
- data/ext/v8/v8_callbacks.h +0 -8
- data/ext/v8/v8_context.cpp +0 -92
- data/ext/v8/v8_context.h +0 -6
- data/ext/v8/v8_date.cpp +0 -34
- data/ext/v8/v8_date.h +0 -6
- data/ext/v8/v8_debug.cpp +0 -17
- data/ext/v8/v8_debug.h +0 -6
- data/ext/v8/v8_exception.cpp +0 -133
- data/ext/v8/v8_exception.h +0 -11
- data/ext/v8/v8_external.cpp +0 -70
- data/ext/v8/v8_external.h +0 -8
- data/ext/v8/v8_function.cpp +0 -69
- data/ext/v8/v8_function.h +0 -11
- data/ext/v8/v8_handle.cpp +0 -186
- data/ext/v8/v8_handle.h +0 -48
- data/ext/v8/v8_locker.cpp +0 -139
- data/ext/v8/v8_locker.h +0 -6
- data/ext/v8/v8_message.cpp +0 -67
- data/ext/v8/v8_message.h +0 -10
- data/ext/v8/v8_object.cpp +0 -122
- data/ext/v8/v8_object.h +0 -10
- data/ext/v8/v8_script.cpp +0 -36
- data/ext/v8/v8_script.h +0 -8
- data/ext/v8/v8_string.cpp +0 -52
- data/ext/v8/v8_string.h +0 -9
- data/ext/v8/v8_template.cpp +0 -344
- data/ext/v8/v8_template.h +0 -8
- data/ext/v8/v8_try_catch.cpp +0 -70
- data/ext/v8/v8_try_catch.h +0 -5
- data/ext/v8/v8_v8.cpp +0 -35
- data/ext/v8/v8_v8.h +0 -6
- data/ext/v8/v8_value.cpp +0 -175
- data/ext/v8/v8_value.h +0 -10
- data/ext/v8/v8_weakref.cpp +0 -61
- data/ext/v8/v8_weakref.h +0 -29
- data/lib/v8/c/locker.rb +0 -18
- data/lib/v8/cli.rb +0 -133
- data/lib/v8/portal.rb +0 -86
- data/lib/v8/portal/caller.rb +0 -37
- data/lib/v8/portal/constructor.rb +0 -98
- data/lib/v8/portal/function.rb +0 -63
- data/lib/v8/portal/interceptors.rb +0 -152
- data/lib/v8/portal/proxies.rb +0 -151
- data/lib/v8/portal/templates.rb +0 -73
- data/lib/v8/stack.rb +0 -66
- data/lib/v8/tap.rb +0 -9
- data/spec/ext/array_spec.rb +0 -15
- data/spec/ext/cxt_spec.rb +0 -57
- data/spec/ext/ext_spec_helper.rb +0 -27
- data/spec/ext/func_spec.rb +0 -64
- data/spec/ext/object_spec.rb +0 -10
- data/spec/ext/string_spec.rb +0 -11
- data/spec/ext/try_catch_spec.rb +0 -60
- data/spec/redjs_helper.rb +0 -3
- data/spec/v8/portal/proxies_spec.rb +0 -106
- data/specmem/handle_memspec.rb +0 -41
- data/specmem/object_memspec.rb +0 -14
- data/specmem/proxies_memspec.rb +0 -49
- data/specmem/spec_helper.rb +0 -24
- data/specthread/spec_helper.rb +0 -2
- data/specthread/threading_spec.rb +0 -13
@@ -0,0 +1,38 @@
|
|
1
|
+
class V8::Conversion
|
2
|
+
module Code
|
3
|
+
include V8::Util::Weakcell
|
4
|
+
|
5
|
+
def to_v8
|
6
|
+
fn = to_template.GetFunction()
|
7
|
+
V8::Context.link self, fn
|
8
|
+
return fn
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_template
|
12
|
+
weakcell(:template) {V8::C::FunctionTemplate::New(InvocationHandler.new(self))}
|
13
|
+
end
|
14
|
+
|
15
|
+
class InvocationHandler
|
16
|
+
include V8::Error::Protect
|
17
|
+
|
18
|
+
def initialize(code)
|
19
|
+
@code = code
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(arguments)
|
23
|
+
protect do
|
24
|
+
context = V8::Context.current
|
25
|
+
access = context.access
|
26
|
+
args = ::Array.new(arguments.Length())
|
27
|
+
0.upto(args.length - 1) do |i|
|
28
|
+
if i < args.length
|
29
|
+
args[i] = context.to_ruby arguments[i]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
this = context.to_ruby arguments.This()
|
33
|
+
context.to_v8 access.methodcall(@code, this, args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'ref'
|
2
|
+
|
3
|
+
class V8::Conversion
|
4
|
+
module Identity
|
5
|
+
def to_ruby(v8_object)
|
6
|
+
if v8_object.class <= V8::C::Object
|
7
|
+
v8_idmap[v8_object.GetIdentityHash()] || super(v8_object)
|
8
|
+
else
|
9
|
+
super(v8_object)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_v8(ruby_object)
|
14
|
+
return super(ruby_object) if ruby_object.is_a?(String) || ruby_object.is_a?(Primitive)
|
15
|
+
rb_idmap[ruby_object.object_id] || super(ruby_object)
|
16
|
+
end
|
17
|
+
|
18
|
+
def equate(ruby_object, v8_object)
|
19
|
+
v8_idmap[v8_object.GetIdentityHash()] = ruby_object
|
20
|
+
rb_idmap[ruby_object.object_id] = v8_object
|
21
|
+
end
|
22
|
+
|
23
|
+
def v8_idmap
|
24
|
+
@v8_idmap ||= Ref::WeakValueMap.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def rb_idmap
|
28
|
+
@ruby_idmap ||= Ref::WeakValueMap.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class V8::Conversion
|
2
|
+
module Method
|
3
|
+
include V8::Conversion::Code
|
4
|
+
|
5
|
+
def to_v8
|
6
|
+
template = @@method_cache[self] ||= to_template
|
7
|
+
template.GetFunction()
|
8
|
+
end
|
9
|
+
|
10
|
+
class MethodCache
|
11
|
+
def initialize
|
12
|
+
@map = Ref::WeakValueMap.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](method)
|
16
|
+
@map[method.to_s]
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(method, template)
|
20
|
+
@map[method.to_s] = template
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@@method_cache = MethodCache.new
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class V8::Conversion
|
2
|
+
module Object
|
3
|
+
def to_v8
|
4
|
+
Reference.construct! self
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_ruby
|
8
|
+
self
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module NativeObject
|
13
|
+
def to_ruby
|
14
|
+
wrap = if IsArray()
|
15
|
+
::V8::Array
|
16
|
+
elsif IsFunction()
|
17
|
+
::V8::Function
|
18
|
+
else
|
19
|
+
::V8::Object
|
20
|
+
end
|
21
|
+
wrap.new(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_v8
|
25
|
+
self
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class V8::Conversion
|
2
|
+
module Reference
|
3
|
+
|
4
|
+
def self.construct!(object)
|
5
|
+
context = V8::Context.current
|
6
|
+
constructor = context.to_v8(object.class)
|
7
|
+
reference = constructor.NewInstance([V8::C::External::New(object)])
|
8
|
+
return reference
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_v8
|
12
|
+
Reference.construct! self
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/lib/v8/error.rb
CHANGED
@@ -1,130 +1,25 @@
|
|
1
|
-
|
2
1
|
module V8
|
3
|
-
class
|
4
|
-
attr_reader :value
|
5
|
-
|
6
|
-
|
7
|
-
@
|
8
|
-
super(initialize_unsafe(try))
|
9
|
-
rescue Exception => e
|
10
|
-
@boundaries = [Boundary.new(:rbframes => e.backtrace)]
|
11
|
-
@value = e
|
12
|
-
super(<<-EOMSG)
|
13
|
-
You have uncovered what is probably a BUG in therubyracer exception code. An error report would be very helpful.
|
14
|
-
JSError#initialize failed!: #{e.message}"
|
15
|
-
EOMSG
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize_unsafe(try)
|
19
|
-
message = nil
|
20
|
-
ex = @to.rb(try.Exception())
|
21
|
-
@boundaries = [Boundary.new(:rbframes => caller(3), :jsframes => parse_js_frames(try))]
|
22
|
-
if V8::Object === ex
|
23
|
-
if msg = ex['message']
|
24
|
-
message = msg
|
25
|
-
else
|
26
|
-
message = ex.to_s
|
27
|
-
end
|
28
|
-
if cause = ex.instance_variable_get(:@native).GetHiddenValue("TheRubyRacer::Cause")
|
29
|
-
if !cause.IsEmpty()
|
30
|
-
prev = cause.Value()
|
31
|
-
if prev.kind_of?(JSError)
|
32
|
-
@boundaries.concat prev.boundaries
|
33
|
-
@value = prev.value
|
34
|
-
else
|
35
|
-
@value = prev
|
36
|
-
@boundaries.concat [Boundary.new(:rbframes => prev.backtrace)]
|
37
|
-
end
|
38
|
-
else
|
39
|
-
@value = ex
|
40
|
-
end
|
41
|
-
end
|
42
|
-
else
|
43
|
-
@value = ex
|
44
|
-
message = ex.to_s
|
45
|
-
end
|
46
|
-
return message
|
2
|
+
class Error < StandardError
|
3
|
+
attr_reader :value
|
4
|
+
def initialize(message, value)
|
5
|
+
super(message)
|
6
|
+
@value = value
|
47
7
|
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
trace_framework = modifiers.include?(:framework)
|
59
|
-
trace_ruby = modifiers.length == 0 || modifiers.include?(:ruby)
|
60
|
-
trace_javascript = modifiers.length == 0 || modifiers.include?(:javascript)
|
61
|
-
mixed = []
|
62
|
-
rbcontext = []
|
63
|
-
jscontext = []
|
64
|
-
@boundaries.each do |b|
|
65
|
-
rbframes = b.rbframes.dup
|
66
|
-
rbcontext.reverse_each do |frame|
|
67
|
-
if frame == rbframes.last
|
68
|
-
rbframes.pop
|
69
|
-
else
|
70
|
-
break
|
71
|
-
end
|
72
|
-
end if trace_ruby
|
73
|
-
jsframes = b.jsframes.dup
|
74
|
-
jscontext.reverse_each do |frame|
|
75
|
-
if frame == jsframes.last
|
76
|
-
jsframes.pop
|
77
|
-
else
|
78
|
-
break
|
79
|
-
end
|
80
|
-
end if trace_javascript
|
81
|
-
rbcontext = b.rbframes
|
82
|
-
jscontext = b.jsframes
|
83
|
-
rbframes.reject! {|f| f =~ /lib\/v8\/.*\.rb/} unless trace_framework
|
84
|
-
mixed.unshift(*rbframes) if trace_ruby
|
85
|
-
mixed.unshift(*jsframes) if trace_javascript
|
86
|
-
end
|
87
|
-
return mixed
|
88
|
-
end
|
89
|
-
|
90
|
-
def parse_js_frames(try)
|
91
|
-
#I can't figure out why V8 is not capturing the stacktrace here
|
92
|
-
#in terms of StackTrace and StackFrame objects, so we have to
|
93
|
-
#parse the string.
|
94
|
-
raw = @to.rb(try.StackTrace())
|
95
|
-
if raw && !raw.empty? && !syntax_error?(try)
|
96
|
-
raw.split("\n")[1..-1].tap do |frames|
|
97
|
-
frames.each {|frame| frame.strip!; frame.chomp!(",")}
|
98
|
-
end.reject(&:empty?)
|
99
|
-
else
|
100
|
-
msg = try.Message()
|
101
|
-
["at #{@to.rb(msg.GetScriptResourceName())}:#{msg.GetLineNumber()}:#{msg.GetStartColumn() + 1}"]
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
#Syntax errors are weird in that they have a non-empty stack trace
|
106
|
-
#but it does not contain any source location information, so
|
107
|
-
#in these instances, we have to pull it out of the Message object
|
108
|
-
#in the TryCatch. Is there a better way to detect a syntax error
|
109
|
-
def syntax_error?(try)
|
110
|
-
ex = @to.rb(try.Exception())
|
111
|
-
if ex && ex.kind_of?(V8::Object)
|
112
|
-
type = ex["constructor"]
|
113
|
-
type && type.kind_of?(V8::Function) && type.name == "SyntaxError"
|
8
|
+
end
|
9
|
+
const_set :JSError, Error
|
10
|
+
|
11
|
+
def self.Error(exception)
|
12
|
+
value = exception.to_ruby
|
13
|
+
if !exception.kind_of?(V8::C::Value)
|
14
|
+
raise V8::Error.new(exception.to_s, value)
|
15
|
+
elsif exception.IsNativeError()
|
16
|
+
if football = exception.GetHiddenValue("rr::Football")
|
17
|
+
raise football.Value()
|
114
18
|
else
|
115
|
-
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
class Boundary
|
120
|
-
attr_reader :rbframes, :jsframes
|
121
|
-
|
122
|
-
def initialize(frames = {})
|
123
|
-
@rbframes = frames[:rbframes] || []
|
124
|
-
@jsframes = frames[:jsframes] || []
|
19
|
+
raise V8::Error.new(exception.Get("message").to_ruby, value)
|
125
20
|
end
|
21
|
+
else
|
22
|
+
raise V8::Error.new(exception.ToString().to_ruby, value)
|
126
23
|
end
|
127
24
|
end
|
128
|
-
#deprecated -- use JSError
|
129
|
-
JavasriptError = JSError
|
130
25
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class V8::Error
|
2
|
+
module Protect
|
3
|
+
def protect
|
4
|
+
yield
|
5
|
+
rescue Football => e
|
6
|
+
e.kickoff!
|
7
|
+
rescue Exception => e
|
8
|
+
e.extend Football
|
9
|
+
e.kickoff!
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Football
|
14
|
+
def kickoff!
|
15
|
+
error = V8::C::Exception::Error(message)
|
16
|
+
error.SetHiddenValue("rr::Football", V8::C::External::New(self))
|
17
|
+
V8::C::ThrowException(error)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/v8/error/try.rb
ADDED
data/lib/v8/function.rb
CHANGED
@@ -1,44 +1,28 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
class V8::Function < V8::Object
|
2
|
+
include V8::Error::Try
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
@portal.open do |to|
|
8
|
-
C::TryCatch.try do |try|
|
9
|
-
this = to.v8(thisObject)
|
10
|
-
return_value = to.rb(@native.Call(this, to.v8(args)))
|
11
|
-
err = JSError.new(try, to) if try.HasCaught()
|
12
|
-
end
|
13
|
-
end
|
14
|
-
raise err if err
|
15
|
-
return return_value
|
16
|
-
end
|
17
|
-
|
18
|
-
def call(*args)
|
19
|
-
@portal.open do
|
20
|
-
self.methodcall(@portal.context.native.Global(), *args)
|
21
|
-
end
|
4
|
+
def initialize(native = nil)
|
5
|
+
super do
|
6
|
+
native || V8::C::FunctionTemplate::New().GetFunction()
|
22
7
|
end
|
8
|
+
end
|
23
9
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
10
|
+
def methodcall(this, *args)
|
11
|
+
@context.enter do
|
12
|
+
this ||= @context.native.Global()
|
13
|
+
@context.to_ruby try {native.Call(@context.to_v8(this), args.map {|a| @context.to_v8 a})}
|
28
14
|
end
|
15
|
+
end
|
29
16
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
17
|
+
def call(*args)
|
18
|
+
@context.enter do
|
19
|
+
methodcall @context.native.Global(), *args
|
34
20
|
end
|
21
|
+
end
|
35
22
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@native.SetName(to.v8(name))
|
40
|
-
end
|
41
|
-
end
|
23
|
+
def new(*args)
|
24
|
+
@context.enter do
|
25
|
+
@context.to_ruby try {native.NewInstance(args.map {|a| @context.to_v8 a})}
|
42
26
|
end
|
43
27
|
end
|
44
28
|
end
|