#include "tomato.h" VALUE eTransError = Qnil; Local js_error_from(VALUE ruby_error) { VALUE message = rb_funcall(ruby_error, rb_intern("to_s"), 0); Local js_error = Local::Cast(Exception::Error(String::New(StringValuePtr(message)))); js_error->Set(String::New("_is_ruby_error"), Boolean::New(true), DontEnum); return js_error; } void err_init(void) { eTransError = rb_define_class_under(cTomato, "TranslatableError", cTomatoError); } /* The following was adapted from samples/shell.cc in v8 project. */ void raise_error(TryCatch *try_catch) { HandleScope handle_scope; String::Utf8Value exception(try_catch->Exception()); Handle message = try_catch->Message(); /* check for Ruby error; if it's an error, reraise $!. TODO: See $! can ever be a different error... */ Handle is_ruby_error = Local::Cast(try_catch->Exception())->Get(String::New("_is_ruby_error")); if (is_ruby_error->IsBoolean() && is_ruby_error->IsTrue()) { throw rb_gv_get("$!"); } std::string errmsg; if (message.IsEmpty()) { // V8 didn't provide any extra information about this error; just // print the exception. errmsg += ToCString(exception); errmsg += "\n"; } else { // Print (filename):(line number): (message). String::Utf8Value filename(message->GetScriptResourceName()); int linenum = message->GetLineNumber(); errmsg += ToCString(filename); errmsg += ":"; errmsg += linenum; errmsg += ToCString(exception); errmsg += "\n"; // Print line of source code. String::Utf8Value sourceline(message->GetSourceLine()); errmsg += ToCString(sourceline); errmsg += "\n"; // Print wavy underline (GetUnderline is deprecated). int start = message->GetStartColumn(); for (int i = 0; i < start; i++) { errmsg += " "; } int end = message->GetEndColumn(); for (int i = start; i < end; i++) { errmsg += "^"; } errmsg += "\n"; String::Utf8Value stack_trace(try_catch->StackTrace()); if (stack_trace.length() > 0) { const char* stack_trace_string = ToCString(stack_trace); errmsg += stack_trace_string; errmsg += "\n"; } } throw errmsg; }