Browse Source

Add a guide section on error handling

v1.0-maintenance
Sami Vaarala 10 years ago
parent
commit
882b3fa6fd
  1. 83
      website/guide/programming.html

83
website/guide/programming.html

@ -572,12 +572,93 @@ error codes are defined in <code>duktape.h</code>, e.g. <code>DUK_ERR_TYPE_ERROR
flags. Negative error values are used in the Duktape/C API as a
shorthand to automatically throw an error.</p>
<h2>Error, fatal, and panic</h2>
<h2 id="error-handling">Error handling</h2>
<p>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
<code><a href="api.html#taglist-protected">protected</a></code>
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 <a href="#error-fatal-panic">Error, fatal, and panic</a>).</p>
<p>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:</p>
<ul>
<li>Use protected calls to evaluate code
(<a href="api.html#duk_peval">duk_peval()</a>), compile code
(<a href="api.html#duk_pcompile">duk_pcompile()</a>), and call
(<a href="api.html#duk_pcall">duk_pcall()</a>) functions.</li>
<li>Use a single <a href="api.html#duk_safe_call">duk_safe_call()</a> to
establish an error catcher so that you can use unsafe primitives freely
inside the safe call.</li>
</ul>
<p>An example of the first technique:</p>
<pre class="c-code">
/* 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);
</pre>
<p>An example of the second technique:</p>
<pre class="c-code">
/* 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);
</pre>
<p>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.</p>
<p>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.</p>
<h2 id="error-fatal-panic">Error, fatal, and panic</h2>
<p>An <b>ordinary error</b> is caused by a <code>throw</code> statement,
a <code>duk_throw()</code> API call (or similar), or by an internal,
recoverable Duktape error. Ordinary errors can be caught with a
<code>try-catch</code> in Ecmascript code or e.g. <code>duk_pcall()</code>
(see API calls tagged
<code><a href="api.html#taglist-protected">protected</a></code>)
in C code.</p>
<p>An uncaught error or an explicit call to <code>duk_fatal()</code> causes

Loading…
Cancel
Save