You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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);
}

常见问题排查

  1. 为什么我栈里找不到错误对象?
    很可能你在duk_pcall()返回后,先做了其他栈操作(比如duk_pop()、duk_get_*),把栈顶的错误对象提前弹出了。处理错误的第一步就要检查栈顶。

  2. 脚本抛出的不是Error对象怎么办?
    如果脚本里直接throw "出错了"而不是throw new Error("出错了"),栈顶就是字符串,这时候没有lineNumber这类属性。建议提示用户在脚本里尽量抛出标准Error实例,才能拿到完整调试信息。

  3. require加载的模块里抛错能拿到路径吗?
    完全可以!Duktape会自动把模块的路径填充到fileName属性里,哪怕是嵌套require的模块,栈跟踪里也会显示完整的调用链,帮你定位到用户不可见的底层脚本。

内容的提问来源于stack exchange,提问作者Antipole

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 13:22:42