How can I get an error object after an ECMAscript throw( )?

178 Views Asked by At

I can throw errors in C++ code by pushing an error object and then calling duk_throw(). duk_pcall() returns with 'outcome != DUK_EXEC_SUCCESS' and I can examine the error object to determine, for example, the line number where the call to my API was. All working well, thank you.

If a script throws an error using EMCAscript throw( ), duk_pcall( ) returns 'outcome != DUK_EXEC_SUCCESS' as above but there is no error object on the stack. So I cannot determine the line number. Since the throw may be in scripts loaded with require() and not visible to the user, this is a pity.

Is it possible to get an error object from an ECMAscript throw( ) ?

2

There are 2 best solutions below

0
Mike Lischke On

Double check your finding. For me there's an error object on the TOS when duk_pcall fails:

    result = duk_pcall(_ctx, static_cast<duk_idx_t>(argCount));
    if (result != DUK_EXEC_SUCCESS)
      checkForErrors();

And the error check is:

/**
 * Checks if the TOS contains a JS error object and throws a C++ exception for it. This is particularly useful
 * when executing code in safe mode (pcall).
 */
void ScriptingContext::checkForErrors() const {
  if (duk_is_error(_ctx, -1)) {
    // See if there's a stack trace. That includes the actual error message so we can use
    // that as exception message. Otherwise just get what is on stack top.
    std::string error;
    if (duk_has_prop_string(_ctx, -1, "stack")) {
      duk_get_prop_string(_ctx, -1, "stack"); // Puts stack trace on the stack.
      error = duk_require_string(_ctx, -1);
    } else {
      error = duk_safe_to_string(_ctx, -1);
    }
    duk_pop(_ctx); // Remove error from stack.

    throw std::runtime_error(error);
  }
}
0
Antipole On

Thanks for commenting. Not for me it isn't.

I have:

startTimeout();
duk_int_t dukOutcome = duk_peval(mpCtx);    // run code
clearTimeout();
if (dukOutcome != DUK_EXEC_SUCCESS){
    if (duk_is_error(mpCtx, -1)){
         wxString formErrorMessage(duk_context *ctx);
         m_result = formErrorMessage(mpCtx);
         }
    else m_result = duk_safe_to_string(mpCtx, -1);
    duk_pop(mpCtx);
    return ERROR;
    }

If the error is thrown in C++ code as I described in my OP, formErrorMessage gets called. If the error is because of a JavaScript throw("Message"); statement, the duk_is_error(mpCtx, -1)) is false and the formErrorMessage route is not taken. I am tracing this under Xcode and can see exactly what is happening. Might there be some configuration option that is different between us?

Duktape v2.5.0 wxWidgets v3.1.2