therubyracer 0.8.0.pre3 → 0.8.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.

data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ === 0.8.0 2010-12-02
2
+ * 3 major enhancements
3
+ * every V8 Context gets its own unique access strategy
4
+ * ruby methods and procs embedded in javascript always return the same function per context.
5
+ * ruby classes and subclasses are now all connected via the javascript prototype chain
6
+ * 3 minor enhancements
7
+ * better error reporting on syntax errors
8
+ * upgrade to rspec 2
9
+ * several bug fixes and stability fixes
10
+
1
11
  === 0.7.5 1010-08-03
2
12
  * 4 major enhancements
3
13
  * upgrade to V8 2.3.3
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ manifest.exclude "lib/v8/*.bundle", "lib/v8/*.so", "ext/**/test/*", "ext/**/test
7
7
  Gem::Specification.new do |gemspec|
8
8
  $gemspec = gemspec
9
9
  gemspec.name = gemspec.rubyforge_project = "therubyracer"
10
- gemspec.version = "0.8.0.pre3"
10
+ gemspec.version = "0.8.0"
11
11
  gemspec.summary = "Embed the V8 Javascript interpreter into Ruby"
12
12
  gemspec.description = "Call javascript code and manipulate javascript objects from ruby. Call ruby code and manipulate ruby objects from javascript."
13
13
  gemspec.email = "cowboyd@thefrontside.net"
data/ext/v8/rr.cpp CHANGED
@@ -8,6 +8,7 @@
8
8
  #include "v8_date.h"
9
9
  #include "v8_msg.h"
10
10
  #include "v8_external.h"
11
+ #include "v8_exception.h"
11
12
 
12
13
  using namespace v8;
13
14
 
