Skip to content
Browse files

support catching javascript exceptions

  • Loading branch information...
1 parent e1a2153 commit a5812812bc157118bdf39cfb9498990fc4a35b83 @cowboyd committed May 25, 2012
Showing with 543 additions and 1 deletion.
  1. +3 −0 ext/v8/init.cc
  2. +51 −0 ext/v8/message.cc
  3. +123 −0 ext/v8/rr.h
  4. +75 −0 ext/v8/stack.cc
  5. +86 −0 ext/v8/trycatch.cc
  6. +9 −1 ext/v8/v8.cc
  7. +137 −0 ext/v8/value.cc
  8. +59 −0 spec/c/trycatch_spec.rb
View
3 ext/v8/init.cc
@@ -24,5 +24,8 @@ extern "C" {
External::Init();
Script::Init();
Template::Init();
+ Stack::Init();
+ Message::Init();
+ TryCatch::Init();
}
}
View
51 ext/v8/message.cc
@@ -0,0 +1,51 @@
+#include "rr.h"
+
+namespace rr {
+
+ void Message::Init() {
+ ClassBuilder("Message").
+ defineMethod("Get", &Get).
+ defineMethod("GetSourceLine", &GetSourceLine).
+ defineMethod("GetScriptResourceName", &GetScriptResourceName).
+ defineMethod("GetScriptData", &GetScriptData).
+ defineMethod("GetStackTrace", &GetStackTrace).
+ defineMethod("GetLineNumber", &GetLineNumber).
+ defineMethod("GetStartPosition", &GetStartPosition).
+ defineMethod("GetEndPosition", &GetEndPosition).
+ defineMethod("GetStartColumn", &GetEndColumn).
+ defineSingletonMethod("kNoLineNumberInfo", &kNoLineNumberInfo).
+ defineSingletonMethod("kNoColumnInfo", &kNoColumnInfo).
+ store(&Class);
+ }
+
+ VALUE Message::Get(VALUE self) {
+ return String(Message(self)->Get());
+ }
+ VALUE Message::GetSourceLine(VALUE self) {
+ return String(Message(self)->GetSourceLine());
+ }
+ VALUE Message::GetScriptResourceName(VALUE self) {
+ return Value(Message(self)->GetScriptResourceName());
+ }
+ VALUE Message::GetScriptData(VALUE self) {
+ return Value(Message(self)->GetScriptData());
+ }
+ VALUE Message::GetStackTrace(VALUE self) {
+ return Stack::Trace(Message(self)->GetStackTrace());
+ }
+ VALUE Message::GetLineNumber(VALUE self) {
+ return INT2FIX(Message(self)->GetLineNumber());
+ }
+ VALUE Message::GetStartPosition(VALUE self) {
+ return INT2FIX(Message(self)->GetStartPosition());
+ }
+ VALUE Message::GetEndPosition(VALUE self) {
+ return INT2FIX(Message(self)->GetEndPosition());
+ }
+ VALUE Message::GetStartColumn(VALUE self) {
+ return INT2FIX(Message(self)->GetStartColumn());
+ }
+ VALUE Message::GetEndColumn(VALUE self) {
+ return INT2FIX(Message(self)->GetEndColumn());
+ }
+}
View
123 ext/v8/rr.h
@@ -209,6 +209,40 @@ class Script : public Ref<v8::Script> {
class Value : public Ref<v8::Value> {
public:
static void Init();
+ static VALUE IsUndefined(VALUE self);
+ static VALUE IsNull(VALUE self);
+ static VALUE IsTrue(VALUE self);
+ static VALUE IsFalse(VALUE self);
+ static VALUE IsString(VALUE self);
+ static VALUE IsFunction(VALUE self);
+ static VALUE IsArray(VALUE self);
+ static VALUE IsObject(VALUE self);
+ static VALUE IsBoolean(VALUE self);
+ static VALUE IsNumber(VALUE self);
+ static VALUE IsExternal(VALUE self);
+ static VALUE IsInt32(VALUE self);
+ static VALUE IsUint32(VALUE self);
+ static VALUE IsDate(VALUE self);
+ static VALUE IsBooleanObject(VALUE self);
+ static VALUE IsNumberObject(VALUE self);
+ static VALUE IsStringObject(VALUE self);
+ static VALUE IsNativeError(VALUE self);
+ static VALUE IsRegExp(VALUE self);
+ // VALUE ToBoolean(VALUE self);
+ // VALUE ToNumber(VALUE self);
+ static VALUE ToString(VALUE self);
+ static VALUE ToDetailString(VALUE self);
+ static VALUE ToObject(VALUE self);
+ // static VALUE ToInteger(VALUE self);
+ // static VALUE ToUint32(VALUE self);
+ // static VALUE ToInt32(VALUE self);
+ // static VALUE ToArrayIndex(VALUE self);
+ static VALUE BooleanValue(VALUE self);
+ static VALUE NumberValue(VALUE self);
+ static VALUE IntegerValue(VALUE self);
+ static VALUE Uint32Value(VALUE self);
+ static VALUE Int32Value(VALUE self);
+
static VALUE Equals(VALUE self, VALUE other);
static VALUE StrictEquals(VALUE self, VALUE other);
inline Value(VALUE value) : Ref<v8::Value>(value) {}
@@ -480,10 +514,99 @@ class FunctionTemplate : public Ref<v8::FunctionTemplate> {
inline FunctionTemplate(v8::Handle<v8::FunctionTemplate> t) : Ref<v8::FunctionTemplate>(t) {}
};
+class Message : public Ref<v8::Message> {
+public:
+ static void Init();
+ inline Message(v8::Handle<v8::Message> message) : Ref<v8::Message>(message) {}
+ inline Message(VALUE value) : Ref<v8::Message>(value) {}
+
+ static VALUE Get(VALUE self);
+ static VALUE GetSourceLine(VALUE self);
+ static VALUE GetScriptResourceName(VALUE self);
+ static VALUE GetScriptData(VALUE self);
+ static VALUE GetStackTrace(VALUE self);
+ static VALUE GetLineNumber(VALUE self);
+ static VALUE GetStartPosition(VALUE self);
+ static VALUE GetEndPosition(VALUE self);
+ static VALUE GetStartColumn(VALUE self);
+ static VALUE GetEndColumn(VALUE self);
+ static inline VALUE kNoLineNumberInfo(VALUE self) {return INT2FIX(v8::Message::kNoLineNumberInfo);}
+ static inline VALUE kNoColumnInfo(VALUE self) {return INT2FIX(v8::Message::kNoColumnInfo);}
+};
+
+class Stack {
+public:
+ static void Init();
+
+ class Trace : public Ref<v8::StackTrace> {
+ public:
+ class StackTraceOptions : public Enum<v8::StackTrace::StackTraceOptions> {
+ public:
+ inline StackTraceOptions(VALUE value) : Enum<v8::StackTrace::StackTraceOptions>(value, v8::StackTrace::kOverview) {}
+ };
+ public:
+ inline Trace(v8::Handle<v8::StackTrace> trace) : Ref<v8::StackTrace>(trace) {}
+ inline Trace(VALUE value) : Ref<v8::StackTrace>(value) {}
+ static inline VALUE kLineNumber(VALUE self) {return INT2FIX(v8::StackTrace::kLineNumber);}
+ static inline VALUE kColumnOffset(VALUE self) {return INT2FIX(v8::StackTrace::kColumnOffset);}
+ static inline VALUE kScriptName(VALUE self) {return INT2FIX(v8::StackTrace::kScriptName);}
+ static inline VALUE kFunctionName(VALUE self) {return INT2FIX(v8::StackTrace::kFunctionName);}
+ static inline VALUE kIsEval(VALUE self) {return INT2FIX(v8::StackTrace::kIsEval);}
+ static inline VALUE kIsConstructor(VALUE self) {return INT2FIX(v8::StackTrace::kIsConstructor);}
+ static inline VALUE kScriptNameOrSourceURL(VALUE self) {return INT2FIX(v8::StackTrace::kScriptNameOrSourceURL);}
+ static inline VALUE kOverview(VALUE self) {return INT2FIX(v8::StackTrace::kOverview);}
+ static inline VALUE kDetailed(VALUE self) {return INT2FIX(v8::StackTrace::kDetailed);}
+
+ static VALUE GetFrame(VALUE self, VALUE index);
+ static VALUE GetFrameCount(VALUE self);
+ static VALUE AsArray(VALUE self);
+ static VALUE CurrentStackTrace(int argc, VALUE argv[], VALUE self);
+ };
+ class Frame : public Ref<v8::StackFrame> {
+ public:
+ inline Frame(v8::Handle<v8::StackFrame> frame) : Ref<v8::StackFrame>(frame) {}
+ inline Frame(VALUE value) : Ref<v8::StackFrame>(value) {}
+ static VALUE GetLineNumber(VALUE self);
+ static VALUE GetColumn(VALUE self);
+ static VALUE GetScriptName(VALUE self);
+ static VALUE GetScriptNameOrSourceURL(VALUE self);
+ static VALUE GetFunctionName(VALUE self);
+ static VALUE IsEval(VALUE self);
+ static VALUE IsConstructor(VALUE self);
+ };
+};
+
+class TryCatch {
+public:
+ static void Init();
+ TryCatch();
+ TryCatch(VALUE value);
+ ~TryCatch();
+ operator VALUE();
+ inline v8::TryCatch* operator->() {return this->impl;}
+ static VALUE HasCaught(VALUE self);
+ static VALUE CanContinue(VALUE self);
+ static VALUE ReThrow(VALUE self);
+ static VALUE Exception(VALUE self);
+ static VALUE StackTrace(VALUE self);
+ static VALUE Message(VALUE self);
+ static VALUE Reset(VALUE self);
+ static VALUE SetVerbose(VALUE self, VALUE value);
+ static VALUE SetCaptureMessage(VALUE self, VALUE value);
+private:
+ static VALUE doTryCatch(int argc, VALUE argv[], VALUE self);
+ static VALUE setupAndCall(int* state, VALUE code);
+ static VALUE doCall(VALUE code);
+ static VALUE Class;
+ v8::TryCatch* impl;
+ bool allocated;
+};
+
class V8 {
public:
static void Init();
static VALUE IdleNotification(VALUE self);
+ static VALUE SetCaptureStackTraceForUncaughtExceptions(int argc, VALUE argv[], VALUE self);
};
class ClassBuilder {
View
75 ext/v8/stack.cc
@@ -0,0 +1,75 @@
+#include "rr.h"
+
+namespace rr {
+ void Stack::Init() {
+ ClassBuilder("StackTrace").
+ defineSingletonMethod("kLineNumber", &Trace::kLineNumber).
+ defineSingletonMethod("kColumnOffset", &Trace::kColumnOffset).
+ defineSingletonMethod("kScriptName", &Trace::kScriptName).
+ defineSingletonMethod("kFunctionName", &Trace::kFunctionName).
+ defineSingletonMethod("kIsEval", &Trace::kIsEval).
+ defineSingletonMethod("kIsConstructor", &Trace::kIsConstructor).
+ defineSingletonMethod("kScriptNameOrSourceURL", &Trace::kScriptNameOrSourceURL).
+ defineSingletonMethod("kOverview", &Trace::kOverview).
+ defineSingletonMethod("kDetailed", &Trace::kDetailed).
+ defineSingletonMethod("CurrentStackTrace", &Trace::CurrentStackTrace).
+ defineMethod("GetFrame", &Trace::GetFrame).
+ defineMethod("GetFrameCount", &Trace::GetFrameCount).
+ defineMethod("AsArray", &Trace::AsArray).
+ store(&Trace::Class);
+ ClassBuilder("StackFrame").
+ defineMethod("GetLineNumber", &Frame::GetLineNumber).
+ defineMethod("GetColumn", &Frame::GetColumn).
+ defineMethod("GetScriptName", &Frame::GetScriptName).
+ defineMethod("GetScriptNameOrSourceURL", &Frame::GetScriptNameOrSourceURL).
+ defineMethod("IsEval", &Frame::IsEval).
+ defineMethod("IsConstructor", &Frame::IsConstructor).
+ store(&Frame::Class);
+ }
+
+ VALUE Stack::Trace::GetFrame(VALUE self, VALUE index) {
+ return Frame(Trace(self)->GetFrame(NUM2UINT(index)));
+ }
+
+ VALUE Stack::Trace::GetFrameCount(VALUE self) {
+ return INT2FIX(Trace(self)->GetFrameCount());
+ }
+
+ VALUE Stack::Trace::AsArray(VALUE self) {
+ return Array(Trace(self)->AsArray());
+ }
+
+ VALUE Stack::Trace::CurrentStackTrace(int argc, VALUE argv[], VALUE self) {
+ VALUE frame_limit; VALUE options;
+ rb_scan_args(argc, argv, "11", &frame_limit, &options);
+ return Trace(v8::StackTrace::CurrentStackTrace(NUM2INT(frame_limit), StackTraceOptions(options)));
+ }
+
+ VALUE Stack::Frame::GetLineNumber(VALUE self) {
+ return INT2FIX(Frame(self)->GetLineNumber());
+ }
+
+ VALUE Stack::Frame::GetColumn(VALUE self) {
+ return INT2FIX(Frame(self)->GetColumn());
+ }
+
+ VALUE Stack::Frame::GetScriptName(VALUE self) {
+ return String(Frame(self)->GetScriptName());
+ }
+
+ VALUE Stack::Frame::GetScriptNameOrSourceURL(VALUE self) {
+ return String(Frame(self)->GetScriptNameOrSourceURL());
+ }
+
+ VALUE Stack::Frame::GetFunctionName(VALUE self) {
+ return String(Frame(self)->GetFunctionName());
+ }
+
+ VALUE Stack::Frame::IsEval(VALUE self) {
+ return Bool(Frame(self)->IsEval());
+ }
+
+ VALUE Stack::Frame::IsConstructor(VALUE self) {
+ return Bool(Frame(self)->IsConstructor());
+ }
+}
View
86 ext/v8/trycatch.cc
@@ -0,0 +1,86 @@
+#include "rr.h"
+
+namespace rr {
+ VALUE TryCatch::Class;
+
+ void TryCatch::Init() {
+ ClassBuilder("TryCatch").
+ defineMethod("HasCaught", &HasCaught).
+ defineMethod("CanContinue", &CanContinue).
+ defineMethod("ReThrow", &ReThrow).
+ defineMethod("Exception", &Exception).
+ defineMethod("StackTrace", &StackTrace).
+ defineMethod("Message", &Message).
+ defineMethod("Reset", &Reset).
+ defineMethod("SetVerbose", &SetVerbose).
+ defineMethod("SetCaptureMessage", &SetCaptureMessage).
+ store(&Class);
+ VALUE v8 = rb_define_module("V8");
+ VALUE c = rb_define_module_under(v8, "C");
+ rb_define_singleton_method(c, "TryCatch", (VALUE (*)(...))&doTryCatch, -1);
+ }
+
+ TryCatch::TryCatch() : impl(new v8::TryCatch()), allocated(true) {}
+ TryCatch::TryCatch(VALUE value) : allocated(false) {
+ Data_Get_Struct(value, class v8::TryCatch, impl);
+ }
+ TryCatch::~TryCatch() {
+ if (this->allocated) {
+ delete this->impl;
+ }
+ }
+ TryCatch::operator VALUE() {
+ return Data_Wrap_Struct(Class, 0, 0, impl);
+ }
+
+ VALUE TryCatch::HasCaught(VALUE self) {
+ return Bool(TryCatch(self)->HasCaught());
+ }
+ VALUE TryCatch::CanContinue(VALUE self) {
+ return Bool(TryCatch(self)->CanContinue());
+ }
+ VALUE TryCatch::ReThrow(VALUE self) {
+ return Value(TryCatch(self)->ReThrow());
+ }
+ VALUE TryCatch::Exception(VALUE self) {
+ return Value(TryCatch(self)->Exception());
+ }
+ VALUE TryCatch::StackTrace(VALUE self) {
+ return Value(TryCatch(self)->StackTrace());
+ }
+ VALUE TryCatch::Message(VALUE self) {
+ return rr::Message(TryCatch(self)->Message());
+ }
+ VALUE TryCatch::Reset(VALUE self) {
+ Void(TryCatch(self)->Reset());
+ }
+ VALUE TryCatch::SetVerbose(VALUE self, VALUE value) {
+ Void(TryCatch(self)->SetVerbose(Bool(value)));
+ }
+ VALUE TryCatch::SetCaptureMessage(VALUE self, VALUE value) {
+ Void(TryCatch(self)->SetCaptureMessage(Bool(value)));
+ }
+
+ VALUE TryCatch::doTryCatch(int argc, VALUE argv[], VALUE self) {
+ if (!rb_block_given_p()) {
+ return Qnil;
+ }
+ int state = 0;
+ VALUE code;
+ rb_scan_args(argc,argv,"00&", &code);
+ VALUE result = setupAndCall(&state, code);
+ if (state != 0) {
+ rb_jump_tag(state);
+ }
+ return result;
+ }
+
+ VALUE TryCatch::setupAndCall(int* state, VALUE code) {
+ return rb_protect(&doCall, code, state);
+ }
+
+ VALUE TryCatch::doCall(VALUE code) {
+ TryCatch trycatch;
+ return rb_funcall(code, rb_intern("call"), 1, (VALUE)trycatch);
+ }
+}
View
10 ext/v8/v8.cc
@@ -4,11 +4,19 @@ namespace rr {
void V8::Init() {
ClassBuilder("V8").
- defineSingletonMethod("IdleNotification", &IdleNotification);
+ defineSingletonMethod("IdleNotification", &IdleNotification).
+ defineSingletonMethod("SetCaptureStackTraceForUncaughtExceptions", &SetCaptureStackTraceForUncaughtExceptions);
}
VALUE V8::IdleNotification(VALUE self) {
return Bool(v8::V8::IdleNotification());
}
+VALUE V8::SetCaptureStackTraceForUncaughtExceptions(int argc, VALUE argv[], VALUE self) {
+ VALUE should_capture; VALUE frame_limit; VALUE options;
+ rb_scan_args(argc, argv, "12", &should_capture, &frame_limit, &options);
+ int limit = RTEST(frame_limit) ? NUM2INT(frame_limit) : 10;
+ Void(v8::V8::SetCaptureStackTraceForUncaughtExceptions(Bool(should_capture), limit, Stack::Trace::StackTraceOptions(options)));
+}
+
}
View
137 ext/v8/value.cc
@@ -4,11 +4,148 @@ namespace rr {
void Value::Init() {
ClassBuilder("Value").
+ defineMethod("IsUndefined", &IsUndefined).
+ defineMethod("IsNull", &IsNull).
+ defineMethod("IsTrue", &IsTrue).
+ defineMethod("IsFalse", &IsFalse).
+ defineMethod("IsString", &IsString).
+ defineMethod("IsFunction", &IsFunction).
+ defineMethod("IsArray", &IsArray).
+ defineMethod("IsObject", &IsObject).
+ defineMethod("IsBoolean", &IsBoolean).
+ defineMethod("IsNumber", &IsNumber).
+ defineMethod("IsExternal", &IsExternal).
+ defineMethod("IsInt32", &IsInt32).
+ defineMethod("IsUint32", &IsUint32).
+ defineMethod("IsDate", &IsDate).
+ defineMethod("IsBooleanObject", &IsBooleanObject).
+ defineMethod("IsNumberObject", &IsNumberObject).
+ defineMethod("IsStringObject", &IsStringObject).
+ defineMethod("IsNativeError", &IsNativeError).
+ defineMethod("IsRegExp", &IsRegExp).
+ defineMethod("ToString", &ToString).
+ defineMethod("ToDetailString", &ToDetailString).
+ defineMethod("ToObject", &ToObject).
+ defineMethod("BooleanValue", &BooleanValue).
+ defineMethod("NumberValue", &NumberValue).
+ defineMethod("IntegerValue", &IntegerValue).
+ defineMethod("Uint32Value", &Uint32Value).
+ defineMethod("IntegerValue", &IntegerValue).
defineMethod("Equals", &Equals).
defineMethod("StrictEquals", &StrictEquals)
.store(&Class);
}
+ VALUE Value::IsUndefined(VALUE self) {
+ return Bool(Value(self)->IsUndefined());
+ }
+ VALUE Value::IsNull(VALUE self) {
+ return Bool(Value(self)->IsNull());
+ }
+ VALUE Value::IsTrue(VALUE self) {
+ return Bool(Value(self)->IsTrue());
+ }
+ VALUE Value::IsFalse(VALUE self) {
+ return Bool(Value(self)->IsFalse());
+ }
+ VALUE Value::IsString(VALUE self) {
+ return Bool(Value(self)->IsString());
+ }
+ VALUE Value::IsFunction(VALUE self) {
+ return Bool(Value(self)->IsFunction());
+ }
+ VALUE Value::IsArray(VALUE self) {
+ return Bool(Value(self)->IsArray());
+ }
+ VALUE Value::IsObject(VALUE self) {
+ return Bool(Value(self)->IsObject());
+ }
+ VALUE Value::IsBoolean(VALUE self) {
+ return Bool(Value(self)->IsBoolean());
+ }
+ VALUE Value::IsNumber(VALUE self) {
+ return Bool(Value(self)->IsNumber());
+ }
+ VALUE Value::IsExternal(VALUE self) {
+ return Bool(Value(self)->IsExternal());
+ }
+ VALUE Value::IsInt32(VALUE self) {
+ return Bool(Value(self)->IsInt32());
+ }
+ VALUE Value::IsUint32(VALUE self) {
+ return Bool(Value(self)->IsUint32());
+ }
+ VALUE Value::IsDate(VALUE self) {
+ return Bool(Value(self)->IsDate());
+ }
+ VALUE Value::IsBooleanObject(VALUE self) {
+ return Bool(Value(self)->IsBooleanObject());
+ }
+ VALUE Value::IsNumberObject(VALUE self) {
+ return Bool(Value(self)->IsNumberObject());
+ }
+ VALUE Value::IsStringObject(VALUE self) {
+ return Bool(Value(self)->IsStringObject());
+ }
+ VALUE Value::IsNativeError(VALUE self) {
+ return Bool(Value(self)->IsNativeError());
+ }
+ VALUE Value::IsRegExp(VALUE self) {
+ return Bool(Value(self)->IsRegExp());
+ }
+
+ // VALUE Value::ToBoolean(VALUE self) {
+ // return Boolean(Value(self)->ToBoolean());
+ // }
+
+ // VALUE Value::ToNumber(VALUE self) {
+ // return Number(Value(self)->ToNumber());
+ // }
+ VALUE Value::ToString(VALUE self) {
+ return String(Value(self)->ToString());
+ }
+
+ VALUE Value::ToDetailString(VALUE self) {
+ return String(Value(self)->ToDetailString());
+ }
+
+ VALUE Value::ToObject(VALUE self) {
+ return Object(Value(self)->ToObject());
+ }
+
+ // VALUE Value::ToInteger(VALUE self) {
+ // return Integer(Value(self)->ToInteger());
+ // }
+
+ // VALUE Value::ToUint32(VALUE self) {
+ // return Uint32(Value(self)->ToUint32());
+ // }
+
+ // VALUE Value::ToInt32(VALUE self) {
+ // return Int32(Value(self)->ToInt32());
+ // }
+
+
+// VALUE Value::ToArrayIndex(VALUE self) {
+// return Uint32(Value(self)->ToArrayIndex());
+// }
+
+VALUE Value::BooleanValue(VALUE self) {
+ return Bool(Value(self)->BooleanValue());
+}
+VALUE Value::NumberValue(VALUE self) {
+ return rb_float_new(Value(self)->NumberValue());
+}
+VALUE Value::IntegerValue(VALUE self) {
+ return INT2NUM(Value(self)->IntegerValue());
+}
+VALUE Value::Uint32Value(VALUE self) {
+ return UINT2NUM(Value(self)->Uint32Value());
+}
+VALUE Value::Int32Value(VALUE self) {
+ return INT2FIX(Value(self)->Int32Value());
+}
+
VALUE Value::Equals(VALUE self, VALUE other) {
return Bool(Value(self)->Equals(Value(other)));
}
View
59 spec/c/trycatch_spec.rb
@@ -0,0 +1,59 @@
+require 'spec_helper'
+
+describe V8::C::External do
+ before do
+ @cxt = V8::C::Context::New()
+ @cxt.Enter()
+ end
+ after do
+ @cxt.Exit()
+ end
+ it "can catch javascript exceptions" do
+ V8::C::V8::SetCaptureStackTraceForUncaughtExceptions(true, 99, V8::C::StackTrace::kDetailed)
+ V8::C::TryCatch() do |trycatch|
+ V8::C::HandleScope() do
+ source = V8::C::String::New(<<-JS)
+ function one() {
+ two()
+ }
+ function two() {
+ three()
+ }
+ function three() {
+ boom()
+ }
+ function boom() {
+ throw new Error('boom!')
+ }
+ eval('one()')
+ JS
+ filename = V8::C::String::New("<eval>")
+ script = V8::C::Script::New(source, filename)
+ result = script.Run()
+ trycatch.HasCaught().should be_true
+ trycatch.CanContinue().should be_true
+ exception = trycatch.Exception()
+ exception.should_not be_nil
+ exception.IsNativeError().should be_true
+ trycatch.StackTrace().Utf8Value().should match /boom.*three.*two.*one/m
+ message = trycatch.Message();
+ message.should_not be_nil
+ message.Get().Utf8Value().should eql "Uncaught Error: boom!"
+ message.GetSourceLine().Utf8Value().should eql " throw new Error('boom!')"
+ message.GetScriptResourceName().Utf8Value().should eql "<eval>"
+ message.GetLineNumber().should eql 11
+ stack = message.GetStackTrace()
+ stack.should_not be_nil
+ stack.GetFrameCount().should eql 6
+ frame = stack.GetFrame(0)
+ frame.GetLineNumber().should eql 11
+ frame.GetColumn().should eql 17
+ frame.GetScriptName().Utf8Value().should eql "<eval>"
+ frame.GetScriptNameOrSourceURL().Utf8Value().should eql "<eval>"
+ frame.IsEval().should be_false
+ stack.GetFrame(4).IsEval().should be_true
+ frame.IsConstructor().should be_false
+ end
+ end
+ end
+end

0 comments on commit a581281

Please sign in to comment.
Something went wrong with that request. Please try again.