[gjs: 8/12] gerror: Make gjs_gerror_make_from_error() infallible




commit fcdf9d01e6fef61e4f74a5a53a675fdcff08d0dc
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun Mar 21 20:15:17 2021 -0700

    gerror: Make gjs_gerror_make_from_error() infallible
    
    In the case where the JS engine fails to convert a JS exception into a
    GError, we still want to have some GError to return to the caller, so
    return a GJS_JS_ERROR_INTERNAL_ERROR with a generic message.

 gi/function.cpp | 12 +++++-------
 gi/gerror.cpp   | 27 +++++++++++++++++++++++----
 2 files changed, 28 insertions(+), 11 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index be84cb8a..687eee96 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -416,13 +416,11 @@ void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) {
             GError* local_error =
                 gjs_gerror_make_from_error(context, exc_object);
 
-            if (local_error) {
-                // the GError ** pointer is the last argument, and is not
-                // included in the n_args
-                auto* gerror = gjs_arg_get<GError**>(error_argument);
-                g_propagate_error(gerror, local_error);
-                JS_ClearPendingException(context);  // don't log
-            }
+            // the GError ** pointer is the last argument, and is not
+            // included in the n_args
+            auto* gerror = gjs_arg_get<GError**>(error_argument);
+            g_propagate_error(gerror, local_error);
+            JS_ClearPendingException(context);  // don't log
         } else if (!rval.isUndefined()) {
             JS_SetPendingException(context, rval);
         }
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index 82e80e12..ddbae7db 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -426,10 +426,8 @@ bool ErrorBase::typecheck(JSContext* cx, JS::HandleObject obj,
     return GIWrapperBase::typecheck(cx, obj, nullptr, G_TYPE_ERROR, no_throw);
 }
 
-GError *
-gjs_gerror_make_from_error(JSContext       *cx,
-                           JS::HandleObject obj)
-{
+GJS_JSAPI_RETURN_CONVENTION
+static GError* gerror_from_error_impl(JSContext* cx, JS::HandleObject obj) {
     if (ErrorBase::typecheck(cx, obj, GjsTypecheckNoThrow())) {
         /* This is already a GError, just copy it */
         GError* inner = ErrorBase::to_c_ptr(cx, obj);
@@ -468,6 +466,27 @@ gjs_gerror_make_from_error(JSContext       *cx,
     return g_error_new_literal(GJS_JS_ERROR, code, message.get());
 }
 
+/*
+ * gjs_gerror_make_from_error:
+ *
+ * Attempts to convert a JavaScript exception into a #GError. This function is
+ * infallible and will always return a #GError with some message, even if the
+ * exception object couldn't be converted.
+ *
+ * Returns: (transfer full): a new #GError
+ */
+GError* gjs_gerror_make_from_error(JSContext* cx, JS::HandleObject obj) {
+    GError* retval = gerror_from_error_impl(cx, obj);
+    if (retval)
+        return retval;
+
+    // Make a GError with an InternalError even if it wasn't possible to convert
+    // the exception into one
+    gjs_log_exception(cx);  // log the inner exception
+    return g_error_new_literal(GJS_JS_ERROR, GJS_JS_ERROR_INTERNAL_ERROR,
+                               "Failed to convert JS exception into GError");
+}
+
 /*
  * gjs_throw_gerror:
  *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]