[gjs/wip/ptomato/730101: 1/3] jsapi-util-error: Allow throwing custom 'name' property



commit 5ce1116af6641035d1a360e4919f6e9fc1924c61
Author: Philip Chimento <philip endlessm com>
Date:   Thu Dec 22 16:49:17 2016 -0700

    jsapi-util-error: Allow throwing custom 'name' property
    
    According to MDN [1], an idiomatic way to indicate a custom error is by
    setting the 'name' property:
    
        var e = new Error('Malformed input'); // e.name is 'Error'
        e.name = 'ParseError';
        throw e;
        // e.toString() would return 'ParseError: Malformed input'
    
    Add an extra 'name' argument to gjs_throw_custom() to allow this. If
    'name' is NULL, then the previous behaviour is maintained.
    
    [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/name
    
    https://bugzilla.gnome.org/show_bug.cgi?id=730101

 gi/boxed.cpp                |    6 +++---
 gi/fundamental.cpp          |    4 ++--
 gi/param.cpp                |    4 ++--
 gi/union.cpp                |    6 +++---
 gjs/jsapi-dynamic-class.cpp |    2 +-
 gjs/jsapi-util-error.cpp    |   31 ++++++++++++++++++++++++-------
 gjs/jsapi-util.h            |    3 ++-
 7 files changed, 37 insertions(+), 19 deletions(-)
---
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 97f92cf..4447ed7 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -1260,7 +1260,7 @@ gjs_typecheck_boxed(JSContext       *context,
 
     if (priv->gboxed == NULL) {
         if (throw_error) {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is %s.%s.prototype, not an object instance - cannot convert to a boxed 
instance",
                              g_base_info_get_namespace( (GIBaseInfo*) priv->info),
                              g_base_info_get_name( (GIBaseInfo*) priv->info));
@@ -1278,14 +1278,14 @@ gjs_typecheck_boxed(JSContext       *context,
 
     if (!result && throw_error) {
         if (expected_info != NULL) {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is of type %s.%s - cannot convert to %s.%s",
                              g_base_info_get_namespace((GIBaseInfo*) priv->info),
                              g_base_info_get_name((GIBaseInfo*) priv->info),
                              g_base_info_get_namespace((GIBaseInfo*) expected_info),
                              g_base_info_get_name((GIBaseInfo*) expected_info));
         } else {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is of type %s.%s - cannot convert to %s",
                              g_base_info_get_namespace((GIBaseInfo*) priv->info),
                              g_base_info_get_name((GIBaseInfo*) priv->info),
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 1a0c96a..56c7121 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -849,13 +849,13 @@ gjs_typecheck_fundamental(JSContext       *context,
 
     if (!result && throw_error) {
         if (priv->prototype->info) {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is of type %s.%s - cannot convert to %s",
                              g_base_info_get_namespace((GIBaseInfo *) priv->prototype->info),
                              g_base_info_get_name((GIBaseInfo *) priv->prototype->info),
                              g_type_name(expected_gtype));
         } else {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is of type %s - cannot convert to %s",
                              g_type_name(priv->prototype->gtype),
                              g_type_name(expected_gtype));
diff --git a/gi/param.cpp b/gi/param.cpp
index 84a0e54..1b18150 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -305,7 +305,7 @@ gjs_typecheck_param(JSContext       *context,
 
     if (priv->gparam == NULL) {
         if (throw_error) {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is GObject.ParamSpec.prototype, not an object instance - "
                              "cannot convert to a GObject.ParamSpec instance");
         }
@@ -319,7 +319,7 @@ gjs_typecheck_param(JSContext       *context,
         result = true;
 
     if (!result && throw_error) {
-        gjs_throw_custom(context, "TypeError",
+        gjs_throw_custom(context, "TypeError", NULL,
                          "Object is of type %s - cannot convert to %s",
                          g_type_name(G_TYPE_FROM_INSTANCE (priv->gparam)),
                          g_type_name(expected_type));
diff --git a/gi/union.cpp b/gi/union.cpp
index 28db3dc..38a1405 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -444,7 +444,7 @@ gjs_typecheck_union(JSContext       *context,
 
     if (priv->gboxed == NULL) {
         if (throw_error) {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is %s.%s.prototype, not an object instance - cannot convert to a union 
instance",
                              g_base_info_get_namespace( (GIBaseInfo*) priv->info),
                              g_base_info_get_name( (GIBaseInfo*) priv->info));
@@ -462,14 +462,14 @@ gjs_typecheck_union(JSContext       *context,
 
     if (!result && throw_error) {
         if (expected_info != NULL) {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is of type %s.%s - cannot convert to %s.%s",
                              g_base_info_get_namespace((GIBaseInfo*) priv->info),
                              g_base_info_get_name((GIBaseInfo*) priv->info),
                              g_base_info_get_namespace((GIBaseInfo*) expected_info),
                              g_base_info_get_name((GIBaseInfo*) expected_info));
         } else {
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object is of type %s.%s - cannot convert to %s",
                              g_base_info_get_namespace((GIBaseInfo*) priv->info),
                              g_base_info_get_name((GIBaseInfo*) priv->info),
diff --git a/gjs/jsapi-dynamic-class.cpp b/gjs/jsapi-dynamic-class.cpp
index 5edc0f1..e229215 100644
--- a/gjs/jsapi-dynamic-class.cpp
+++ b/gjs/jsapi-dynamic-class.cpp
@@ -151,7 +151,7 @@ gjs_typecheck_instance(JSContext       *context,
         if (throw_error) {
             const JSClass *obj_class = JS_GetClass(obj);
 
-            gjs_throw_custom(context, "TypeError",
+            gjs_throw_custom(context, "TypeError", NULL,
                              "Object %p is not a subclass of %s, it's a %s",
                              obj.get(), static_clasp->name,
                              format_dynamic_class_name(obj_class->name));
diff --git a/gjs/jsapi-util-error.cpp b/gjs/jsapi-util-error.cpp
index bea2694..de890f1 100644
--- a/gjs/jsapi-util-error.cpp
+++ b/gjs/jsapi-util-error.cpp
@@ -42,9 +42,10 @@
  * http://egachine.berlios.de/embedding-sm-best-practice/embedding-sm-best-practice.html#error-handling
  */
 static void
-G_GNUC_PRINTF(3, 0)
+G_GNUC_PRINTF(4, 0)
 gjs_throw_valist(JSContext       *context,
                  const char      *error_class,
+                 const char      *error_name,
                  const char      *format,
                  va_list          args)
 {
@@ -76,7 +77,8 @@ gjs_throw_valist(JSContext       *context,
 
     JS::RootedObject constructor(context);
     JS::RootedObject global(context, JS::CurrentGlobalOrNull(context));
-    JS::RootedValue v_constructor(context), new_exc(context);
+    JS::RootedValue v_constructor(context), exc_val(context);
+    JS::RootedObject new_exc(context);
     JS::AutoValueArray<1> error_args(context);
     result = false;
 
@@ -93,8 +95,22 @@ gjs_throw_valist(JSContext       *context,
 
     /* throw new Error(message) */
     constructor = &v_constructor.toObject();
-    new_exc.setObjectOrNull(JS_New(context, constructor, error_args));
-    JS_SetPendingException(context, new_exc);
+    new_exc = JS_New(context, constructor, error_args);
+
+    if (new_exc == NULL)
+        goto out;
+
+    if (error_name != NULL) {
+        JS::RootedId name_id(context,
+            gjs_context_get_const_string(context, GJS_STRING_NAME));
+        JS::RootedValue name_value(context);
+        if (!gjs_string_from_utf8(context, error_name, -1, &name_value) ||
+            !JS_SetPropertyById(context, new_exc, name_id, name_value))
+            goto out;
+    }
+
+    exc_val.setObject(*new_exc);
+    JS_SetPendingException(context, exc_val);
 
     result = true;
 
@@ -128,25 +144,26 @@ gjs_throw(JSContext       *context,
     va_list args;
 
     va_start(args, format);
-    gjs_throw_valist(context, "Error", format, args);
+    gjs_throw_valist(context, "Error", NULL, format, args);
     va_end(args);
 }
 
 /*
  * Like gjs_throw, but allows to customize the error
- * class. Mainly used for throwing TypeError instead of
+ * class and 'name' property. Mainly used for throwing TypeError instead of
  * error.
  */
 void
 gjs_throw_custom(JSContext       *context,
                  const char      *error_class,
+                 const char      *error_name,
                  const char      *format,
                  ...)
 {
     va_list args;
 
     va_start(args, format);
-    gjs_throw_valist(context, error_class, format, args);
+    gjs_throw_valist(context, error_class, error_name, format, args);
     va_end(args);
 }
 
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 9f7c945..79d64fb 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -361,8 +361,9 @@ void        gjs_throw                        (JSContext       *context,
                                               ...)  G_GNUC_PRINTF (2, 3);
 void        gjs_throw_custom                 (JSContext       *context,
                                               const char      *error_class,
+                                              const char      *error_name,
                                               const char      *format,
-                                              ...)  G_GNUC_PRINTF (3, 4);
+                                              ...)  G_GNUC_PRINTF (4, 5);
 void        gjs_throw_literal                (JSContext       *context,
                                               const char      *string);
 void        gjs_throw_g_error                (JSContext       *context,


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