therubyracer 0.11.0beta8 → 0.11.0

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.

@@ -1,6 +1,6 @@
1
1
  # Changelog
2
2
 
3
- ## 0.11
3
+ ## 0.11.0 2012/12/04
4
4
 
5
5
  * upgrade V8 version to 3.11.8
6
6
  * remove dependency on libv8. enable compilation against system v8
@@ -91,7 +91,7 @@
91
91
  * upgrade to rspec 2
92
92
  * several bug fixes and stability fixes
93
93
 
94
- ## 0.7.5 - 1010/08/03
94
+ ## 0.7.5 - 2010/08/03
95
95
 
96
96
  * upgrade to V8 2.3.3
97
97
  * property interceptors from ruby via [] and []=
data/README.md CHANGED
@@ -7,13 +7,13 @@
7
7
 
8
8
  ## DESCRIPTION
9
9
 
10
- Embed the V8 Javascript interpreter into Ruby.
10
+ Embed the V8 JavaScript interpreter into Ruby.
11
11
 
12
12
 
13
13
  ## FEATURES
14
14
 
15
- * Evaluate Javascript from with in Ruby
16
- * Embed your Ruby objects into the Javascript world
15
+ * Evaluate JavaScript from within Ruby
16
+ * Embed your Ruby objects into the JavaScript world
17
17
  * Manipulate JavaScript objects and call JavaScript functions from Ruby
