DUK_F_UCLIBC checks for __UCLIBC__ which comes from #include files rather
than being built into the compiler, so it must be placed after platform
includes instead of being automatically inserted to top of file.
If the lightfunc had varargs, the coerced normal function object would
also get a vararg argument count, but the 'nargs' variable went through
fragile casts in the process.
These have been unnecessary even before, but they caused seemingly bogus
warnings with some compilers. Now that the setjmp() functions are much
smaller, these are hopefully no longer an issue.
* Define duk_internal_exception, a plain exception class, wihch is used as
the value thrown for Duktape internal long control transfers. The value
intentionally does not inherit from std::exception so that it'd be as
unlikely as possible that user code would catch the internal exception
type; only a "catch (...)" would catch it.
* Replace DUK_SETJMP() if clauses with "try", and SETJMP() error handling
blocks with "catch (duk_internal_exception &exc)" blocks.
* Also add clauses for "catch (std::exception &exc)" and "catch (...)" to
catch C++ exceptions thrown by user code which are propagated to Duktape
try-catch blocks. Such exceptions are converted to API errors. For now
it's not supported for user code to propagate a C++ exception "through"
Duktape, as that would require some semantics changes to (native) protected
calls. Catching and converting such exceptions to API errors makes the
user code error apparent and easier to fix.
* Add DUK_USE_CPP_EXCEPTIONS (DUK_OPT_CPP_EXCEPTIONS) which causes Duktape
to use C++ try/catch instead of longjmp/setjmp for internal long control
transfers. When try/catch is used scope-based resource management
(SBRM, a special case of RAII) works as expected, e.g. C++ automatic
destructors in Duktape/C functions will be executed.
* Add <exception> header to shared headers when compiling in C++ mode.
The header is needed to provide std::exception.
* Add a sanity check: if DUK_USE_CPP_EXCEPTIONS is enabled and not
compiling with a C++ compiler, fail the compile with an explicit #error.
Separate call handling into three functions: unprotected call wrapper,
protected call wrapper, and a shared inner call handler. Having setjmp
only in a smaller wrapper reduces problems with compiler, including:
* Spurious volatile warnings
* Performance impact on compilers where optimizations must be disabled for
any function involving a setjmp
Also make every DUK_SETJMP() call site compatible with a later refactoring
to supporting C++ exceptions by handling the success case in the then-block
and the error in the else-block. This allows a try-catch structure to
trivially replace the setjmp construct.
Split call error handling to separate function which makes it easier to
share for C++ exception handling which may need a catch (xxx) for Duktape
errors and a separate catch (...) for other errors accidentally thrown by
user code.
Other minor cleanups in call handling.
The bytecode was missing DUK_REOP_SAVE for indices 0 and 1, i.e. the
zeroth capture, which caused the RegExp.prototype to match an empty
input but without providing the zeroth capture which is assumed in
other parts of Duktape internals. This caused the GH-492 assert failure
and, with asserts disabled, a segfault.
DUK_USE_DEBUGGER_THROW_NOTIFY default is "true". If the option "requires"
DUK_USE_DEBUGGER_SUPPORT (which defaults to "false") the option configuraiton
would be inconsistent and rejected by default.
Remove the "required" metadata for debugger options: the options don't really
require debugger support. Instead, if debugger support is disabled, the
debugger config options are just ignored without causing a build error.