diff options
Diffstat (limited to '')
-rw-r--r-- | src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_error_misc.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_error_misc.c b/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_error_misc.c new file mode 100644 index 000000000..5b3785533 --- /dev/null +++ b/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_error_misc.c @@ -0,0 +1,132 @@ +/* + * Error helpers + */ + +#include "duk_internal.h" + +/* + * Helper to walk the thread chain and see if there is an active error + * catcher. Protected calls or finally blocks aren't considered catching. + */ + +#if defined(DUK_USE_DEBUGGER_SUPPORT) && \ + (defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)) +DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) { + /* + * XXX: As noted above, a protected API call won't be counted as a + * catcher. This is usually convenient, e.g. in the case of a top- + * level duk_pcall(), but may not always be desirable. Perhaps add an + * argument to treat them as catchers? + */ + + duk_size_t i; + + DUK_ASSERT(thr != NULL); + + while (thr != NULL) { + for (i = 0; i < thr->catchstack_top; i++) { + duk_catcher *cat = thr->catchstack + i; + if (DUK_CAT_HAS_CATCH_ENABLED(cat)) { + return 1; /* all we need to know */ + } + } + thr = thr->resumer; + } + return 0; +} +#endif /* DUK_USE_DEBUGGER_SUPPORT && (DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) */ + +/* + * Get prototype object for an integer error code. + */ + +DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) { + switch (code) { + case DUK_ERR_EVAL_ERROR: + return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]; + case DUK_ERR_RANGE_ERROR: + return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]; + case DUK_ERR_REFERENCE_ERROR: + return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]; + case DUK_ERR_SYNTAX_ERROR: + return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]; + case DUK_ERR_TYPE_ERROR: + return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]; + case DUK_ERR_URI_ERROR: + return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]; + + /* XXX: more specific error classes? */ + case DUK_ERR_UNIMPLEMENTED_ERROR: + case DUK_ERR_INTERNAL_ERROR: + case DUK_ERR_ALLOC_ERROR: + case DUK_ERR_ASSERTION_ERROR: + case DUK_ERR_API_ERROR: + case DUK_ERR_ERROR: + default: + return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]; + } +} + +/* + * Exposed helper for setting up heap longjmp state. + */ + +DUK_INTERNAL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type) { +#if defined(DUK_USE_DEBUGGER_SUPPORT) + /* If something is thrown with the debugger attached and nobody will + * catch it, execution is paused before the longjmp, turning over + * control to the debug client. This allows local state to be examined + * before the stack is unwound. Errors are not intercepted when debug + * message loop is active (e.g. for Eval). + */ + + /* XXX: Allow customizing the pause and notify behavior at runtime + * using debugger runtime flags. For now the behavior is fixed using + * config options. + */ +#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) + if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) && + !thr->heap->dbg_processing && + lj_type == DUK_LJ_TYPE_THROW) { + duk_context *ctx = (duk_context *) thr; + duk_bool_t fatal; + duk_hobject *h_obj; + + /* Don't intercept a DoubleError, we may have caused the initial double + * fault and attempting to intercept it will cause us to be called + * recursively and exhaust the C stack. + */ + h_obj = duk_get_hobject(ctx, -1); + if (h_obj == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) { + DUK_D(DUK_DPRINT("built-in DoubleError instance thrown, not intercepting")); + goto skip_throw_intercept; + } + + DUK_D(DUK_DPRINT("throw with debugger attached, report to client")); + + fatal = !duk__have_active_catcher(thr); + +#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY) + /* Report it to the debug client */ + duk_debug_send_throw(thr, fatal); +#endif + +#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) + if (fatal) { + DUK_D(DUK_DPRINT("throw will be fatal, halt before longjmp")); + duk_debug_halt_execution(thr, 1 /*use_prev_pc*/); + } +#endif + } + + skip_throw_intercept: +#endif /* DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT */ +#endif /* DUK_USE_DEBUGGER_SUPPORT */ + + thr->heap->lj.type = lj_type; + + DUK_ASSERT(thr->valstack_top > thr->valstack); + DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, thr->valstack_top - 1); /* side effects */ + + duk_pop((duk_context *) thr); +} |