@@ -75,6 +76,13 @@ VALUE rr_v82rb(Handle<Value> value) {
75
76
  VALUE rr_v82rb(Handle<Message> value) {
76
77
  return rr_reflect_v8_message(value);
77
78
  }
79
+ VALUE rr_v82rb(Handle<StackTrace> value) {
80
+ return rr_reflect_v8_stacktrace(value);
81
+ }
82
+ VALUE rr_v82rb(Handle<StackFrame> value) {
83
+ return rr_reflect_v8_stackframe(value);
84
+ }
85
+
78
86
  VALUE rr_v82rb(Handle<Boolean> value) {
79
87
  return rr_v82rb((Handle<Value>)value);
80
88
  }
@@ -87,6 +95,9 @@ VALUE rr_v82rb(Handle<String> value) {
87
95
  VALUE rr_v82rb(Handle<Object> value) {
88
96
  return rr_v82rb((Handle<Value>)value);
89
97
  }
98
+ VALUE rr_v82rb(Handle<Array> value) {
99
+ return rr_v82rb((Handle<Value>)value);
100
+ }
90
101
  VALUE rr_v82rb(v8::Handle<v8::Function> value) {
91
102
  return rr_v82rb((Handle<Value>)value);
92
103
  }
data/ext/v8/rr.h CHANGED
@@ -16,11 +16,15 @@ VALUE rr_v82rb(v8::Handle<v8::Boolean> value);
16
16
  VALUE rr_v82rb(v8::Handle<v8::Number> value);
17
17
  VALUE rr_v82rb(v8::Handle<v8::String> value);
18
18
  VALUE rr_v82rb(v8::Handle<v8::Object> value);
19
+ VALUE rr_v82rb(v8::Handle<v8::Array> value);
19
20
  VALUE rr_v82rb(v8::Handle<v8::Function> value);
20
21
  VALUE rr_v82rb(v8::Handle<v8::Integer> value);
21
22
  VALUE rr_v82rb(v8::Handle<v8::Uint32> value);
22
23
  VALUE rr_v82rb(v8::Handle<v8::Int32> value);
23
24
  VALUE rr_v82rb(v8::Handle<v8::Message> value);
25
+ VALUE rr_v82rb(v8::Handle<v8::StackTrace> value);
26
+ VALUE rr_v82rb(v8::Handle<v8::StackFrame> value);
27
+
24
28
  VALUE rr_v82rb(bool value);
25
29
  VALUE rr_v82rb(double value);
26
30
  VALUE rr_v82rb(int64_t value);
@@ -1,5 +1,6 @@
1
1
  #include "v8_exception.h"
2
2
  #include "rr.h"
3
+ #include "v8_ref.h"
3
4
  #include "execinfo.h"
4
5
  #include "signal.h"
5
6
 
@@ -38,19 +39,90 @@ namespace {
38
39
  HandleScope scope;
39
40
  return rr_v82rb(Exception::Error(rr_rb2v8(value)->ToString()));
40
41
  }
42
+
43
+ VALUE StackTraceClass;
44
+ VALUE StackFrameClass;
45
+ namespace Trace {
46
+
47
+ Local<StackTrace> trace(VALUE value) {
48
+ return V8_Ref_Get<StackTrace>(value);
49
+ }
50
+ VALUE GetFrame(VALUE self, VALUE index) {
51
+ HandleScope scope;
52
+ return rr_v82rb(trace(self)->GetFrame(NUM2UINT(index)));
53
+ }
54
+ VALUE GetFrameCount(VALUE self) {
55
+ HandleScope scope;
56
+ Local<StackTrace> t = trace(self);
57
+ return rr_v82rb(t->GetFrameCount());
58
+ }
59
+ VALUE AsArray(VALUE self) {
60
+ return rr_v82rb(trace(self)->AsArray());
61
+ }
62
+ VALUE CurrentStackTrace(VALUE self, VALUE frame_limit) {
63
+ return rr_v82rb(StackTrace::CurrentStackTrace(NUM2INT(frame_limit)));
64
+ }
65
+ }
66
+
67
+ namespace Frame {
68
+ Local<StackFrame> frame(VALUE value) {
69
+ return V8_Ref_Get<StackFrame>(value);
70
+ }
71
+ VALUE GetLineNumber(VALUE self) {
72
+ return rr_v82rb(frame(self)->GetLineNumber());
73
+ }
74
+ VALUE GetColumn(VALUE self) {
75
+ return rr_v82rb(frame(self)->GetColumn());
76
+ }
77
+ VALUE GetScriptName(VALUE self) {
78
+ return rr_v82rb(frame(self)->GetScriptName());
79
+ }
80
+ VALUE GetFunctionName(VALUE self) {
81
+ return rr_v82rb(frame(self)->GetFunctionName());
82
+ }
83
+ VALUE IsEval(VALUE self) {
84
+ return rr_v82rb(frame(self)->IsEval());
85
+ }
86
+ VALUE IsConstructor(VALUE self) {
87
+ return rr_v82rb(frame(self)->IsConstructor());
88
+ }
89
+ }
90
+
41
91
  }
42
92
 
43
93
  void rr_init_v8_exception() {
44
94
  VALUE V8 = rb_define_module("V8");
45
95
  VALUE V8_C = rb_define_module_under(V8, "C");
46
96
  rr_define_singleton_method(V8_C, "ThrowException", _ThrowException, 1);
97
+
47
98
  VALUE ExceptionClass = rr_define_class("Exception");
48
99
  rr_define_singleton_method(ExceptionClass, "RangeError", RangeError, 1);
49
100
  rr_define_singleton_method(ExceptionClass, "ReferenceError", ReferenceError, 1);
50
101
  rr_define_singleton_method(ExceptionClass, "SyntaxError", SyntaxError, 1);
51
102
  rr_define_singleton_method(ExceptionClass, "Error", Error, 1);
52
-
103
+
104
+ StackTraceClass = rr_define_class("StackTrace");
105
+ rr_define_singleton_method(StackTraceClass, "CurrentStackTrace", Trace::CurrentStackTrace, 0);
106
+ rr_define_method(StackTraceClass, "GetFrame", Trace::GetFrame, 1);
107
+ rr_define_method(StackTraceClass, "GetFrameCount", Trace::GetFrameCount, 0);
108
+ rr_define_method(StackTraceClass, "AsArray", Trace::AsArray, 0);
109
+
110
+ StackFrameClass = rr_define_class("StackFrame");
111
+ rr_define_method(StackFrameClass, "GetLineNumber", Frame::GetLineNumber, 0);
112
+ rr_define_method(StackFrameClass, "GetColumn", Frame::GetColumn, 0);
113
+ rr_define_method(StackFrameClass, "GetScriptName", Frame::GetScriptName, 0);
114
+ rr_define_method(StackFrameClass, "GetFunctionName", Frame::GetFunctionName, 0);
115
+ rr_define_method(StackFrameClass, "IsEval", Frame::IsEval, 0);
116
+ rr_define_method(StackFrameClass, "IsConstructor", Frame::IsConstructor, 0);
117
+
53
118
  v8::V8::SetFatalErrorHandler(fatal);
54
119
  //comment this in for debugging.
55
120
  // signal(SIGSEGV, segfault);
56
- }
121
+ }
122
+
123
+ VALUE rr_reflect_v8_stacktrace(Handle<StackTrace> value) {
124
+ return rr_v8_ref_create(StackTraceClass, value);
125
+ }
126
+ VALUE rr_reflect_v8_stackframe(Handle<StackTrace> value) {
127
+ return rr_v8_ref_create(StackFrameClass, value);
128
+ }
@@ -1,6 +1,11 @@
1
1
  #ifndef _RR_V8_EXCEPTION_
