therubyracer-st 0.11.0beta5-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/.gitignore +23 -0
  2. data/.travis.yml +10 -0
  3. data/Changelog.md +242 -0
  4. data/Gemfile +15 -0
  5. data/README.md +185 -0
  6. data/Rakefile +58 -0
  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 +54 -0
  11. data/ext/v8/build.rb +53 -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 +23 -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/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 +883 -0
  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 +36 -0
  40. data/lib/v8/access.rb +5 -0
  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 +26 -0
  45. data/lib/v8/context.rb +243 -0
  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 +25 -0
  62. data/lib/v8/error/protect.rb +20 -0
  63. data/lib/v8/error/try.rb +15 -0
  64. data/lib/v8/function.rb +28 -0
  65. data/lib/v8/helper.rb +30 -0
  66. data/lib/v8/object.rb +79 -0
  67. data/lib/v8/util/weakcell.rb +29 -0
  68. data/lib/v8/version.rb +3 -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 +9 -0
  87. data/spec/v8/error_spec.rb +21 -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. data/vendor/v8.dll +0 -0
  93. metadata +161 -0
@@ -0,0 +1,65 @@
1
+ require 'set'
2
+ class V8::Access
3
+ module Names
4
+ def names(obj)
5
+ accessible_names(obj)
6
+ end
7
+
8
+ def get(obj, name, &dontintercept)
9
+ methods = accessible_names(obj)
10
+ if methods.include?(name)
11
+ method = obj.method(name)
12
+ method.arity == 0 ? method.call : method.unbind
13
+ elsif obj.respond_to?(:[]) && !special?(name)
14
+ obj.send(:[], name, &dontintercept)
15
+ else
16
+ yield
17
+ end
18
+ end
19
+
20
+ def set(obj, name, value, &dontintercept)
21
+ setter = name + "="
22
+ methods = accessible_names(obj, true)
23
+ if methods.include?(setter)
24
+ obj.send(setter, value)
25
+ elsif obj.respond_to?(:[]=) && !special?(name)
26
+ obj.send(:[]=, name, value, &dontintercept)
27
+ else
28
+ yield
29
+ end
30
+ end
31
+
32
+ def query(obj, name, attributes, &dontintercept)
33
+ if obj.respond_to?(name)
34
+ attributes.dont_delete
35
+ unless obj.respond_to?(name + "=")
36
+ attributes.read_only
37
+ end
38
+ else
39
+ yield
40
+ end
41
+ end
42
+
43
+ def delete(obj, name, &dontintercept)
44
+ yield
45
+ end
46
+
47
+ def accessible_names(obj, special_methods = false)
48
+ obj.public_methods(false).map {|m| m.to_s}.to_set.tap do |methods|
49
+ ancestors = obj.class.ancestors.dup
50
+ while ancestor = ancestors.shift
51
+ break if ancestor == ::Object
52
+ methods.merge(ancestor.public_instance_methods(false).map {|m| m.to_s})
53
+ end
54
+ methods.reject!(&special?) unless special_methods
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def special?(name = nil)
61
+ @special ||= lambda {|m| m == "[]" || m == "[]=" || m =~ /=$/}
62
+ name.nil? ? @special : @special[name]
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,26 @@
1
+ class V8::Array < V8::Object
2
+
3
+ def initialize(native_or_length = nil)
4
+ super do
5
+ if native_or_length.is_a?(Numeric)
6
+ V8::C::Array::New(native_or_length)
7
+ elsif native_or_length.is_a?(V8::C::Array)
8
+ native_or_length
9
+ else
10
+ V8::C::Array::New()
11
+ end
12
+ end
13
+ end
14
+
15
+ def each
16
+ @context.enter do
17
+ 0.upto(@native.Length() - 1) do |i|
18
+ yield @context.to_ruby(@native.Get(i))
19
+ end
20
+ end
21
+ end
22
+
23
+ def length
24
+ @native.Length()
25
+ end
26
+ end
@@ -0,0 +1,243 @@
1
+ require 'stringio'
2
+ module V8
3
+ # All JavaScript must be executed in a context. This context consists of a global scope containing the
4
+ # standard JavaScript objects¨and functions like Object, String, Array, as well as any objects or
5
+ # functions from Ruby which have been embedded into it from the containing enviroment. E.g.
6
+ #
7
+ # V8::Context.new do |cxt|
8
+ # cxt['num'] = 5
9
+ # cxt.eval('num + 5') #=> 10
10
+ # end
11
+ #
12
+ # The same object may appear in any number of contexts, but only one context may be executing JavaScript code
13
+ # in any given thread. If a new context is opened in a thread in which a context is already opened, the second
14
+ # context will "mask" the old context e.g.
15
+ #
16
+ # six = 6
17
+ # Context.new do |cxt|
18
+ # cxt['num'] = 5
19
+ # cxt.eval('num') # => 5
20
+ # Context.new do |cxt|
21
+ # cxt['num'] = 10
22
+ # cxt.eval('num') # => 10
23
+ # cxt.eval('++num') # => 11
24
+ # end
25
+ # cxt.eval('num') # => 5
26
+ # end
27
+ class Context
28
+ include V8::Error::Try
29
+
30
+ # @!attribute [r] conversion
31
+ # @return [V8::Conversion] conversion behavior for this context
32
+ attr_reader :conversion
33
+
34
+ # @!attrribute [r] access
35
+ # @return [V8::Access] Ruby access behavior for this context
36
+ attr_reader :access
37
+
38
+ # @!attribute [r] native
39
+ # @return [V8::C::Context] the underlying C++ object
40
+ attr_reader :native
41
+
42
+ # Creates a new context.
43
+ #
44
+ # If passed the `:with` option, that object will be used as
45
+ # the global scope of the newly creating context. e.g.
46
+ #
47
+ # scope = Object.new
48
+ # def scope.hello; "Hi"; end
49
+ # V8::Context.new(:with => scope) do |cxt|
50
+ # cxt['hello'] #=> 'Hi'
51
+ # end
52
+ #
53
+ # @param [Hash<Symbol, Object>] options initial context configuration
54
+ # * :with scope serves as the global scope of the new context
55
+ # @yield [V8::Context] the newly created context
56
+ def initialize(options = {})
57
+ @conversion = Conversion.new
58
+ @access = Access.new
59
+ if global = options[:with]
60
+ Context.new.enter do
61
+ global_template = global.class.to_template.InstanceTemplate()
62
+ @native = V8::C::Context::New(nil, global_template)
63
+ end
64
+ enter {link global, @native.Global()}
65
+ else
66
+ @native = V8::C::Context::New()
67
+ end
68
+ yield self if block_given?
69
+ end
70
+
71
+ # Compile and execute a string of JavaScript source.
72
+ #
73
+ # If `source` is an IO object it will be read fully before being evaluated
74
+ #
75
+ # @param [String,IO] source the source code to compile and execute
76
+ # @param [String] filename the name to use for this code when generating stack traces
77
+ # @param [Integer] line the line number to start with
78
+ # @return [Object] the result of the evaluation
79
+ def eval(source, filename = '<eval>', line = 1)
80
+ if IO === source || StringIO === source
81
+ source = source.read
82
+ end
83
+ enter do
84
+ script = try { V8::C::Script::New(source.to_s, filename.to_s) }
85
+ to_ruby try {script.Run()}
86
+ end
87
+ end
88
+
89
+ # Read a value from the global scope of this context
90
+ #
91
+ # @param [Object] key the name of the value to read
92
+ # @return [Object] value the value at `key`
93
+ def [](key)
94
+ enter do
95
+ to_ruby(@native.Global().Get(to_v8(key)))
96
+ end
97
+ end
98
+
99
+ # Binds `value` to the name `key` in the global scope of this context.
100
+ #
101
+ # @param [Object] key the name to bind to
102
+ # @param [Object] value the value to bind
103
+ def []=(key, value)
104
+ enter do
105
+ @native.Global().Set(to_v8(key), to_v8(value))
106
+ end
107
+ return value
108
+ end
109
+
110
+ # Destroy this context and release any internal references it may
111
+ # contain to embedded Ruby objects.
112
+ #
113
+ # A disposed context may never again be used for anything, and all
114
+ # objects created with it will become unusable.
115
+ def dispose
116
+ return unless @native
117
+ @native.Dispose()
118
+ @native = nil
119
+ V8::C::V8::ContextDisposedNotification()
120
+ def self.enter
121
+ fail "cannot enter a context which has already been disposed"
122
+ end
123
+ end
124
+
125
+ # Returns this context's global object. This will be a `V8::Object`
126
+ # if no scope was provided or just an `Object` if a Ruby object
127
+ # is serving as the global scope.
128
+ #
129
+ # @return [Object] scope the context's global scope.
130
+ def scope
131
+ enter { to_ruby @native.Global() }
132
+ end
133
+
134
+ # Converts a v8 C++ object into its ruby counterpart. This is method
135
+ # is used to translate all values passed to Ruby from JavaScript, either
136
+ # as return values or as callback parameters.
137
+ #
138
+ # @param [V8::C::Object] v8_object the native c++ object to convert.
139
+ # @return [Object] to pass to Ruby
140
+ # @see V8::Conversion for how to customize and extend this mechanism
141
+ def to_ruby(v8_object)
142
+ @conversion.to_ruby(v8_object)
143
+ end
144
+
145
+ # Converts a Ruby object into a native v8 C++ object. This method is
146
+ # used to translate all values passed to JavaScript from Ruby, either
147
+ # as return value or as callback parameters.
148
+ #
149
+ # @param [Object] ruby_object the Ruby object to convert
150
+ # @return [V8::C::Object] to pass to V8
151
+ # @see V8::Conversion for customizing and extending this mechanism
152
+ def to_v8(ruby_object)
153
+ @conversion.to_v8(ruby_object)
154
+ end
155
+
156
+ # Marks a Ruby object and a v8 C++ Object as being the same. In other
157
+ # words whenever `ruby_object` is passed to v8, the result of the
158
+ # conversion should be `v8_object`. Conversely, whenever `v8_object`
159
+ # is passed to Ruby, the result of the conversion should be `ruby_object`.
160
+ # The Ruby Racer uses this mechanism to maintain referential integrity
161
+ # between Ruby and JavaScript peers
162
+ #
163
+ # @param [Object] ruby_object the Ruby half of the object identity
164
+ # @param [V8::C::Object] v8_object the V8 half of the object identity.
165
+ # @see V8::Conversion::Identity
166
+ def link(ruby_object, v8_object)
167
+ @conversion.equate ruby_object, v8_object
168
+ end
169
+
170
+ # Links `ruby_object` and `v8_object` inside the currently entered
171
+ # context. This is an error if no context has been entered.
172
+ #
173
+ # @param [Object] ruby_object the Ruby half of the object identity
174
+ # @param [V8::C::Object] v8_object the V8 half of the object identity.
175
+ def self.link(ruby_object, v8_object)
176
+ current.link ruby_object, v8_object
177
+ end
178
+
179
+ # Run some Ruby code in the context of this context.
180
+ #
181
+ # This will acquire the V8 interpreter lock (possibly blocking
182
+ # until it is available), and prepare V8 for JavaScript execution.
183
+ #
184
+ # Only one context may be running at a time per thread.
185
+ #
186
+ # @return [Object] the result of executing `block`
187
+ def enter(&block)
188
+ if !entered?
189
+ lock_scope_and_enter(&block)
190
+ else
191
+ yield
192
+ end
193
+ end
194
+
195
+ # Indicates if this context is the currently entered context
196
+ #
197
+ # @return true if this context is currently entered
198
+ def entered?
199
+ Context.current == self
200
+ end
201
+
202
+ # Get the currently entered context.
203
+ #
204
+ # @return [V8::Context] currently entered context, nil if none entered.
205
+ def self.current
206
+ Thread.current[:v8_context]
207
+ end
208
+
209
+ # Compile and execute the contents of the file with path `filename`
210
+ # as JavaScript code.
211
+ #
212
+ # @param [String] filename path to the file to execute.
213
+ # @return [Object] the result of the evaluation.
214
+ def load(filename)
215
+ File.open(filename) do |file|
216
+ self.eval file, filename
217
+ end
218
+ end
219
+
220
+ private
221
+
222
+ def self.current=(context)
223
+ Thread.current[:v8_context] = context
224
+ end
225
+
226
+ def lock_scope_and_enter
227
+ current = Context.current
228
+ Context.current = self
229
+ V8::C::Locker() do
230
+ V8::C::HandleScope() do
231
+ begin
232
+ @native.Enter()
233
+ yield if block_given?
234
+ ensure
235
+ @native.Exit()
236
+ end
237
+ end
238
+ end
239
+ ensure
240
+ Context.current = current
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,35 @@
1
+
2
+ class V8::Conversion
3
+ include Fundamental
4
+ include Identity
5
+
6
+ def to_ruby(v8_object)
7
+ super v8_object
8
+ end
9
+
10
+ def to_v8(ruby_object)
11
+ super ruby_object
12
+ end
13
+ end
14
+
15
+ for type in [TrueClass, FalseClass, NilClass, Float, Fixnum] do
16
+ type.class_eval do
17
+ include V8::Conversion::Primitive
18
+ end
19
+ end
20
+
21
+ for type in [Class, Object, Array, Hash, String, Symbol, Time, Proc, Method] do
22
+ type.class_eval do
23
+ include V8::Conversion.const_get(name)
24
+ end
25
+ end
26
+ class UnboundMethod
27
+ include V8::Conversion::Method
28
+ end
29
+
30
+ for type in [:Object, :String, :Date] do
31
+ V8::C::const_get(type).class_eval do
32
+ include V8::Conversion::const_get("Native#{type}")
33
+ end
34
+ end
35
+
@@ -0,0 +1,11 @@
1
+ class V8::Conversion
2
+ module Array
3
+ def to_v8
4
+ array = V8::Array.new(length)
5
+ each_with_index do |item, i|
6
+ array[i] = item
7
+ end
8
+ return array.to_v8
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,120 @@
1
+ class V8::Conversion
2
+ module Class
3
+ include V8::Conversion::Code
4
+
5
+ def to_template
6
+ weakcell(:constructor) do
7
+ template = V8::C::FunctionTemplate::New(Constructor.new(self))
8
+ prototype = template.InstanceTemplate()
9
+ prototype.SetNamedPropertyHandler(Get, Set)
10
+ prototype.SetIndexedPropertyHandler(IGet, ISet)
11
+ if self != ::Object && superclass != ::Object && superclass != ::Class
12
+ template.Inherit(superclass.to_template)
13
+ end
14
+ template
15
+ end
16
+ end
17
+
18
+ class Constructor
19
+ include V8::Error::Protect
20
+
21
+ def initialize(cls)
22
+ @class = cls
23
+ end
24
+
25
+ def call(arguments)
26
+ arguments.extend Args
27
+ protect do
28
+ if arguments.linkage_call?
29
+ arguments.link
30
+ else
31
+ arguments.construct @class
32
+ end
33
+ end
34
+ return arguments.This()
35
+ end
36
+
37
+ module Args
38
+ def linkage_call?
39
+ self.Length() == 1 && self[0].IsExternal()
40
+ end
41
+
42
+ def link
43
+ external = self[0]
44
+ This().SetHiddenValue("rr::implementation", external)
45
+ context.link external.Value(), This()
46
+ end
47
+
48
+ def construct(cls)
49
+ context.link cls.new(*to_args), This()
50
+ end
51
+
52
+ def context
53
+ V8::Context.current
54
+ end
55
+
56
+ def to_args
57
+ args = ::Array.new(Length())
58
+ 0.upto(args.length - 1) do |i|
59
+ args[i] = self[i]
60
+ end
61
+ return args
62
+ end
63
+ end
64
+ end
65
+
66
+ module Accessor
67
+ include V8::Error::Protect
68
+ def intercept(info, key, &block)
69
+ context = V8::Context.current
70
+ access = context.access
71
+ object = context.to_ruby(info.This())
72
+ handles_property = true
73
+ dontintercept = proc do
74
+ handles_property = false
75
+ end
76
+ protect do
77
+ result = block.call(context, access, object, context.to_ruby(key), dontintercept)
78
+ handles_property ? context.to_v8(result) : V8::C::Value::Empty
79
+ end
80
+ end
81
+ end
82
+
83
+ class Get
84
+ extend Accessor
85
+ def self.call(property, info)
86
+ intercept(info, property) do |context, access, object, key, dontintercept|
87
+ access.get(object, key, &dontintercept)
88
+ end
89
+ end
90
+ end
91
+
92
+ class Set
93
+ extend Accessor
94
+ def self.call(property, value, info)
95
+ intercept(info, property) do |context, access, object, key, dontintercept|
96
+ access.set(object, key, context.to_ruby(value), &dontintercept)
97
+ end
98
+ end
99
+ end
100
+
101
+ class IGet
102
+ extend Accessor
103
+ def self.call(property, info)
104
+ intercept(info, property) do |context, access, object, key, dontintercept|
105
+ access.iget(object, key, &dontintercept)
106
+ end
107
+ end
108
+ end
109
+
110
+ class ISet
111
+ extend Accessor
112
+ def self.call(property, value, info)
113
+ intercept(info, property) do |context, access, object, key, dontintercept|
114
+ access.iset(object, key, context.to_ruby(value), &dontintercept)
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+ end