基于Duktape:如何获取ECMAScript throw()抛出的错误对象?
获取Duktape脚本中throw抛出的错误对象
我之前也碰到过一模一样的问题,其实核心点很简单:当ECMAScript脚本里用throw抛出错误时,duk_pcall()返回失败后,抛出的对象其实就压在栈的最顶端——你大概率是没正确检查栈的状态,或者在处理错误前不小心做了栈操作把它弄丢了。
下面是具体的处理流程和代码示例,帮你拿到错误对象的详细调试信息(包括行号、文件名、完整栈跟踪):
核心逻辑
当duk_pcall()返回非DUK_EXEC_SUCCESS时,栈顶就是脚本抛出的那个值(可能是标准Error实例,也可能是字符串、数字这类非标准值)。如果是标准Error对象,它会自带lineNumber、fileName、stack这些对调试至关重要的属性。
完整处理代码示例
// 假设你已经把要调用的函数推到了栈顶,这里执行调用 duk_int_t outcome = duk_pcall(ctx, 0); // 第二个参数是传入函数的参数个数 if (outcome != DUK_EXEC_SUCCESS) { printf("脚本执行失败!\n"); // 先获取错误的基础描述(兼容非标准抛出值) const char* err_desc = duk_safe_to_string(ctx, -1); printf("错误描述:%s\n", err_desc); // 如果是标准Error对象,提取详细调试信息 if (duk_is_error(ctx, -1)) { // 获取错误行号 duk_get_prop_string(ctx, -1, "lineNumber"); duk_int_t line_num = duk_get_int(ctx, -1); duk_pop(ctx); // 弹出行号值,恢复栈状态 // 获取错误所在文件路径(包括require加载的模块) duk_get_prop_string(ctx, -1, "fileName"); const char* file_name = duk_safe_to_string(ctx, -1); duk_pop(ctx); // 弹出文件名值 // 获取完整栈跟踪 duk_get_prop_string(ctx, -1, "stack"); const char* stack_trace = duk_safe_to_string(ctx, -1); duk_pop(ctx); // 弹出栈跟踪值 printf("\n详细错误信息:\n"); printf("文件:%s\n行号:%d\n", file_name, line_num); printf("栈跟踪:\n%s\n", stack_trace); } // 最后务必弹出栈顶的错误对象,清理栈空间 duk_pop(ctx); }
常见问题排查
为什么我栈里找不到错误对象?
很可能你在duk_pcall()返回后,先做了其他栈操作(比如duk_pop()、duk_get_*),把栈顶的错误对象提前弹出了。处理错误的第一步就要检查栈顶。脚本抛出的不是Error对象怎么办?
如果脚本里直接throw "出错了"而不是throw new Error("出错了"),栈顶就是字符串,这时候没有lineNumber这类属性。建议提示用户在脚本里尽量抛出标准Error实例,才能拿到完整调试信息。require加载的模块里抛错能拿到路径吗?
完全可以!Duktape会自动把模块的路径填充到fileName属性里,哪怕是嵌套require的模块,栈跟踪里也会显示完整的调用链,帮你定位到用户不可见的底层脚本。
内容的提问来源于stack exchange,提问作者Antipole
相关产品推荐
相关产品推荐

