From 882b3fa6fdb9aee47d14ce67c8b0d1cca8a7efe3 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Tue, 21 Oct 2014 23:55:07 +0300 Subject: [PATCH] Add a guide section on error handling --- website/guide/programming.html | 83 +++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/website/guide/programming.html b/website/guide/programming.html index 282e67f2..053ab75c 100644 --- a/website/guide/programming.html +++ b/website/guide/programming.html @@ -572,12 +572,93 @@ error codes are defined in duktape.h, e.g. DUK_ERR_TYPE_ERROR flags. Negative error values are used in the Duktape/C API as a shorthand to automatically throw an error.

-

Error, fatal, and panic

+

Error handling

+ +

Error handling in the Duktape API is similar to how Ecmascript handles +errors: errors are thrown either explicitly or implicitly, then caught and +handled. However, instead of a try-catch statement application code uses +protected +Duktape API calls to establish points in C code where errors can be caught +and handled. +An uncaught error causes the fatal error handler to be called, which is +considered an unrecoverable situation and should ordinarily be avoided +(see Error, fatal, and panic).

+ +

To avoid fatal errors, typical application code should establish an error +catch point before making other Duktape API calls. This is done using +protected Duktape API calls, for example:

+ + +

An example of the first technique:

+
+/* Use duk_peval() variant to evaluate a file so that script errors are
+ * handled safely.  Both syntax errors and runtime errors are caught.
+ */
+
+if (duk_peval_file(ctx, "myscript.js") != 0) {
+    /* Use duk_safe_to_string() to convert error into string.  This API
+     * call is guaranteed not to throw an error during the coercion.
+     */
+    printf("Script error: %s\n", duk_safe_to_string(ctx, -1));
+}
+duk_pop(ctx);
+
+ +

An example of the second technique:

+
+/* Use duk_safe_call() to wrap all unsafe code into a separate C function.
+ * This approach has the advantage of covering all API calls automatically
+ * but is a bit more verbose.
+ */
+
+static duk_ret_t unsafe_code(duk_context *ctx) {
+    /* Here we can use unprotected calls freely. */
+    duk_eval_file_noresult(ctx, "myscript.js");
+
+    /* ... */
+
+    return 0;  /* success return, no return value */
+}
+
+/* elsewhere: */
+
+if (duk_safe_call(ctx, unsafe_code, 0 /*nargs*/, 1 /*nrets */) != 0) {
+    /* The 'nrets' argument should be at least 1 so that an error value
+     * is left on the stack if an error occurs.  To avoid further errors,
+     * use duk_safe_to_string() for safe error printing.
+     */
+    printf("Unexpected error: %s\n", duk_safe_to_string(ctx, -1));
+}
+duk_pop(ctx);
+
+ +

Even within protected calls there are some rare cases, such as internal +errors, that will either cause a fatal error or propagate an error outwards +from a protected API call. These should only happen in abnormal conditions +and are not considered recoverable. To handle also these cases well, a +production quality application should always have a fatal error handler with +a reasonable strategy for dealing with fatal errors.

+ +

Note that it may be fine for some applications to make API calls without +an error catcher and risk throwing uncaught errors. Even in this case there +should be a fatal error handler to easily detect and fix any remaining errors.

+ +

Error, fatal, and panic

An ordinary error is caused by a throw statement, a duk_throw() API call (or similar), or by an internal, recoverable Duktape error. Ordinary errors can be caught with a try-catch in Ecmascript code or e.g. duk_pcall() +(see API calls tagged +protected) in C code.

An uncaught error or an explicit call to duk_fatal() causes