therubyracer 0.11.0beta1 → 0.11.0beta2

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.

@@ -4,6 +4,7 @@ LIBV8_COMPATIBILITY = '~> 3.11.8'
4
4
  def have_rubygem_libv8?
5
5
  require 'rubygems'
6
6
  gem 'libv8', LIBV8_COMPATIBILITY
7
+ require 'libv8'
7
8
  return true
8
9
  rescue Gem::LoadError
9
10
  return false
@@ -1,9 +1,58 @@
1
1
  require 'stringio'
2
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
3
27
  class Context
4
28
  include V8::Error::Try
5
- attr_reader :native, :conversion, :access
6
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
7
56
  def initialize(options = {})
8
57
  @conversion = Conversion.new
9
58
  @access = Access.new
@@ -19,6 +68,14 @@ module V8
19
68
  yield self if block_given?
20
69
  end
21
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
22
79
  def eval(source, filename = '<eval>', line = 1)
23
80
  if IO === source || StringIO === source
24
81
  source = source.read
@@ -29,12 +86,20 @@ module V8
29
86
  end
30
87
  end
31
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`
32
93
  def [](key)
33
94
  enter do
34
95
  to_ruby(@native.Global().Get(to_v8(key)))
35
96
  end
36
97
  end
37
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
38
103
  def []=(key, value)
39
104
  enter do
40
105
  @native.Global().Set(to_v8(key), to_v8(value))
@@ -42,6 +107,11 @@ module V8
42
107
  return value
43
108
  end
44
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.
45
115
  def dispose
46
116
  return unless @native
47
117
  @native.Dispose()
@@ -52,26 +122,68 @@ module V8
52
122
  end
53
123
  end
54
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.
55
130
  def scope
56
131
  enter { to_ruby @native.Global() }
57
132
  end
58
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
59
141
  def to_ruby(v8_object)
60
142
  @conversion.to_ruby(v8_object)
61
143
  end
62
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
63
152
  def to_v8(ruby_object)
64
153
  @conversion.to_v8(ruby_object)
65
154
  end
66
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
67
166
  def link(ruby_object, v8_object)
68
167
  @conversion.equate ruby_object, v8_object
69
168
  end
70
169
 
71
- def self.link(*args)
72
- current.link *args
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
73
177
  end
74
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`
75
187
  def enter(&block)
76
188
  if !entered?
77
189
  lock_scope_and_enter(&block)
@@ -80,14 +192,33 @@ module V8
80
192
  end
81
193
  end
82
194
 
195
+ # Indicates if this context is the currently entered context
196
+ #
197
+ # @return true if this context is currently entered
83
198
  def entered?
84
199
  Context.current == self
85
200
  end
86
201
 
202
+ # Get the currently entered context.
203
+ #
204
+ # @return [V8::Context] currently entered context, nil if none entered.
87
205
  def self.current
88
206
  Thread.current[:v8_context]
89
207
  end
90
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
+
91
222
  def self.current=(context)
92
223
  Thread.current[:v8_context] = context
93
224
  end
@@ -108,11 +239,5 @@ module V8
108
239
  ensure
109
240
  Context.current = current
110
241
  end
111
-
112
- def load(filename)
113
- File.open(filename) do |file|
114
- self.eval file, filename
115
- end
116
- end
117
242
  end
118
243
  end
@@ -22,6 +22,20 @@ class V8::Object
22
22
  return value
23
23
  end
24
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
+
25
39
  def each
26
40
  @context.enter do
27
41
  names = @native.GetPropertyNames()
@@ -1,3 +1,3 @@
1
1
  module V8
2
- VERSION = "0.11.0beta1"
2
+ VERSION = "0.11.0beta2"
3
3
  end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe V8::Object do
4
+ before do
5
+ @object = V8::Context.new.eval('({foo: "bar", baz: "bang", qux: "qux1"})')
6
+ end
7
+
8
+ it "can list all keys" do
9
+ @object.keys.sort.should eql %w(baz foo qux)
10
+ end
11
+
12
+ it "can list all values" do
13
+ @object.values.sort.should eql %w(bang bar qux1)
14
+ end
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: therubyracer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0beta1
4
+ version: 0.11.0beta2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-22 00:00:00.000000000 Z
12
+ date: 2012-07-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ref
@@ -123,6 +123,7 @@ files:
123
123
  - spec/v8/conversion_spec.rb
124
124
  - spec/v8/error_spec.rb
125
125
  - spec/v8/function_spec.rb
126
+ - spec/v8/object_spec.rb
126
127
  - thefrontside.png
127
128
  - therubyracer.gemspec
128
129
  homepage: http://github.com/cowboyd/therubyracer
@@ -140,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
141
  version: '0'
141
142
  segments:
142
143
  - 0
143
- hash: -4333973813536710638
144
+ hash: -2507841520703019375
144
145
  required_rubygems_version: !ruby/object:Gem::Requirement
145
146
  none: false
146
147
  requirements:
@@ -174,3 +175,4 @@ test_files:
174
175
  - spec/v8/conversion_spec.rb
175
176
  - spec/v8/error_spec.rb
176
177
  - spec/v8/function_spec.rb
178
+ - spec/v8/object_spec.rb