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.

Files changed (159) hide show
  1. data/.gitignore +21 -11
  2. data/.travis.yml +2 -1
  3. data/Changelog.md +46 -0
  4. data/Gemfile +16 -1
  5. data/README.md +31 -13
  6. data/Rakefile +42 -23
  7. data/benchmarks.rb +217 -0
  8. data/ext/v8/accessor.cc +181 -0
  9. data/ext/v8/array.cc +26 -0
  10. data/ext/v8/backref.cc +56 -0
  11. data/ext/v8/build.rb +51 -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 +14 -18
  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/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 +334 -0
  28. data/ext/v8/primitive.cc +8 -0
  29. data/ext/v8/rr.cc +83 -0
  30. data/ext/v8/rr.h +878 -36
  31. data/ext/v8/script.cc +80 -0
  32. data/ext/v8/signature.cc +18 -0
  33. data/ext/v8/stack.cc +75 -0
  34. data/ext/v8/string.cc +47 -0
  35. data/ext/v8/template.cc +175 -0
  36. data/ext/v8/trycatch.cc +86 -0
  37. data/ext/v8/v8.cc +87 -0
  38. data/ext/v8/value.cc +239 -0
  39. data/lib/v8.rb +30 -22
  40. data/lib/v8/access.rb +5 -87
  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 +19 -10
  45. data/lib/v8/context.rb +85 -78
  46. data/lib/v8/conversion.rb +35 -0
  47. data/lib/v8/conversion/array.rb +11 -0
  48. data/lib/v8/conversion/class.rb +120 -0
  49. data/lib/v8/conversion/code.rb +38 -0
  50. data/lib/v8/conversion/fundamental.rb +11 -0
  51. data/lib/v8/conversion/hash.rb +11 -0
  52. data/lib/v8/conversion/indentity.rb +31 -0
  53. data/lib/v8/conversion/method.rb +26 -0
  54. data/lib/v8/conversion/object.rb +28 -0
  55. data/lib/v8/conversion/primitive.rb +7 -0
  56. data/lib/v8/conversion/proc.rb +5 -0
  57. data/lib/v8/conversion/reference.rb +16 -0
  58. data/lib/v8/conversion/string.rb +12 -0
  59. data/lib/v8/conversion/symbol.rb +7 -0
  60. data/lib/v8/conversion/time.rb +13 -0
  61. data/lib/v8/error.rb +18 -123
  62. data/lib/v8/error/protect.rb +20 -0
  63. data/lib/v8/error/try.rb +15 -0
  64. data/lib/v8/function.rb +18 -34
  65. data/lib/v8/object.rb +48 -52
  66. data/lib/v8/util/weakcell.rb +29 -0
  67. data/lib/v8/version.rb +2 -2
  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 +40 -4
  83. data/spec/threading_spec.rb +52 -0
  84. data/spec/v8/context_spec.rb +19 -0
  85. data/spec/v8/conversion_spec.rb +9 -0
  86. data/spec/v8/error_spec.rb +15 -125
  87. data/spec/v8/function_spec.rb +9 -0
  88. data/therubyracer.gemspec +15 -24
  89. metadata +102 -135
  90. data/.gitmodules +0 -3
  91. data/.rspec +0 -1
  92. data/.yardopts +0 -1
  93. data/bin/therubyracer +0 -11
  94. data/ext/v8/rr.cpp +0 -189
  95. data/ext/v8/v8.cpp +0 -48
  96. data/ext/v8/v8_array.cpp +0 -48
  97. data/ext/v8/v8_array.h +0 -8
  98. data/ext/v8/v8_callbacks.cpp +0 -81
  99. data/ext/v8/v8_callbacks.h +0 -8
  100. data/ext/v8/v8_context.cpp +0 -92
  101. data/ext/v8/v8_context.h +0 -6
  102. data/ext/v8/v8_date.cpp +0 -34
  103. data/ext/v8/v8_date.h +0 -6
  104. data/ext/v8/v8_debug.cpp +0 -17
  105. data/ext/v8/v8_debug.h +0 -6
  106. data/ext/v8/v8_exception.cpp +0 -133
  107. data/ext/v8/v8_exception.h +0 -11
  108. data/ext/v8/v8_external.cpp +0 -70
  109. data/ext/v8/v8_external.h +0 -8
  110. data/ext/v8/v8_function.cpp +0 -69
  111. data/ext/v8/v8_function.h +0 -11
  112. data/ext/v8/v8_handle.cpp +0 -186
  113. data/ext/v8/v8_handle.h +0 -48
  114. data/ext/v8/v8_locker.cpp +0 -139
  115. data/ext/v8/v8_locker.h +0 -6
  116. data/ext/v8/v8_message.cpp +0 -67
  117. data/ext/v8/v8_message.h +0 -10
  118. data/ext/v8/v8_object.cpp +0 -122
  119. data/ext/v8/v8_object.h +0 -10
  120. data/ext/v8/v8_script.cpp +0 -36
  121. data/ext/v8/v8_script.h +0 -8
  122. data/ext/v8/v8_string.cpp +0 -52
  123. data/ext/v8/v8_string.h +0 -9
  124. data/ext/v8/v8_template.cpp +0 -344
  125. data/ext/v8/v8_template.h +0 -8
  126. data/ext/v8/v8_try_catch.cpp +0 -70
  127. data/ext/v8/v8_try_catch.h +0 -5
  128. data/ext/v8/v8_v8.cpp +0 -35
  129. data/ext/v8/v8_v8.h +0 -6
  130. data/ext/v8/v8_value.cpp +0 -175
  131. data/ext/v8/v8_value.h +0 -10
  132. data/ext/v8/v8_weakref.cpp +0 -61
  133. data/ext/v8/v8_weakref.h +0 -29
  134. data/lib/v8/c/locker.rb +0 -18
  135. data/lib/v8/cli.rb +0 -133
  136. data/lib/v8/portal.rb +0 -86
  137. data/lib/v8/portal/caller.rb +0 -37
  138. data/lib/v8/portal/constructor.rb +0 -98
  139. data/lib/v8/portal/function.rb +0 -63
  140. data/lib/v8/portal/interceptors.rb +0 -152
  141. data/lib/v8/portal/proxies.rb +0 -151
  142. data/lib/v8/portal/templates.rb +0 -73
  143. data/lib/v8/stack.rb +0 -66
  144. data/lib/v8/tap.rb +0 -9
  145. data/spec/ext/array_spec.rb +0 -15
  146. data/spec/ext/cxt_spec.rb +0 -57
  147. data/spec/ext/ext_spec_helper.rb +0 -27
  148. data/spec/ext/func_spec.rb +0 -64
  149. data/spec/ext/object_spec.rb +0 -10
  150. data/spec/ext/string_spec.rb +0 -11
  151. data/spec/ext/try_catch_spec.rb +0 -60
  152. data/spec/redjs_helper.rb +0 -3
  153. data/spec/v8/portal/proxies_spec.rb +0 -106
  154. data/specmem/handle_memspec.rb +0 -41
  155. data/specmem/object_memspec.rb +0 -14
  156. data/specmem/proxies_memspec.rb +0 -49
  157. data/specmem/spec_helper.rb +0 -24
  158. data/specthread/spec_helper.rb +0 -2
  159. 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,11 @@
