如何从 v8 脚本编译错误中获取行号和列?
How can I get line number and column from v8 script compile error?
在C++项目中嵌入V8 Javascript引擎时,我没有找到任何方法来获取脚本编译失败的行号。我尝试了以下方法:
//Given that v8 is initialized, isolate, context and script_source is setup.
v8::TryCatch try_catch{isolate};
//Compile the script from source
v8::Local<v8::Script> script;
if (!v8::Script::Compile(context, script_source).ToLocal(&script)) {
//Compilation failed
//Print exception from TryCatch
auto exc = try_catch.Exception();
v8::String::Utf8Value err{isolate, exc};
if (*err) {
std::cerr << "Exception: " << *err << std::endl;
}
//Print StackTrace from TryCatch
v8::Local<v8::Value> trace;
if (try_catch.StackTrace(context).ToLocal(&trace)) {
v8::String::Utf8Value trace_str{isolate, trace};
std::cerr << "Trace: " << *trace_str << std::endl;
}
//Print stack trace from isolate
auto stack = v8::StackTrace::CurrentStackTrace(isolate, 100);
std::cerr << "Stack trace:\n";
for (int i = 0; i < stack->GetFrameCount(); ++i) {
auto frame = stack->GetFrame(isolate, i);
v8::String::Utf8Value function_name{isolate, frame->GetFunctionName()};
std::cerr
<< "\tat "
<< function_name
<< " (line " << frame->GetLineNumber()
<< ", column " << frame->GetColumn() << ")\n";
}
}
转换为字符串时使用 v8::TryCatch::Exception
检索到的异常会导致如下错误消息:
SyntaxError: missing ) after argument list
消息中没有行号或列。使用 v8::TryCatch::StackTrace
转换为字符串时,我得到完全相同的消息,仍然没有行号。
v8::StackTrace::CurrentStackTrace
返回的堆栈跟踪不包含任何帧,所以我也无法在那里获取行号或列。
我也尝试在 v8::Script::Compile
函数中添加 v8::ScriptOrigin
,但这并没有影响错误消息。
似乎行号存储在与异常关联的 v8::Message
中。
我在 example in the v8 repo 中找到以下内容:
void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
v8::HandleScope handle_scope(isolate);
v8::String::Utf8Value exception(isolate, try_catch->Exception());
const char* exception_string = ToCString(exception);
v8::Local<v8::Message> message = try_catch->Message();
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just
// print the exception.
fprintf(stderr, "%s\n", exception_string);
} else {
// Print (filename):(line number): (message).
v8::String::Utf8Value filename(isolate,
message->GetScriptOrigin().ResourceName());
v8::Local<v8::Context> context(isolate->GetCurrentContext());
const char* filename_string = ToCString(filename);
int linenum = message->GetLineNumber(context).FromJust();
fprintf(stderr, "%s:%i: %s\n", filename_string, linenum, exception_string);
// Print line of source code.
v8::String::Utf8Value sourceline(
isolate, message->GetSourceLine(context).ToLocalChecked());
const char* sourceline_string = ToCString(sourceline);
fprintf(stderr, "%s\n", sourceline_string);
// Print wavy underline (GetUnderline is deprecated).
int start = message->GetStartColumn(context).FromJust();
for (int i = 0; i < start; i++) {
fprintf(stderr, " ");
}
int end = message->GetEndColumn(context).FromJust();
for (int i = start; i < end; i++) {
fprintf(stderr, "^");
}
fprintf(stderr, "\n");
v8::Local<v8::Value> stack_trace_string;
if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
stack_trace_string->IsString() &&
v8::Local<v8::String>::Cast(stack_trace_string)->Length() > 0) {
v8::String::Utf8Value stack_trace(isolate, stack_trace_string);
const char* stack_trace_string = ToCString(stack_trace);
fprintf(stderr, "%s\n", stack_trace_string);
}
}
}
在C++项目中嵌入V8 Javascript引擎时,我没有找到任何方法来获取脚本编译失败的行号。我尝试了以下方法:
//Given that v8 is initialized, isolate, context and script_source is setup.
v8::TryCatch try_catch{isolate};
//Compile the script from source
v8::Local<v8::Script> script;
if (!v8::Script::Compile(context, script_source).ToLocal(&script)) {
//Compilation failed
//Print exception from TryCatch
auto exc = try_catch.Exception();
v8::String::Utf8Value err{isolate, exc};
if (*err) {
std::cerr << "Exception: " << *err << std::endl;
}
//Print StackTrace from TryCatch
v8::Local<v8::Value> trace;
if (try_catch.StackTrace(context).ToLocal(&trace)) {
v8::String::Utf8Value trace_str{isolate, trace};
std::cerr << "Trace: " << *trace_str << std::endl;
}
//Print stack trace from isolate
auto stack = v8::StackTrace::CurrentStackTrace(isolate, 100);
std::cerr << "Stack trace:\n";
for (int i = 0; i < stack->GetFrameCount(); ++i) {
auto frame = stack->GetFrame(isolate, i);
v8::String::Utf8Value function_name{isolate, frame->GetFunctionName()};
std::cerr
<< "\tat "
<< function_name
<< " (line " << frame->GetLineNumber()
<< ", column " << frame->GetColumn() << ")\n";
}
}
转换为字符串时使用 v8::TryCatch::Exception
检索到的异常会导致如下错误消息:
SyntaxError: missing ) after argument list
消息中没有行号或列。使用 v8::TryCatch::StackTrace
转换为字符串时,我得到完全相同的消息,仍然没有行号。
v8::StackTrace::CurrentStackTrace
返回的堆栈跟踪不包含任何帧,所以我也无法在那里获取行号或列。
我也尝试在 v8::Script::Compile
函数中添加 v8::ScriptOrigin
,但这并没有影响错误消息。
似乎行号存储在与异常关联的 v8::Message
中。
我在 example in the v8 repo 中找到以下内容:
void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
v8::HandleScope handle_scope(isolate);
v8::String::Utf8Value exception(isolate, try_catch->Exception());
const char* exception_string = ToCString(exception);
v8::Local<v8::Message> message = try_catch->Message();
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just
// print the exception.
fprintf(stderr, "%s\n", exception_string);
} else {
// Print (filename):(line number): (message).
v8::String::Utf8Value filename(isolate,
message->GetScriptOrigin().ResourceName());
v8::Local<v8::Context> context(isolate->GetCurrentContext());
const char* filename_string = ToCString(filename);
int linenum = message->GetLineNumber(context).FromJust();
fprintf(stderr, "%s:%i: %s\n", filename_string, linenum, exception_string);
// Print line of source code.
v8::String::Utf8Value sourceline(
isolate, message->GetSourceLine(context).ToLocalChecked());
const char* sourceline_string = ToCString(sourceline);
fprintf(stderr, "%s\n", sourceline_string);
// Print wavy underline (GetUnderline is deprecated).
int start = message->GetStartColumn(context).FromJust();
for (int i = 0; i < start; i++) {
fprintf(stderr, " ");
}
int end = message->GetEndColumn(context).FromJust();
for (int i = start; i < end; i++) {
fprintf(stderr, "^");
}
fprintf(stderr, "\n");
v8::Local<v8::Value> stack_trace_string;
if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
stack_trace_string->IsString() &&
v8::Local<v8::String>::Cast(stack_trace_string)->Length() > 0) {
v8::String::Utf8Value stack_trace(isolate, stack_trace_string);
const char* stack_trace_string = ToCString(stack_trace);
fprintf(stderr, "%s\n", stack_trace_string);
}
}
}