1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

properly report source:line:column on SyntaxErrors.

This commit is contained in:
Charles Lowell 2010-11-09 09:43:25 -06:00
parent 22727d1e4a
commit 59ac87f37d
3 changed files with 44 additions and 13 deletions

View file

@ -24,7 +24,8 @@ namespace {
} }
VALUE GetStackTrace(VALUE self) { VALUE GetStackTrace(VALUE self) {
return rr_v82rb(unwrap(self)->GetStackTrace()); Handle<StackTrace> trace = unwrap(self)->GetStackTrace();
return trace.IsEmpty() ? Qnil : rr_v82rb(trace);
} }
VALUE GetLineNumber(VALUE self) { VALUE GetLineNumber(VALUE self) {

View file

@ -41,7 +41,6 @@ module V8
else else
@value = ex @value = ex
message = ex.to_s message = ex.to_s
@boundaries.first.jsframes << 'at [???].js'
end end
return message return message
end end
@ -88,13 +87,31 @@ module V8
end end
def parse_js_frames(try) def parse_js_frames(try)
#I can't figure out why V8 is not capturing the stacktrace here
#in terms of StackTrace and StackFrame objects, so we have to
#parse the string.
raw = @to.rb(try.StackTrace()) raw = @to.rb(try.StackTrace())
if raw && !raw.empty? if raw && !raw.empty? && !syntax_error?(try)
raw.split("\n")[1..-1].tap do |frames| raw.split("\n")[1..-1].tap do |frames|
frames.each {|frame| frame.strip!.chomp!(",")} frames.each {|frame| frame.strip!.chomp!(",")}
end end
else else
[] msg = try.Message()
["at #{@to.rb(msg.GetScriptResourceName())}:#{msg.GetLineNumber()}:#{msg.GetStartColumn() + 1}"]
end
end
#Syntax errors are weird in that they have a non-empty stack trace
#but it does not contain any source location information, so
#in these instances, we have to pull it out of the Message object
#in the TryCatch. Is there a better way to detect a syntax error
def syntax_error?(try)
ex = try.Exception()
if ex && ex.kind_of?(V8::C::Object)
type = ex.Get("constructor")
type && type.kind_of?(V8::C::Function) && type.GetName().AsciiValue == "SyntaxError"
else
false
end end
end end

View file

@ -1,7 +1,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe V8::JSError do describe V8::JSError do
before(:each) do before(:each) do
@cxt = V8::Context.new @cxt = V8::Context.new
@cxt['one'] = lambda do @cxt['one'] = lambda do
@ -11,13 +11,13 @@ describe V8::JSError do
@cxt.eval('three()', 'two.js') @cxt.eval('three()', 'two.js')
end end
end end
it "captures a message without over nesting when the error is an error" do it "captures a message without over nesting when the error is an error" do
throw! do |e| throw! do |e|
e.message.should == "BOOM!" e.message.should == "BOOM!"
end end
end end
it "captures the js message without over nesting when the error is a normal object" do it "captures the js message without over nesting when the error is a normal object" do
throw!('{foo: "bar"}') do |e| throw!('{foo: "bar"}') do |e|
e.message.should == "[object Object]" e.message.should == "[object Object]"
@ -26,7 +26,7 @@ describe V8::JSError do
e.message.should == "bar" e.message.should == "bar"
end end
end end
it "captures a thrown value as the message" do it "captures a thrown value as the message" do
throw!('"BOOM!"') do |e| throw!('"BOOM!"') do |e|
e.message.should == "BOOM!" e.message.should == "BOOM!"
@ -35,7 +35,7 @@ describe V8::JSError do
e.message.should == '6' e.message.should == '6'
end end
end end
it "has a reference to the root javascript cause" do it "has a reference to the root javascript cause" do
throw!('"I am a String"') do |e| throw!('"I am a String"') do |e|
e.should_not be_in_ruby e.should_not be_in_ruby
@ -43,7 +43,7 @@ describe V8::JSError do
e.value.should == "I am a String" e.value.should == "I am a String"
end end
end end
it "has a reference to the root ruby cause if one exists" do it "has a reference to the root ruby cause if one exists" do
StandardError.new("BOOM!").tap do |bomb| StandardError.new("BOOM!").tap do |bomb|
@cxt['boom'] = lambda do @cxt['boom'] = lambda do
@ -58,9 +58,9 @@ describe V8::JSError do
end) end)
end end
end end
describe "backtrace" do describe "backtrace" do
it "is mixed with ruby and javascript" do it "is mixed with ruby and javascript" do
throw! do |e| throw! do |e|
e.backtrace.first.should == "at three.js:1:7" e.backtrace.first.should == "at three.js:1:7"
@ -89,10 +89,23 @@ describe V8::JSError do
it "includes a mystery marker when the original frame is unavailable because what got thrown wasn't an error" do it "includes a mystery marker when the original frame is unavailable because what got thrown wasn't an error" do
throw!("6") do |e| throw!("6") do |e|
e.backtrace.first.should == 'at [???].js' e.backtrace.first.should == 'at three.js:1:1'
end end
end end
it "has a source name and line number when there is a javascript SyntaxError" do
lambda do
@cxt.eval(<<-INVALID, 'source.js')
"this line is okay";
"this line has a syntax error because it ends with a colon":
"this line is also okay";
"how do I find out that line 2 has the syntax error?";
INVALID
end.should raise_error(V8::JSError) {|error|
error.backtrace.first.should == 'at source.js:2:60'
}
end
it "can start with ruby at the bottom" do it "can start with ruby at the bottom" do
@cxt['boom'] = lambda do @cxt['boom'] = lambda do
raise StandardError, "Bif!" raise StandardError, "Bif!"