1
+ class V8::Conversion
2
+ module Fundamental
3
+ def to_ruby(v8_object)
4
+ v8_object.to_ruby
5
+ end
6
+
7
+ def to_v8(ruby_object)
8
+ ruby_object.to_v8
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class V8::Conversion
2
+ module Hash
3
+ def to_v8
4
+ object = V8::Object.new
5
+ each do |key, value|
6
+ object[key] = value
7
+ end
8
+ return object.to_v8
9
+ end
10
+ end
11
+ 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,7 @@
1
+ class V8::Conversion
2
+ module Primitive
3
+ def to_v8
4
+ return self
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class V8::Conversion
2
+ module Proc
3
+ include V8::Conversion::Code
4
+ end
5
+ 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
@@ -0,0 +1,12 @@
1
+ class V8::Conversion
2
+ module String
3
+ def to_v8
4
+ V8::C::String::New(self)
5
+ end
6
+ end
7
+ module NativeString
8
+ def to_ruby
9
+ self.Utf8Value()
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ class V8::Conversion
2
+ module Symbol
3
+ def to_v8
4
+ V8::C::String::NewSymbol(to_s)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ class V8::Conversion
2
+ module Time
3
+ def to_v8
4
+ V8::C::Date::New(to_f * 1000)
5
+ end
6
+ end
7
+
8
+ module NativeDate
9
+ def to_ruby
10
+ ::Time.at(self.NumberValue() / 1000)
11
+ end
12
+ end
13
+ end
data/lib/v8/error.rb CHANGED
@@ -1,130 +1,25 @@
1
-
2
1
  module V8
3
- class JSError < StandardError
4
- attr_reader :value, :boundaries
5
-
6
- def initialize(try, to)
7
- @to = to
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
- def in_ruby?
50
- @value.kind_of?(Exception)
51
- end
52
-
53
- def in_javascript?
54
- !in_ruby?
55
- end
56
-
57
- def backtrace(*modifiers)
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
- false
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
@@ -0,0 +1,15 @@
1
+ class V8::Error
2
+ module Try
3
+ def try
4
+ context = V8::Context.current
5
+ V8::C::TryCatch() do |trycatch|
6
+ result = yield
7
+ if trycatch.HasCaught()
8
+ V8::Error(trycatch.Exception())
9
+ else
10
+ result
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
data/lib/v8/function.rb CHANGED
@@ -1,44 +1,28 @@
1
- module V8
2
- class Function < V8::Object
1
+ class V8::Function < V8::Object
2
+ include V8::Error::Try
3
3
 
4
- def methodcall(thisObject, *args)
5
- err = nil
6
- return_value = nil
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
- def new(*args)
25
- @portal.open do |to|
26
- to.rb(@native.NewInstance(to.v8(args)))
27
- end
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
- def name
31
- @portal.open do |to|
32
- to.rb(@native.GetName())
33
- end
17
+ def call(*args)
18
+ @context.enter do
19
+ methodcall @context.native.Global(), *args
34
20
  end
21
+ end
35
22
 
36
- def name=(name)
37
- name.tap do
38
- @portal.open do |to|
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