mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.9 KiB
125 lines
3.9 KiB
/*
|
|
* 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];
|
|
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);
|
|
}
|
|
|