2
2
  #define _RR_V8_EXCEPTION_
3
3
 
4
+ #include "v8.h"
5
+ #include "ruby.h"
6
+
4
7
  void rr_init_v8_exception();
8
+ VALUE rr_reflect_v8_stacktrace(v8::Handle<v8::StackTrace> value);
9
+ VALUE rr_reflect_v8_stackframe(v8::Handle<v8::StackFrame> value);
5
10
 
6
11
  #endif
data/ext/v8/v8_msg.cpp CHANGED
@@ -23,6 +23,11 @@ namespace {
23
23
  return rr_v82rb(unwrap(self)->GetScriptResourceName());
24
24
  }
25
25
 
26
+ VALUE GetStackTrace(VALUE self) {
27
+ Handle<StackTrace> trace = unwrap(self)->GetStackTrace();
28
+ return trace.IsEmpty() ? Qnil : rr_v82rb(trace);
29
+ }
30
+
26
31
  VALUE GetLineNumber(VALUE self) {
27
32
  return rr_v82rb(unwrap(self)->GetLineNumber());
28
33
  }
@@ -49,6 +54,7 @@ void rr_init_msg() {
49
54
  rr_define_method(MessageClass, "Get", Get, 0);
50
55
  rr_define_method(MessageClass, "GetSourceLine", GetSourceLine, 0);
51
56
  rr_define_method(MessageClass, "GetScriptResourceName", GetScriptResourceName, 0);
57
+ rr_define_method(MessageClass, "GetStackTrace", GetStackTrace, 0);
52
58
  rr_define_method(MessageClass, "GetLineNumber", GetLineNumber, 0);
53
59
  rr_define_method(MessageClass, "GetStartPosition", GetStartPosition, 0);
54
60
  rr_define_method(MessageClass, "GetEndPosition", GetEndPosition, 0);
data/lib/v8/error.rb CHANGED
@@ -41,7 +41,6 @@ module V8
41
41
  else
42
42
  @value = ex
43
43
  message = ex.to_s
44
- @boundaries.first.jsframes << 'at [???].js'
45
44
  end
46
45
  return message
47
46
  end
@@ -88,13 +87,31 @@ module V8
88
87
  end
89
88
 
90
89
  def parse_js_frames(try)
90
+ #I can't figure out why V8 is not capturing the stacktrace here
91
+ #in terms of StackTrace and StackFrame objects, so we have to
92
+ #parse the string.
91
93
  raw = @to.rb(try.StackTrace())
92
- if raw && !raw.empty?
94
+ if raw && !raw.empty? && !syntax_error?(try)
93
95
  raw.split("\n")[1..-1].tap do |frames|
94
96
  frames.each {|frame| frame.strip!.chomp!(",")}
95
97
  end
96
98
  else
97
- []
99
+ msg = try.Message()
100
+ ["at #{@to.rb(msg.GetScriptResourceName())}:#{msg.GetLineNumber()}:#{msg.GetStartColumn() + 1}"]
101
+ end
102
+ end
103
+
104
+ #Syntax errors are weird in that they have a non-empty stack trace
105
+ #but it does not contain any source location information, so
106
+ #in these instances, we have to pull it out of the Message object
107
+ #in the TryCatch. Is there a better way to detect a syntax error
108
+ def syntax_error?(try)
109
+ ex = try.Exception()
110
+ if ex && ex.kind_of?(V8::C::Object)
111
+ type = ex.Get("constructor")
112
+ type && type.kind_of?(V8::C::Function) && type.GetName().AsciiValue == "SyntaxError"
113
+ else
114
+ false
98
115
  end
99
116
  end
100
117
 
data/lib/v8.rb CHANGED
@@ -2,7 +2,7 @@ $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  module V8
5
- VERSION = '0.8.0.pre3'
5
+ VERSION = '0.8.0'
6
6
  require 'v8/v8' #native glue
7
7
  require 'v8/portal'
8
8
  require 'v8/portal/functions'
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe V8::JSError do
4
-
4
+
5
5
  before(:each) do
6
6
  @cxt = V8::Context.new
7
7
  @cxt['one'] = lambda do
@@ -11,13 +11,13 @@ describe V8::JSError do
11
11
  @cxt.eval('three()', 'two.js')
12
12
  end
13
13
  end
14
-
14
+
15
15
  it "captures a message without over nesting when the error is an error" do
16
16
  throw! do |e|
17
17
  e.message.should == "BOOM!"
18
18
  end
19
19
  end
20
-
20
+
21
21
  it "captures the js message without over nesting when the error is a normal object" do
22
22
  throw!('{foo: "bar"}') do |e|
23
23
  e.message.should == "[object Object]"
@@ -26,7 +26,7 @@ describe V8::JSError do
26
26
  e.message.should == "bar"
27
27
  end
28
28
  end
29
-
29
+
30
30
  it "captures a thrown value as the message" do
31
31
  throw!('"BOOM!"') do |e|
32
32
  e.message.should == "BOOM!"
@@ -35,7 +35,7 @@ describe V8::JSError do
35
35
  e.message.should == '6'
36
36
  end
37
37
  end
38
-
38
+
39
39
  it "has a reference to the root javascript cause" do
40
40
  throw!('"I am a String"') do |e|
41
41
  e.should_not be_in_ruby
@@ -43,7 +43,7 @@ describe V8::JSError do
43
43
  e.value.should == "I am a String"
44
44
  end
45
45
  end
46
-
46
+
47
47
  it "has a reference to the root ruby cause if one exists" do
48
48
  StandardError.new("BOOM!").tap do |bomb|
49
49
  @cxt['boom'] = lambda do
@@ -58,9 +58,9 @@ describe V8::JSError do
58
58
  end)
