Js解释器V8引擎嵌入的异常处理
    Js解释器V8引擎嵌入的异常处理 
2011年08月10日
  v8引擎为Google开发的JS语言解释器有着高效易用等特点,通常它执行一个Js脚本需要经过编译和运行步骤, 
  由于我们的脚本程序很可能不正确,随时造成过程环节的异常,我们来解决一个异常以及错误的捕捉和处理过程,如下脚本: 
  test.js: 使用以下经典的V8 C++示例代码来执行脚本: #include  
  usingnamespace v8; 
  //提取js文件 
  v8::Handle::String> ReadFile(constchar* name) 
  { 
  FILE* file = fopen(name, "rb"); 
  if (file == NULL) return v8::Handle::String>(); 
  fseek(file, 0, SEEK_END); 
  int size = ftell(file); 
  rewind(file); 
  char* chars =newchar[size +1]; 
  chars[size] ='\0'; 
  for (int i =0; i ::Handle::String> result = v8::String::New(chars, size); 
  delete[] chars; 
  return result; 
  } 
  int main() 
  { 
  HandleScope handle_scope; 
  Handle context = Context::New(); 
  Context::Scope context_scope(context); 
  constchar* fname ="test.js"; 
  Handle source = ReadFile(fname); 
  //ExecuteString(source, String::New(fname), true, true); 
  Handle script = Script::Compile(source); 
  Handle result = script->Run(); 
  String::AsciiValue ascii(result); 
  printf("%s\n", *ascii); 
  return0; 
  } 
  然后编译程序  
  # g++ -o test test.cpp -lv8  
  # ./test 
  :58: Uncaught ReferenceError: alert is not defined 
  Segmentation fault 
  在执行过程遇到JS语法错误时,V8很干脆地中上了进程,提醒段错误。 
  在这我们正常应用环境是无法使用的,需要有一种异常处理机制来收集并处理错误。 
  这就是v8::TryCatch ,在编译前声明,在之后的编译和执行中只要有错误的发生均可捕获。 
  查找了相关的V8源代码,改进后的代码实现如下(函数体), 
  其中source为源文件内容,name用来标记当前脚本名称(文件名), 
  print_result表示是否打印脚本执行结果,report_exceptions表示是否报告异常(错误): bool ExecuteString(v8::Handle::String> source, 
  v8::Handle::Value> name, 
  bool print_result, 
  bool report_exceptions) 
  { 
  v8::HandleScope handle_scope; 
  v8::TryCatch try_catch; //这里设置异常机制 
  v8::Handle::Script> script = v8::Script::Compile(source, name); 
  if (script.IsEmpty()) { 
  // Print errors that happened during compilation. 
  if (report_exceptions) 
  ReportException(&try_catch); 
  returnfalse; 
  } else { 
  v8::Handle::Value> result = script->Run(); 
  if (result.IsEmpty()) { 
  assert(try_catch.HasCaught()); 
  // Print errors that happened during execution. 
  if (report_exceptions) 
  ReportException(&try_catch); 
  returnfalse; 
  } else { 
  assert(!try_catch.HasCaught()); 
  if (print_result &&!result->IsUndefined()) { 
  // If all went well and the result wasn't undefined then print 
  // the returned value. 
  v8::String::Utf8Value str(result); 
  constchar* cstr = ToCString(str); 
  printf("%s\n", cstr); 
  } 
  returntrue; 
  } 
  } 
  } 
  相关的异常处理函数: constchar* ToCString(const v8::String::Utf8Value& value) { 
  return*value ?*value : ""; 
  } 
  void ReportException(v8::TryCatch* try_catch) { 
  v8::HandleScope handle_scope; 
  v8::String::Utf8Value exception(try_catch->Exception()); 
  constchar* exception_string = ToCString(exception); 
  v8::Handle::Message> message = try_catch->Message(); 
  if (message.IsEmpty()) { 
  // V8 didn't provide any extra information about this error; just 
  // print the exception. 
  printf("%s\n", exception_string); 
  } else { 
  // Print (filename):(line number): (message). 
  v8::String::Utf8Value filename(message->GetScriptResourceName()); 
  constchar* filename_string = ToCString(filename); 
  int linenum = message->GetLineNumber(); 
  printf("%s:%i: %s\n", filename_string, linenum, exception_string); 
  // Print line of source code. 
  v8::String::Utf8Value sourceline(message->GetSourceLine()); 
  constchar* sourceline_string = ToCString(sourceline); 
  printf("%s