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,38 @@
1
+ class V8::Conversion
2
+ module Code
3
+ include V8::Weak::Cell
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 Fixnum
3
+ def to_ruby
4
+ self
5
+ end
6
+
7
+ def to_v8
8
+ self.to_f.to_v8
9
+ end
10
+ end
11
+ 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 ||= V8::Weak::WeakValueMap.new
25
+ end
26
+
27
+ def rb_idmap
28
+ @ruby_idmap ||= V8::Weak::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 = V8::Weak::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 ADDED
@@ -0,0 +1,166 @@
1
+ module V8
2
+ # capture 99 stack frames on exception with normal details.
3
+ # You can adjust these values for performance or turn of stack capture entirely
4
+ V8::C::V8::SetCaptureStackTraceForUncaughtExceptions(true, 99, V8::C::StackTrace::kOverview)
5
+ class Error < StandardError
6
+ include Enumerable
7
+
8
+ # @!attribute [r] value
9
+ # @return [Object] the JavaScript value passed to the `throw` statement
10
+ attr_reader :value
11
+
12
+ # @!attribute [r] cause
13
+ # @return [Exception] the underlying error (if any) that triggered this error to be raised
14
+ attr_reader :cause
15
+
16
+ # @!attribute [r] javascript_backtrace
17
+ # @return [V8::StackTrace] the complete JavaScript stack at the point this error was thrown
18
+ attr_reader :javascript_backtrace
19
+
20
+ # keep an alias to the StandardError#backtrace method so that we can capture
21
+ # just ruby backtrace frames
22
+ alias_method :standard_error_backtrace, :backtrace
23
+
24
+ def initialize(message, value, javascript_backtrace, cause = nil)
25
+ super(message)
26
+ @value = value
27
+ @cause = cause
28
+ @javascript_backtrace = javascript_backtrace
29
+ end
30
+
31
+ def causes
32
+ [].tap do |causes|
33
+ current = self
34
+ until current.nil? do
35
+ causes.push current
36
+ current = current.respond_to?(:cause) ? current.cause : nil
37
+ end
38
+ end
39
+ end
40
+
41
+ def backtrace(*modifiers)
42
+ return unless super()
43
+ trace_framework = modifiers.include?(:framework)
44
+ trace_ruby = modifiers.length == 0 || modifiers.include?(:ruby)
45
+ trace_javascript = modifiers.length == 0 || modifiers.include?(:javascript)
46
+ bilingual_backtrace(trace_ruby, trace_javascript).tap do |trace|
47
+ trace.reject! {|frame| frame =~ %r{(lib/v8/.*\.rb|ext/v8/.*\.cc)}} unless modifiers.include?(:framework)
48
+ end
49
+ end
50
+
51
+ def root_cause
52
+ causes.last
53
+ end
54
+
55
+ def in_javascript?
56
+ causes.last.is_a? self.class
57
+ end
58
+
59
+ def in_ruby?
60
+ !in_javascript?
61
+ end
62
+
63
+ def bilingual_backtrace(trace_ruby = true, trace_javascript = true)
64
+ backtrace = causes.reduce(:backtrace => [], :ruby => -1, :javascript => -1) { |accumulator, cause|
65
+ accumulator.tap do
66
+ if trace_ruby
67
+ backtrace_selector = cause.respond_to?(:standard_error_backtrace) ? :standard_error_backtrace : :backtrace
68
+ ruby_frames = cause.send(backtrace_selector)[0..accumulator[:ruby]]
69
+ accumulator[:backtrace].unshift *ruby_frames
70
+ accumulator[:ruby] -= ruby_frames.length
71
+ end
72
+ if trace_javascript && cause.respond_to?(:javascript_backtrace)
73
+ javascript_frames = cause.javascript_backtrace.to_a[0..accumulator[:javascript]].map(&:to_s)
74
+ accumulator[:backtrace].unshift *javascript_frames
75
+ accumulator[:javascript] -= javascript_frames.length
76
+ end
77
+ end
78
+ }[:backtrace]
79
+ end
80
+
81
+ module Try
82
+ def try
83
+ V8::C::TryCatch() do |trycatch|
84
+ result = yield
85
+ if trycatch.HasCaught()
86
+ raise V8::Error(trycatch)
87
+ else
88
+ result
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ module Protect
95
+ def protect
96
+ yield
97
+ rescue Exception => e
98
+ error = V8::C::Exception::Error(e.message)
99
+ error.SetHiddenValue("rr::Cause", V8::C::External::New(e))
100
+ V8::C::ThrowException(error)
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ # Convert the result of a triggered JavaScript try/catch block into
107
+ # a V8::Error
108
+ #
109
+ # This is a bit of a yak-shave because JavaScript let's you throw all
110
+ # kinds of things. We do our best to make sure that the message property
111
+ # of the resulting V8::Error is as helpful as possible, and that it
112
+ # contains as much source location information as we can put onto it.
113
+ #
114
+ # For example:
115
+ #
116
+ # throw 4
117
+ # throw 'four'
118
+ # throw {number: 4}
119
+ #
120
+ # are all valid cases, none of which actually reference an exception object
121
+ # with a stack trace and a message. only with something like:
122
+ #
123
+ # throw new Error('fail!')
124
+ #
125
+ # do you get the a proper stacktrace and a message property. However a lot of
126
+ # times JavaScript library authors are lazy and do this:
127
+ #
128
+ # throw {message: 'foo', otherMetadata: 'bar'}
129
+ #
130
+ # It's common enough so we do the courtesy of having the resulting V8::Error
131
+ # have as its message in ruby land the 'message' property of the value object
132
+ #
133
+ # To further complicate things, SyntaxErrors do not have a JavaScript stack
134
+ # (even if they occur during js execution). This can make debugging a nightmare
135
+ # so we copy in the source location of the syntax error into the message of
136
+ # the resulting V8::Error
137
+ #
138
+ # @param [V8::C::TryCatch] native trycatch object that has been triggered
139
+ # @return [V8::Error] the error generated by this try/catch
140
+ def self.Error(trycatch)
141
+ exception = trycatch.Exception()
142
+ value = exception.to_ruby
143
+ cause = nil
144
+ javascript_backtrace = V8::StackTrace.new(trycatch.Message().GetStackTrace())
145
+ message = if !exception.kind_of?(V8::C::Value)
146
+ exception.to_s
147
+ elsif exception.IsNativeError()
148
+ if cause = exception.GetHiddenValue("rr::Cause")
149
+ cause = cause.Value()
150
+ end
151
+ if value['constructor'] == V8::Context.current['SyntaxError']
152
+ info = trycatch.Message()
153
+ resource_name = info.GetScriptResourceName().to_ruby
154
+ "#{value['message']} at #{resource_name}:#{info.GetLineNumber()}:#{info.GetStartColumn() + 1}"
155
+ else
156
+ exception.Get("message").to_ruby
157
+ end
158
+ elsif exception.IsObject()
159
+ value['message'] || value.to_s
160
+ else
161
+ value.to_s
162
+ end
163
+ V8::Error.new(message, value, javascript_backtrace, cause)
164
+ end
165
+ const_set :JSError, Error
166
+ end
@@ -0,0 +1,28 @@
1
+ class V8::Function < V8::Object
2
+ include V8::Error::Try
3
+
4
+ def initialize(native = nil)
5
+ super do
6
+ native || V8::C::FunctionTemplate::New().GetFunction()
7
+ end
8
+ end
9
+
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})}
14
+ end
15
+ end
16
+
17
+ def call(*args)
18
+ @context.enter do
19
+ methodcall @context.native.Global(), *args
20
+ end
21
+ end
22
+
23
+ def new(*args)
24
+ @context.enter do
25
+ @context.to_ruby try {native.NewInstance(args.map {|a| @context.to_v8 a})}
26
+ end
27
+ end
28
+ end
data/lib/v8/object.rb ADDED
@@ -0,0 +1,79 @@
1
+ class V8::Object
2
+ include Enumerable
3
+ attr_reader :native
4
+ alias_method :to_v8, :native
5
+
6
+ def initialize(native = nil)
7
+ @context = V8::Context.current or fail "tried to initialize a #{self.class} without being in an entered V8::Context"
8
+ @native = block_given? ? yield : native || V8::C::Object::New()
9
+ @context.link self, @native
10
+ end
11
+
12
+ def [](key)
13
+ @context.enter do
14
+ @context.to_ruby @native.Get(@context.to_v8(key))
15
+ end
16
+ end
17
+
18
+ def []=(key, value)
19
+ @context.enter do
20
+ @native.Set(@context.to_v8(key), @context.to_v8(value))
21
+ end
22
+ return value
23
+ end
24
+
25
+ def keys
26
+ @context.enter do
27
+ names = @native.GetPropertyNames()
28
+ 0.upto( names.Length() - 1).to_enum.map {|i| @context.to_ruby names.Get(i)}
29
+ end
30
+ end
31
+
32
+ def values
33
+ @context.enter do
34
+ names = @native.GetPropertyNames()
35
+ 0.upto( names.Length() - 1).to_enum.map {|i| @context.to_ruby @native.Get(names.Get(i))}
36
+ end
37
+ end
38
+
39
+ def each
40
+ @context.enter do
41
+ names = @native.GetPropertyNames()
42
+ 0.upto(names.Length() - 1) do |i|
43
+ name = names.Get(i)
44
+ yield @context.to_ruby(name), @context.to_ruby(@native.Get(name))
45
+ end
46
+ end
47
+ end
48
+
49
+ def to_s
50
+ @context.enter do
51
+ @context.to_ruby @native.ToString()
52
+ end
53
+ end
54
+
55
+ def respond_to?(method)
56
+ super or self[method] != nil
57
+ end
58
+
59
+ def method_missing(name, *args, &block)
60
+ if name.to_s =~ /(.*)=$/
61
+ if args.length > 1
62
+ self[$1] = args
63
+ return args
64
+ else
65
+ self[$1] = args.first
66
+ return args
67
+ end
68
+ end
69
+ return super(name, *args, &block) unless self.respond_to?(name)
70
+ property = self[name]
71
+ if property.kind_of?(V8::Function)
72
+ property.methodcall(self, *args)
73
+ elsif args.empty?
74
+ property
75
+ else
76
+ raise ArgumentError, "wrong number of arguments (#{args.length} for 0)" unless args.empty?
77
+ end
78
+ end
79
+ end