59
59
  end
60
60
  end
61
-
61
+
62
62
  describe "backtrace" do
63
-
63
+
64
64
  it "is mixed with ruby and javascript" do
65
65
  throw! do |e|
66
66
  e.backtrace.first.should == "at three.js:1:7"
@@ -89,10 +89,23 @@ describe V8::JSError do
89
89
 
90
90
  it "includes a mystery marker when the original frame is unavailable because what got thrown wasn't an error" do
91
91
  throw!("6") do |e|
92
- e.backtrace.first.should == 'at [???].js'
92
+ e.backtrace.first.should == 'at three.js:1:1'
93
93
  end
94
94
  end
95
95
 
96
+ it "has a source name and line number when there is a javascript SyntaxError" do
97
+ lambda do
98
+ @cxt.eval(<<-INVALID, 'source.js')
99
+ "this line is okay";
100
+ "this line has a syntax error because it ends with a colon":
101
+ "this line is also okay";
102
+ "how do I find out that line 2 has the syntax error?";
103
+ INVALID
104
+ end.should raise_error(V8::JSError) {|error|
105
+ error.backtrace.first.should == 'at source.js:2:60'
106
+ }
107
+ end
108
+
96
109
  it "can start with ruby at the bottom" do
97
110
  @cxt['boom'] = lambda do
98
111
  raise StandardError, "Bif!"
data/therubyracer.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{therubyracer}
5
- s.version = "0.8.0.pre3"
5
+ s.version = "0.8.0"
6
6
 
7
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Charles Lowell", "Bill Robertson"]
9
- s.date = %q{2010-11-01}
9
+ s.date = %q{2010-12-03}
10
10
  s.description = %q{Call javascript code and manipulate javascript objects from ruby. Call ruby code and manipulate ruby objects from javascript.}
11
11
  s.email = %q{cowboyd@thefrontside.net}
12
12
  s.executables = ["therubyracer", "v8"]
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: therubyracer
3
3
  version: !ruby/object:Gem::Version
4
- hash: -1876988226
5
- prerelease: true
4
+ hash: 63
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 8
9
9
  - 0
10
- - pre3
11
- version: 0.8.0.pre3
10
+ version: 0.8.0
12
11
  platform: ruby
13
12
  authors:
14
13
  - Charles Lowell
@@ -17,7 +16,7 @@ autorequire:
17
16
  bindir: bin
18
17
  cert_chain: []
19
18
 
20
- date: 2010-11-01 00:00:00 -05:00
19
+ date: 2010-12-03 00:00:00 -06:00
21
20
  default_executable:
22
21
  dependencies: []
23
22
 
@@ -790,14 +789,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
790
789
  required_rubygems_version: !ruby/object:Gem::Requirement
791
790
  none: false
792
791
  requirements:
793
- - - ">"
792
+ - - ">="
794
793
  - !ruby/object:Gem::Version
795
- hash: 25
794
+ hash: 3
796
795
  segments:
797
- - 1
798
- - 3
799
- - 1
800
- version: 1.3.1
796
+ - 0
797
+ version: "0"
801
798
  requirements: []
802
799
 
803
800
  rubyforge_project: therubyracer