日期:2014-05-16  浏览次数:20320 次

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