18
18
  * API compatible with the The Ruby Rhino (for JRuby: http://github.com/cowboyd/therubyrhino)
19
19
 
@@ -21,13 +21,13 @@ Embed the V8 Javascript interpreter into Ruby.
21
21
 
22
22
  gem install therubyracer
23
23
 
24
- then in your ruby code
24
+ then in your Ruby code
25
25
 
26
26
  require 'v8'
27
27
  # or if using bundler (as with Rails), add the following to your Gemfile
28
28
  gem "therubyracer", :require => 'v8'
29
29
 
30
- evaluate some simple javascript
30
+ evaluate some simple JavaScript
31
31
 
32
32
  cxt = V8::Context.new
33
33
  cxt.eval('7 * 6') #=> 42
@@ -37,12 +37,12 @@ embed values into the scope of your context
37
37
  cxt['foo'] = "bar"
38
38
  cxt.eval('foo') # => "bar"
39
39
 
40
- embed ruby code into your scope and call it from javascript
40
+ embed Ruby code into your scope and call it from JavaScript
41
41
 
42
42
  cxt["say"] = lambda {|this, word, times| word * times}
43
43
  cxt.eval("say('Hello', 3)") #=> HelloHelloHello
44
44
 
45
- embed a ruby object into your scope and access its properties/methods from javascript
45
+ embed a Ruby object into your scope and access its properties/methods from JavaScript
46
46
 
47
47
  class MyMath
48
48
  def plus(lhs, rhs)
@@ -53,7 +53,7 @@ embed a ruby object into your scope and access its properties/methods from javas
53
53
  cxt['math'] = MyMath.new
54
54
  cxt.eval("math.plus(20,22)") #=> 42
55
55
 
56
- make a ruby object *be* your global javascript scope.
56
+ make a Ruby object *be* your global JavaScript scope.
57
57
 
58
58
  math = MyMath.new
59
59
  V8::Context.new(:with => math) do |cxt|
@@ -64,9 +64,9 @@ you can do the same thing with Object#eval_js
64
64
 
65
65
  math.eval_js("plus(20,22)")
66
66
 
67
- ## Different ways of loading javascript source
67
+ ## Different ways of loading JavaScript source
68
68
 
69
- In addition to just evaluating strings, you can also use streams such as files.
69
+ In addition to just evaluating strings, you can also use streams, such as files.
70
70
 
71
71
  evaluate bytes read from any File/IO object:
72
72
 
@@ -81,11 +81,11 @@ or load it by filename
81
81
 
82
82
  ## Safe by default, dangerous by demand
83
83
 
84
- The Ruby Racer is designed to let you evaluate javascript as safely as possible unless you tell it to do something more
85
- dangerous. The default context is a hermetically sealed javascript environment with only the standard javascript objects
86
- and functions. Nothing from the ruby world is accessible at all.
84
+ The Ruby Racer is designed to let you evaluate JavaScript as safely as possible unless you tell it to do something more
85
+ dangerous. The default context is a hermetically sealed JavaScript environment with only the standard JavaScript objects
86
+ and functions. Nothing from the Ruby world is accessible at all.
87
87
 
88
- For ruby objects that you explicitly embed into javascript, by default only the _public_ methods _below_ `Object` are
88
+ For Ruby objects that you explicitly embed into JavaScript, by default only the _public_ methods _below_ `Object` are
89
89
  exposed by default. E.g.
90
90
 
91
91
  class A
@@ -118,19 +118,20 @@ exposed by default. E.g.
118
118
  If needed, you can override the [Ruby Access](https://github.com/cowboyd/therubyracer/blob/master/lib/v8/access.rb)
119
119
  to allow whatever behavior you'd like
120
120
 
121
- More documentation can be found on the [github wiki](https://github.com/cowboyd/therubyracer/wiki)
121
+ More documentation can be found on the [GitHub wiki](https://github.com/cowboyd/therubyracer/wiki)
122
122
 
123
123
  ## PREREQUISITES
124
124
 
125
125
  For platforms for which there is a binary version of therubyracer gem available, there are no
126
- dependencies other than ruby and rubygems.
126
+
127
+ dependencies other than Ruby and rubygems.
127
128
 
128
129
  If there is not a binary version for your system, then you will need to compile it from source.
129
130
  To do this, you must have v8 >= 3.11.8 installed somewhere on your system. There are several
130
- ways of doing this. For both you will need a C++ compiler.
131
+ ways of doing this. For both, you will need a C++ compiler.
131
132
 
132
- The first method involves using a version of the v8 source which is maintained
133
- [as a rubygem called libv8][1]. To use it, all you have to do is
133
+ The first method involves using a version of the v8 source, which is maintained
134
+ [as a RubyGem called libv8][1]. To use it, all you have to do is
134
135
  add the following to your Gemfile:
135
136
 
136
137
  gem 'libv8', '~> 3.11.8'
@@ -139,9 +140,9 @@ This will download and build v8 from source for you as part of the gem installat
139
140
  process. When therubyracer is installed, it will find this gem if it is present and
140
141
  link against the v8 binaries contained therein.
141
142
 
142
- If you cannot, or do not wish to use the libv8 rubygem, then you can either install
143
- libv8 with you operating system's packaging system or you can [build it from source][2].
144
- If you build from source, be sure to set the library=shared option. Also, if you install
143
+ If you cannot, or do not wish to use the libv8 RubyGem, you can either install libv8
144
+ with you operating system's packaging system or you can [build it from source][2]. If
145
+ you build from source, be sure to set the library=shared option. Also, if you install
145
146
  this shared library into a place that is not on your standard lib and include paths, then
146
147
  you can pass your non-standard locations to therubyracer using the
147
148
  `--with-v8-include` and `--with-v8-lib` configuration options.
@@ -182,4 +183,4 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
182
183
  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
183
184
 
184
185
  [1]: https://github.com/cowboyd/libv8
185
- [2]: http://code.google.com/p/v8/wiki/BuildingWithGYP
186
+ [2]: http://code.google.com/p/v8/wiki/BuildingWithGYP
@@ -14,32 +14,23 @@ namespace rr {
14
14
  }
15
15
 
16
16
  Backref::Backref(VALUE initial) {
17
- allocate(initial);
17
+ set(initial);
18
+ rb_gc_register_address(&storage);
18
19
  }
19
20
 
20
21
  Backref::~Backref() {
21
- deallocate();
22
+ rb_gc_unregister_address(&storage);
22
23
  }
23
24
 
24
- void Backref::allocate(VALUE data) {
25
+ VALUE Backref::set(VALUE data) {
25
26
  this->storage = rb_funcall(Storage, _new, 1, data);
26
- rb_gc_register_address(&storage);
27
- }
28
-
29
- void Backref::deallocate() {
30
- rb_gc_unregister_address(&storage);
27
+ return data;
31
28
  }
32
29
 
33
30
  VALUE Backref::get() {
34
31
  return rb_funcall(storage, object, 0);
35
32
  }
36
33
 
37
- VALUE Backref::set(VALUE data) {
38
- deallocate();
39
- allocate(data);
40
- return data;
41
- }
42
-
43
34
  v8::Handle<v8::Value> Backref::toExternal() {
44
35
  v8::Local<v8::Value> wrapper = v8::External::Wrap(this);
45
36
  v8::Persistent<v8::Value>::New(wrapper).MakeWeak(this, &release);
@@ -96,6 +96,28 @@ private:
96
96
 
97
97
  /**
98
98
  * A pointer to V8 object managed by Ruby
99
+ *
100
+ * You deal with V8 objects as either pointers or handles.
101
+ * While handles are managed by the V8 garbage collector, pointers
102
+ * must be explicitly created and destroyed by your code.
103
+ *
104
+ * The pointer class provides a handly way to wrap V8 pointers
105
+ * into Ruby objects so that they will be deleted when the
106
+ * Ruby object is garbage collected. Automatic type coercion is
107
+ * used to make wrapping and unwrapping painless.
108
+ *
109
+ * To create Ruby VALUE:
110
+ *
111
+ * Pointer<v8::ScriptOrigin> ptr(new v8::ScriptOrigin());
112
+ * VALUE value = ptr; //automatically wraps in Data_Wrap_Struct
113
+ *
114
+ * Conversely, the pointer can be unwrapped from a struct
115
+ * created in this way and the underlying methods can be
116
+ * invoked:
117
+ *
118
+ * VALUE value = ...;
119
+ * Pointer<v8::ScriptOrigin> ptr(value);
120
+ * ptr->CallMethod();
99
121
  */
100
122
 
101
123
  template <class T> class Pointer {
@@ -125,6 +147,29 @@ template <class T> VALUE Pointer<T>::Class;
125
147
 
126
148
  /**
127
149
  * A Reference to a V8 managed object
150
+ *
151
+ * Uses type coercion to quickly convert from a v8 handle
152
+ * to a ruby object and back again. Suppose we have a v8 handle
153
+ * that we want to return to Ruby. We can put it into a Ref:
154
+ *
155
+ * v8::Handle<v8::Object> object = v8::Object::New();
156
+ * VALUE val = Ref<v8::Object>(object);
157
+ *
158
+ * this will create a `v8::Persistent` handle for the object
159
+ * so that it will not be garbage collected by v8. It then
160
+ * stuffs this new persistent handle into a Data_Wrap_Struct
161
+ * which can then be passed to Ruby code. When this struct
162
+ * is garbage collected by Ruby, it enqueues the corresponding
163
+ * v8 handle to be released during v8 gc.
164
+ *
165
+ * By the same token, you can use Refs to unwrap a Data_Wrap_Struct
166
+ * which has been generated in this fashion and call through to
167
+ * the underlying v8 methods. Suppose we are passed a VALUE `val`
168
+ * wrapping a v8::Object:
169
+ *
170
+ * Ref<v8::Object> object(val);
171
+ * object->Get(v8::String::New("foo"));
172
+ *
128
173
  */
129
174
  template <class T> class Ref {
130
175
  public:
@@ -135,9 +180,15 @@ public:
135
180
  this->handle = handle;
136
181
  }
137
182
  virtual ~Ref() {}
183
+ /*
184
+ * Coerce a Ref into a Ruby VALUE
185
+ */
138
186
  virtual operator VALUE() const {
139
- return handle.IsEmpty() ? Qnil : (new Holder(handle, Class))->value;
187
+ return handle.IsEmpty() ? Qnil : Data_Wrap_Struct(Class, 0, &Holder::enqueue, new Holder(handle));
140
188
  }
189
+ /*
190
+ * Coerce a Ref into a v8::Handle.
191
+ */
141
192
  virtual operator v8::Handle<T>() const {
142
193
  if (RTEST(this->value)) {
143
194
  Holder* holder = NULL;
@@ -153,6 +204,12 @@ public:
153
204
  holder->dispose();
154
205
  }
155
206
 
207
+ /*
208
+ * Pointer de-reference operators, this lets you use a ref to
209
+ * call through to underlying v8 methods. e.g
210
+ *
211
+ * Ref<v8::Object>(value)->ToString();
212
+ */
156
213
  inline v8::Handle<T> operator->() const { return *this;}
157
214
  inline v8::Handle<T> operator*() const {return *this;}
158
215
 
@@ -173,10 +230,9 @@ public:
173
230
  class Holder {
174
231
  friend class Ref;
175
232
  public:
176
- Holder(v8::Handle<T> handle, VALUE klass) {
233
+ Holder(v8::Handle<T> handle) {
177
234
  this->disposed_p = false;
178
235
  this->handle = v8::Persistent<T>::New(handle);
179
- this->value = Data_Wrap_Struct(klass, 0, &enqueue, this);
180
236
  }
181
237
  virtual ~Holder() {
182
238
  this->dispose();
@@ -188,12 +244,10 @@ public:
188
244
  }
189
245
  }
190
246
  protected:
191
- VALUE value;
192
247
  v8::Persistent<T> handle;
193
248
  bool disposed_p;
194
249
 
195
250
  static void enqueue(Holder* holder) {
196
- holder->value = Qnil;
197
251
  GC::Finalize(holder);
198
252
  }
199
253
  };
@@ -214,8 +268,6 @@ public:
214
268
  v8::Handle<v8::Value> toExternal();
215
269
  static void release(v8::Persistent<v8::Value> handle, void* data);
216
270
  private:
217
- void allocate(VALUE data);
218
- void deallocate();
219
271
  VALUE storage;
220
272
  static VALUE Storage;
221
273
  static ID _new;
@@ -564,7 +616,6 @@ public:
564
616
  inline Object(VALUE value) : Ref<v8::Object>(value) {}
565
617
  inline Object(v8::Handle<v8::Object> object) : Ref<v8::Object>(object) {}
566
618
  virtual operator VALUE();
567
- static VALUE toVALUE(VALUE yield, VALUE wrapper);
568
619
 
569
620
  protected:
570
621
  VALUE downcast();
@@ -63,7 +63,9 @@ module V8
63
63
  end
64
64
  enter {link global, @native.Global()}
65
65
  else
66
- @native = V8::C::Context::New()
66
+ V8::C::Locker() do
67
+ @native = V8::C::Context::New()
68
+ end
67
69
  end
68
70
  yield self if block_given?
69
71
  end
@@ -13,8 +13,8 @@ module V8
13
13
  # @return [Exception] the underlying error (if any) that triggered this error to be raised
14
14
  attr_reader :cause
15
15
 
16
- # @!attribute [V8::StackTrace] javascript_backtrace
17
- # @return the complete JavaScript stack at the point this error was thrown
16
+ # @!attribute [r] javascript_backtrace
17
+ # @return [V8::StackTrace] the complete JavaScript stack at the point this error was thrown
18
18
  attr_reader :javascript_backtrace
19
19
 
20
20
  # keep an alias to the StandardError#backtrace method so that we can capture
@@ -103,6 +103,40 @@ module V8
103
103
 
104
104
  end
105
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
106
140
  def self.Error(trycatch)
107
141
  exception = trycatch.Exception()
108
142
  value = exception.to_ruby
@@ -114,8 +148,6 @@ module V8
114
148
  if cause = exception.GetHiddenValue("rr::Cause")
115
149
  cause = cause.Value()
116
150
  end
117
- # SyntaxErrors do not have a JavaScript stack (even if they occur during js execution).
118
- # To caputre where the error occured, we need to put it in the message
119
151
  if value['constructor'] == V8::Context.current['SyntaxError']
120
152
  info = trycatch.Message()
121
153
  resource_name = info.GetScriptResourceName().to_ruby
@@ -1,3 +1,3 @@
1
1
  module V8
2
- VERSION = "0.11.0beta8"
2
+ VERSION = "0.11.0"
3
3
  end
@@ -4,8 +4,8 @@ require File.expand_path('../lib/v8/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Charles Lowell"]
6
6
  gem.email = ["javascript-and-friends@googlegroups.com"]
7
- gem.summary = "Embed the V8 Javascript interpreter into Ruby"
8
- gem.description = "Call javascript code and manipulate javascript objects from ruby. Call ruby code and manipulate ruby objects from javascript."
7
+ gem.summary = "Embed the V8 JavaScript interpreter into Ruby"
8
+ gem.description = "Call JavaScript code and manipulate JavaScript objects from Ruby. Call Ruby code and manipulate Ruby objects from JavaScript."
9
9
  gem.homepage = "http://github.com/cowboyd/therubyracer"
10
10
 
11
11
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: therubyracer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0beta8
5
- prerelease: 6
4
+ version: 0.11.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Charles Lowell
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-13 00:00:00.000000000 Z
12
+ date: 2012-12-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ref
@@ -27,8 +27,8 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
- description: Call javascript code and manipulate javascript objects from ruby. Call
31
- ruby code and manipulate ruby objects from javascript.
30
+ description: Call JavaScript code and manipulate JavaScript objects from Ruby. Call
31
+ Ruby code and manipulate Ruby objects from JavaScript.
32
32
  email:
33
33
  - javascript-and-friends@googlegroups.com
34
34
  executables: []
@@ -141,19 +141,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
141
  version: '0'
142
142
  segments:
143
143
  - 0
144
- hash: -2118637317038769164
144
+ hash: -1132929021972714729
145
145
  required_rubygems_version: !ruby/object:Gem::Requirement
146
146
  none: false
147
147
  requirements:
148
- - - ! '>'
148
+ - - ! '>='
149
149
  - !ruby/object:Gem::Version
150
- version: 1.3.1
150
+ version: '0'
151
+ segments:
152
+ - 0
153
+ hash: -1132929021972714729
151
154
  requirements: []
152
155
  rubyforge_project:
153
156
  rubygems_version: 1.8.24
154
157
  signing_key:
155
158
  specification_version: 3
156
- summary: Embed the V8 Javascript interpreter into Ruby
159
+ summary: Embed the V8 JavaScript interpreter into Ruby
157
160
  test_files:
158
161
  - spec/c/array_spec.rb
159
162
  - spec/c/constants_spec.rb