[gjs] Use GLib for JS logging



commit 9deaf856f3a0f686a0e1c38e70f29c2428a1d6a1
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Wed Jan 2 22:49:38 2013 +0100

    Use GLib for JS logging
    
    Reserve our custom logging framework for debug logging, and use standard
    g_log functions for log() and logError().
    This allows us to finally have readable error messages, it associates
    them with a program and process when necessary, and it prepares us
    for a future where glib logs to the journal by default.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=690984

 Makefile.am                            |    2 +-
 gi/arg.c                               |   12 +--
 gi/boxed.c                             |    7 +-
 gi/closure.c                           |    6 +-
 gi/function.c                          |    2 +-
 gi/gerror.c                            |    4 +-
 gi/interface.c                         |    2 +-
 gi/keep-alive.c                        |   12 ++--
 gi/ns.c                                |    4 +-
 gi/object.c                            |    2 +-
 gi/param.c                             |    2 +-
 gi/repo.c                              |    6 +-
 gi/union.c                             |    2 +-
 gi/value.c                             |    4 +-
 gjs/context.c                          |  118 +++++++++-------------------
 gjs/importer.c                         |   17 ++--
 gjs/jsapi-private.cpp                  |   23 ++----
 gjs/jsapi-util.c                       |  131 ++++++++++++--------------------
 gjs/jsapi-util.h                       |   13 ++--
 installed-tests/test/js/testSignals.js |    6 ++
 util/log.c                             |   51 +-----------
 util/log.h                             |    5 -
 22 files changed, 151 insertions(+), 280 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 9debd81..bdf8cb8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,7 +17,7 @@ TEST_PROGS =
 check_PROGRAMS = $(TEST_PROGS)
 INTROSPECTION_GIRS =
 ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
-AM_CFLAGS = $(WARN_CFLAGS)
+AM_CFLAGS = $(WARN_CFLAGS) -DG_LOG_DOMAIN=\"Gjs\"
 
 gjsjsdir = @gjsjsdir@
 gjsoverridedir = $(gjsjsdir)/overrides
diff --git a/gi/arg.c b/gi/arg.c
index fb5e2ca..e9105d6 100644
--- a/gi/arg.c
+++ b/gi/arg.c
@@ -1748,8 +1748,7 @@ gjs_value_to_g_argument(JSContext      *context,
         break;
     }
     default:
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Unhandled type %s for JavaScript to GArgument conversion",
+        g_warning("Unhandled type %s for JavaScript to GArgument conversion",
                   g_type_tag_to_string(type_tag));
         wrong = TRUE;
         report_type_mismatch = TRUE;
@@ -1899,8 +1898,7 @@ gjs_g_argument_init_default(JSContext      *context,
         break;
 
     default:
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Unhandled type %s for default GArgument initialization",
+        g_warning("Unhandled type %s for default GArgument initialization",
                   g_type_tag_to_string(type_tag));
         break;
     }
@@ -2757,8 +2755,7 @@ gjs_value_from_g_argument (JSContext  *context,
         break;
 
     default:
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Unhandled type %s converting GArgument to JavaScript",
+        g_warning("Unhandled type %s converting GArgument to JavaScript",
                   g_type_tag_to_string(type_tag));
         return JS_FALSE;
     }
@@ -3197,8 +3194,7 @@ gjs_g_arg_release_internal(JSContext  *context,
         break;
 
     default:
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Unhandled type %s releasing GArgument",
+        g_warning("Unhandled type %s releasing GArgument",
                   g_type_tag_to_string(type_tag));
         return JS_FALSE;
     }
diff --git a/gi/boxed.c b/gi/boxed.c
index 26d7f69..839846f 100644
--- a/gi/boxed.c
+++ b/gi/boxed.c
@@ -869,8 +869,7 @@ define_boxed_class_fields (JSContext *context,
      * memory overhead.
      */
     if (n_fields > 256) {
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Only defining the first 256 fields in boxed type '%s'",
+        g_warning("Only defining the first 256 fields in boxed type '%s'",
                   g_base_info_get_name ((GIBaseInfo *)priv->info));
         n_fields = 256;
     }
@@ -1217,8 +1216,8 @@ gjs_define_boxed_class(JSContext    *context,
                                 NULL,
                                 &prototype,
                                 &constructor)) {
-        gjs_log_exception(context, NULL);
-        gjs_fatal("Can't init class %s", constructor_name);
+        gjs_log_exception(context);
+        g_error("Can't init class %s", constructor_name);
     }
 
     GJS_INC_COUNTER(boxed);
diff --git a/gi/closure.c b/gi/closure.c
index de6d7d6..2784a0f 100644
--- a/gi/closure.c
+++ b/gi/closure.c
@@ -271,7 +271,7 @@ gjs_closure_invoke(GClosure *closure,
     if (JS_IsExceptionPending(context)) {
         gjs_debug_closure("Exception was pending before invoking callback??? "
                           "Not expected");
-        gjs_log_exception(context, NULL);
+        gjs_log_exception(context);
     }
 
     if (!gjs_call_function_value(context,
@@ -284,12 +284,12 @@ gjs_closure_invoke(GClosure *closure,
         gjs_debug_closure("Closure invocation failed (exception should "
                           "have been thrown) closure %p callable %p",
                           closure, c->obj);
-        if (!gjs_log_exception(context, NULL))
+        if (!gjs_log_exception(context))
             gjs_debug_closure("Closure invocation failed but no exception was set?");
         goto out;
     }
 
-    if (gjs_log_exception(context, NULL)) {
+    if (gjs_log_exception(context)) {
         gjs_debug_closure("Closure invocation succeeded but an exception was set");
     }
 
diff --git a/gi/function.c b/gi/function.c
index ff53eae..4de7647 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -1582,7 +1582,7 @@ function_new(JSContext      *context,
                                  /* funcs of constructor, MyConstructor.myfunc() */
                                  NULL);
         if (prototype == NULL)
-            gjs_fatal("Can't init class %s", gjs_function_class.name);
+            g_error("Can't init class %s", gjs_function_class.name);
 
         gjs_debug(GJS_DEBUG_GFUNCTION, "Initialized class %s prototype %p",
                   gjs_function_class.name, prototype);
diff --git a/gi/gerror.c b/gi/gerror.c
index 30e710c..3bcad05 100644
--- a/gi/gerror.c
+++ b/gi/gerror.c
@@ -441,8 +441,8 @@ gjs_define_error_class(JSContext    *context,
                                 &gjs_error_constructor_funcs[0],
                                 &prototype,
                                 &constructor)) {
-        gjs_log_exception(context, NULL);
-        gjs_fatal("Can't init class %s", constructor_name);
+        gjs_log_exception(context);
+        g_error("Can't init class %s", constructor_name);
     }
 
     GJS_INC_COUNTER(gerror);
diff --git a/gi/interface.c b/gi/interface.c
index 98be8e5..29cefe1 100644
--- a/gi/interface.c
+++ b/gi/interface.c
@@ -224,7 +224,7 @@ gjs_define_interface_class(JSContext       *context,
                                 NULL,
                                 &prototype,
                                 &constructor)) {
-        gjs_fatal("Can't init class %s", constructor_name);
+        g_error("Can't init class %s", constructor_name);
     }
 
     GJS_INC_COUNTER(interface);
diff --git a/gi/keep-alive.c b/gi/keep-alive.c
index e933a43..08624c6 100644
--- a/gi/keep-alive.c
+++ b/gi/keep-alive.c
@@ -229,7 +229,7 @@ gjs_keep_alive_new(JSContext *context)
                                  /* funcs of constructor, MyConstructor.myfunc() */
                                  NULL);
         if (prototype == NULL)
-            gjs_fatal("Can't init class %s", gjs_keep_alive_class.name);
+            g_error("Can't init class %s", gjs_keep_alive_class.name);
 
         gjs_debug(GJS_DEBUG_KEEP_ALIVE, "Initialized class %s prototype %p",
                   gjs_keep_alive_class.name, prototype);
@@ -241,8 +241,8 @@ gjs_keep_alive_new(JSContext *context)
 
     keep_alive = JS_NewObject(context, &gjs_keep_alive_class, NULL, global);
     if (keep_alive == NULL) {
-        gjs_log_exception(context, NULL);
-        gjs_fatal("Failed to create keep_alive object");
+        gjs_log_exception(context);
+        g_error("Failed to create keep_alive object");
     }
 
     priv = g_slice_new0(KeepAlive);
@@ -330,7 +330,7 @@ gjs_keep_alive_create(JSContext *context)
 
     keep_alive = gjs_keep_alive_new(context);
     if (!keep_alive)
-        gjs_fatal("could not create keep_alive on global object, no memory?");
+        g_error("could not create keep_alive on global object, no memory?");
 
     gjs_set_global_slot(context, GJS_GLOBAL_SLOT_KEEP_ALIVE, OBJECT_TO_JSVAL(keep_alive));
 
@@ -383,8 +383,8 @@ gjs_keep_alive_remove_global_child(JSContext         *context,
     keep_alive = gjs_keep_alive_get_global(context);
 
     if (!keep_alive)
-        gjs_fatal("no keep_alive property on the global object, have you "
-                  "previously added this child?");
+        g_error("no keep_alive property on the global object, have you "
+                "previously added this child?");
 
     gjs_keep_alive_remove_child(context,
                                 gjs_keep_alive_get_global(context),
diff --git a/gi/ns.c b/gi/ns.c
index 3ec7e5a..391397f 100644
--- a/gi/ns.c
+++ b/gi/ns.c
@@ -216,7 +216,7 @@ ns_new(JSContext    *context,
                                  /* funcs of constructor, MyConstructor.myfunc() */
                                  NULL);
         if (prototype == NULL)
-            gjs_fatal("Can't init class %s", gjs_ns_class.name);
+            g_error("Can't init class %s", gjs_ns_class.name);
 
         gjs_debug(GJS_DEBUG_GNAMESPACE, "Initialized class %s prototype %p",
                   gjs_ns_class.name, prototype);
@@ -224,7 +224,7 @@ ns_new(JSContext    *context,
 
     ns = JS_NewObject(context, &gjs_ns_class, NULL, global);
     if (ns == NULL)
-        gjs_fatal("No memory to create ns object");
+        g_error("No memory to create ns object");
 
     priv = g_slice_new0(Ns);
 
diff --git a/gi/object.c b/gi/object.c
index 7426e31..9e1cf90 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -1984,7 +1984,7 @@ gjs_define_object_class(JSContext     *context,
                                 NULL,
                                 &prototype,
                                 &constructor)) {
-        gjs_fatal("Can't init class %s", constructor_name);
+        g_error("Can't init class %s", constructor_name);
     }
 
     GJS_INC_COUNTER(object);
diff --git a/gi/param.c b/gi/param.c
index 857bc46..f2542c1 100644
--- a/gi/param.c
+++ b/gi/param.c
@@ -528,7 +528,7 @@ gjs_define_param_class(JSContext    *context,
                                 gjs_param_constructor_funcs,
                                 &prototype,
                                 &constructor)) {
-        gjs_fatal("Can't init class %s", constructor_name);
+        g_error("Can't init class %s", constructor_name);
     }
 
     value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, G_TYPE_PARAM));
diff --git a/gi/repo.c b/gi/repo.c
index 6db129b..68bfed8 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -122,7 +122,7 @@ resolve_namespace_object(JSContext  *context,
                            ns_name, OBJECT_TO_JSVAL(namespace),
                            NULL, NULL,
                            GJS_MODULE_PROP_FLAGS))
-        gjs_fatal("no memory to define ns property");
+        g_error("no memory to define ns property");
 
     override = lookup_override_function(context, ns_id);
     if (override && !JS_CallFunctionValue (context,
@@ -282,7 +282,7 @@ repo_new(JSContext *context)
                                  /* funcs of constructor, MyConstructor.myfunc() */
                                  NULL);
         if (prototype == NULL)
-            gjs_fatal("Can't init class %s", gjs_repo_class.name);
+            g_error("Can't init class %s", gjs_repo_class.name);
 
         gjs_debug(GJS_DEBUG_GREPO, "Initialized class %s prototype %p",
                   gjs_repo_class.name, prototype);
@@ -620,7 +620,7 @@ gjs_lookup_namespace_object_by_name(JSContext      *context,
     if (!gjs_object_require_property(context, JSVAL_TO_OBJECT(importer), "importer",
                                      gi_name, &girepository) ||
         !JSVAL_IS_OBJECT(girepository)) {
-        gjs_log_exception(context, NULL);
+        gjs_log_exception(context);
         gjs_throw(context, "No gi property in importer");
         goto fail;
     }
diff --git a/gi/union.c b/gi/union.c
index f87a2b0..5d8825e 100644
--- a/gi/union.c
+++ b/gi/union.c
@@ -423,7 +423,7 @@ gjs_define_union_class(JSContext    *context,
                                 NULL,
                                 &prototype,
                                 &constructor)) {
-        gjs_fatal("Can't init class %s", constructor_name);
+        g_error("Can't init class %s", constructor_name);
     }
 
     GJS_INC_COUNTER(boxed);
diff --git a/gi/value.c b/gi/value.c
index c69debe..9d6e633 100644
--- a/gi/value.c
+++ b/gi/value.c
@@ -122,7 +122,7 @@ closure_marshal(GClosure        *closure,
             gjs_debug(GJS_DEBUG_GCLOSURE,
                       "Unable to convert arg %d in order to invoke closure",
                       i);
-            gjs_log_exception(context, NULL);
+            gjs_log_exception(context);
             goto cleanup;
         }
     }
@@ -138,7 +138,7 @@ closure_marshal(GClosure        *closure,
         if (!gjs_value_to_g_value(context, rval, return_value)) {
             gjs_debug(GJS_DEBUG_GCLOSURE,
                       "Unable to convert return value when invoking closure");
-            gjs_log_exception(context, NULL);
+            gjs_log_exception(context);
             goto cleanup;
         }
     }
diff --git a/gjs/context.c b/gjs/context.c
index e39d290..b6dd7dd 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -131,7 +131,7 @@ gjs_log(JSContext *context,
     JS_RestoreExceptionState(context, exc_state);
 
     if (jstr == NULL) {
-        gjs_debug(GJS_DEBUG_LOG, "<cannot convert value to string>");
+        g_message("JS LOG: <cannot convert value to string>");
         JS_EndRequest(context);
         return JS_TRUE;
     }
@@ -141,7 +141,7 @@ gjs_log(JSContext *context,
         return JS_FALSE;
     }
 
-    gjs_debug(GJS_DEBUG_LOG, "%s", s);
+    g_message("JS LOG: %s", s);
     g_free(s);
 
     JS_EndRequest(context);
@@ -155,43 +155,29 @@ gjs_log_error(JSContext *context,
               jsval     *vp)
 {
     jsval *argv = JS_ARGV(context, vp);
-    char *s;
     JSExceptionState *exc_state;
     JSString *jstr;
-    jsval exc;
-
-    if (argc != 2) {
-        gjs_throw(context, "Must pass an exception and message string to logError()");
-        return JS_FALSE;
-    }
 
     JS_BeginRequest(context);
 
-    exc = argv[0];
-
-    /* JS_ValueToString might throw, in which we will only
-     *log that the value could be converted to string */
-    exc_state = JS_SaveExceptionState(context);
-    jstr = JS_ValueToString(context, argv[1]);
-    if (jstr != NULL)
-        argv[1] = STRING_TO_JSVAL(jstr);    // GC root
-    JS_RestoreExceptionState(context, exc_state);
-
-    if (jstr == NULL) {
-        gjs_debug(GJS_DEBUG_ERROR, "<cannot convert value to string>");
-        gjs_log_exception_props(context, exc);
-        JS_EndRequest(context);
-        return JS_TRUE;
+    if ((argc != 1 && argc != 2) ||
+        !JSVAL_IS_OBJECT (argv[0])) {
+        gjs_throw(context, "Must pass an exception and optionally a message to logError()");
     }
 
-    if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(jstr), &s)) {
-        JS_EndRequest(context);
-        return JS_FALSE;
+    if (argc == 2) {
+        /* JS_ValueToString might throw, in which we will only
+         *log that the value could be converted to string */
+        exc_state = JS_SaveExceptionState(context);
+        jstr = JS_ValueToString(context, argv[1]);
+        if (jstr != NULL)
+            argv[1] = STRING_TO_JSVAL(jstr);    // GC root
+        JS_RestoreExceptionState(context, exc_state);
+    } else {
+        jstr = NULL;
     }
 
-    gjs_debug(GJS_DEBUG_ERROR, "%s", s);
-    gjs_log_exception_props(context, exc);
-    g_free(s);
+    gjs_log_exception_full(context, argv[0], jstr);
 
     JS_EndRequest(context);
     JS_SET_RVAL(context, vp, JSVAL_VOID);
@@ -568,12 +554,12 @@ gjs_context_constructor (GType                  type,
 
     js_context->runtime = JS_NewRuntime(32*1024*1024 /* max bytes */);
     if (js_context->runtime == NULL)
-        gjs_fatal("Failed to create javascript runtime");
+        g_error("Failed to create javascript runtime");
     JS_SetGCParameter(js_context->runtime, JSGC_MAX_BYTES, 0xffffffff);
 
     js_context->context = JS_NewContext(js_context->runtime, 8192 /* stack chunk size */);
     if (js_context->context == NULL)
-        gjs_fatal("Failed to create javascript context");
+        g_error("Failed to create javascript context");
 
     gjs_runtime_init_for_context(js_context->runtime, js_context->context);
 
@@ -622,39 +608,39 @@ gjs_context_constructor (GType                  type,
     }
 
     if (!gjs_init_context_standard(js_context->context))
-        gjs_fatal("Failed to initialize context");
+        g_error("Failed to initialize context");
     js_context->global = JS_GetGlobalObject(js_context->context);
 
     if (!JS_DefineProperty(js_context->context, js_context->global,
                            "window", OBJECT_TO_JSVAL(js_context->global),
                            NULL, NULL,
                            JSPROP_READONLY | JSPROP_PERMANENT))
-        gjs_fatal("No memory to export global object as 'window'");
+        g_error("No memory to export global object as 'window'");
 
     /* Define a global function called log() */
     if (!JS_DefineFunction(js_context->context, js_context->global,
                            "log",
                            (JSNative)gjs_log,
                            1, GJS_MODULE_PROP_FLAGS))
-        gjs_fatal("Failed to define log function");
+        g_error("Failed to define log function");
 
     if (!JS_DefineFunction(js_context->context, js_context->global,
                            "logError",
                            (JSNative)gjs_log_error,
                            2, GJS_MODULE_PROP_FLAGS))
-        gjs_fatal("Failed to define logError function");
+        g_error("Failed to define logError function");
 
     /* Define global functions called print() and printerr() */
     if (!JS_DefineFunction(js_context->context, js_context->global,
                            "print",
                            (JSNative)gjs_print,
                            3, GJS_MODULE_PROP_FLAGS))
-        gjs_fatal("Failed to define print function");
+        g_error("Failed to define print function");
     if (!JS_DefineFunction(js_context->context, js_context->global,
                            "printerr",
                            (JSNative)gjs_printerr,
                            4, GJS_MODULE_PROP_FLAGS))
-        gjs_fatal("Failed to define printerr function");
+        g_error("Failed to define printerr function");
 
     /* We create the global-to-runtime root importer with the
      * passed-in search path. If someone else already created
@@ -665,14 +651,14 @@ gjs_context_constructor (GType                  type,
                                   (const char**) js_context->search_path :
                                   NULL,
                                   TRUE))
-        gjs_fatal("Failed to create root importer");
+        g_error("Failed to create root importer");
 
     /* Now copy the global root importer (which we just created,
      * if it didn't exist) to our global object
      */
     if (!gjs_define_root_importer(js_context->context,
                                   js_context->global))
-        gjs_fatal("Failed to point 'imports' property at root importer");
+        g_error("Failed to point 'imports' property at root importer");
 
     js_context->profiler = gjs_profiler_new(js_context->runtime);
 
@@ -996,7 +982,7 @@ gjs_context_eval(GjsContext *js_context,
     }
 
     /* log and clear exception if it's set (should not be, normally...) */
-    if (gjs_log_exception(js_context->context, NULL)) {
+    if (gjs_log_exception(js_context->context)) {
         gjs_debug(GJS_DEBUG_CONTEXT,
                   "Exception was set prior to JS_EvaluateScript()");
     }
@@ -1016,29 +1002,14 @@ gjs_context_eval(GjsContext *js_context,
                            filename,
                            line_number,
                            &retval)) {
-        char *message;
-
         gjs_debug(GJS_DEBUG_CONTEXT,
                   "Script evaluation failed");
 
-        /* if message is NULL then somehow exception wasn't set */
-        message = NULL;
-        gjs_log_exception(js_context->context,
-                             &message);
-        if (message) {
-            g_set_error(error,
-                        GJS_ERROR,
-                        GJS_ERROR_FAILED,
-                        "%s", message);
-            g_free(message);
-        } else {
-            gjs_debug(GJS_DEBUG_CONTEXT,
-                      "JS_EvaluateScript() failed but no exception message?");
-            g_set_error(error,
-                        GJS_ERROR,
-                        GJS_ERROR_FAILED,
-                        "JS_EvaluateScript() failed but no exception message?");
-        }
+        gjs_log_exception(js_context->context);
+        g_set_error(error,
+                    GJS_ERROR,
+                    GJS_ERROR_FAILED,
+                    "JS_EvaluateScript() failed");
 
         success = FALSE;
     }
@@ -1046,7 +1017,7 @@ gjs_context_eval(GjsContext *js_context,
     gjs_debug(GJS_DEBUG_CONTEXT,
               "Script evaluation succeeded");
 
-    if (gjs_log_exception(js_context->context, NULL)) {
+    if (gjs_log_exception(js_context->context)) {
         g_set_error(error,
                     GJS_ERROR,
                     GJS_ERROR_FAILED,
@@ -1109,24 +1080,11 @@ gjs_context_define_string_array(GjsContext  *js_context,
                                  js_context->global,
                                  array_name, array_length, array_values,
                                  JSPROP_READONLY | JSPROP_PERMANENT)) {
-        char *message;
-
-        message = NULL;
-        gjs_log_exception(js_context->context, &message);
-        if (message) {
-            g_set_error(error,
-                        GJS_ERROR,
-                        GJS_ERROR_FAILED,
-                        "%s", message);
-            g_free(message);
-        } else {
-            message = "gjs_define_string_array() failed but no exception message?";
-            gjs_debug(GJS_DEBUG_CONTEXT, "%s", message);
-            g_set_error(error,
-                        GJS_ERROR,
-                        GJS_ERROR_FAILED,
-                        "%s", message);
-        }
+        gjs_log_exception(js_context->context);
+        g_set_error(error,
+                    GJS_ERROR,
+                    GJS_ERROR_FAILED,
+                    "gjs_define_string_array() failed");
         return FALSE;
     }
 
diff --git a/gjs/importer.c b/gjs/importer.c
index 45034e1..6ee5a0d 100644
--- a/gjs/importer.c
+++ b/gjs/importer.c
@@ -350,7 +350,7 @@ load_module_init(JSContext  *context,
         if (JS_IsExceptionPending(context)) {
             gjs_debug(GJS_DEBUG_IMPORTER,
                       "Module " MODULE_INIT_FILENAME " left an exception set");
-            gjs_log_and_keep_exception(context, NULL);
+            gjs_log_and_keep_exception(context);
         } else {
             gjs_throw(context,
                       "JS_EvaluateScript() returned FALSE but did not set exception");
@@ -464,7 +464,7 @@ import_file(JSContext  *context,
             gjs_debug(GJS_DEBUG_IMPORTER,
                       "Module '%s' left an exception set",
                       name);
-            gjs_log_and_keep_exception(context, NULL);
+            gjs_log_and_keep_exception(context);
         } else {
             gjs_throw(context,
                          "JS_EvaluateScript() returned FALSE but did not set exception");
@@ -1023,7 +1023,8 @@ importer_new(JSContext    *context)
     global = gjs_get_import_global(context);
 
     if (!JS_HasProperty(context, global, gjs_importer_class.name, &found))
-        gjs_fatal("HasProperty call failed creating importer class");
+        g_error("HasProperty call failed creating importer class");
+
     if (!found) {
         JSObject *prototype;
         prototype = JS_InitClass(context, global,
@@ -1049,7 +1050,7 @@ importer_new(JSContext    *context)
                                  /* funcs of constructor, MyConstructor.myfunc() */
                                  NULL);
         if (prototype == NULL)
-            gjs_fatal("Can't init class %s", gjs_importer_class.name);
+            g_error("Can't init class %s", gjs_importer_class.name);
 
         gjs_debug(GJS_DEBUG_IMPORTER, "Initialized class %s prototype %p",
                   gjs_importer_class.name, prototype);
@@ -1057,7 +1058,7 @@ importer_new(JSContext    *context)
 
     importer = JS_NewObject(context, &gjs_importer_class, NULL, global);
     if (importer == NULL)
-        gjs_fatal("No memory to create importer importer");
+        g_error("No memory to create importer importer");
 
     priv = g_slice_new0(Importer);
 
@@ -1152,12 +1153,12 @@ gjs_create_importer(JSContext    *context,
                                  "searchPath", -1, (const char **)search_path,
                                  /* settable (no READONLY) but not deleteable (PERMANENT) */
                                  JSPROP_PERMANENT | JSPROP_ENUMERATE))
-        gjs_fatal("no memory to define importer search path prop");
+        g_error("no memory to define importer search path prop");
 
     g_strfreev(search_path);
 
     if (!define_meta_properties(context, importer, NULL, importer_name, in_object))
-        gjs_fatal("failed to define meta properties on importer");
+        g_error("failed to define meta properties on importer");
 
     return importer;
 }
@@ -1178,7 +1179,7 @@ gjs_define_importer(JSContext    *context,
                            importer_name, OBJECT_TO_JSVAL(importer),
                            NULL, NULL,
                            GJS_MODULE_PROP_FLAGS))
-        gjs_fatal("no memory to define importer property");
+        g_error("no memory to define importer property");
 
     gjs_debug(GJS_DEBUG_IMPORTER,
               "Defined importer '%s' %p in %p", importer_name, importer, in_object);
diff --git a/gjs/jsapi-private.cpp b/gjs/jsapi-private.cpp
index 5f39053..9950ecd 100644
--- a/gjs/jsapi-private.cpp
+++ b/gjs/jsapi-private.cpp
@@ -44,6 +44,7 @@ gjs_error_reporter(JSContext     *context,
                    JSErrorReport *report)
 {
     const char *warning;
+    GLogLevelFlags level;
 
     if (gjs_environment_variable_is_set("GJS_ABORT_ON_OOM") &&
         report->flags == JSREPORT_ERROR &&
@@ -54,11 +55,8 @@ gjs_error_reporter(JSContext     *context,
     }
 
     if ((report->flags & JSREPORT_WARNING) != 0) {
-        /* We manually insert "WARNING" into the output instead of
-         * having GJS_DEBUG_WARNING because it's convenient to
-         * search for 'JS ERROR' to find all problems
-         */
-        warning = "WARNING: ";
+        warning = "WARNING";
+        level = G_LOG_LEVEL_MESSAGE;
 
         /* suppress bogus warnings. See mozilla/js/src/js.msg */
         switch (report->errorNumber) {
@@ -71,18 +69,9 @@ gjs_error_reporter(JSContext     *context,
             return;
         }
     } else {
-        warning = "REPORTED: ";
+        warning = "REPORTED";
+        level = G_LOG_LEVEL_WARNING;
     }
 
-    gjs_debug(GJS_DEBUG_ERROR,
-              "%s'%s'",
-              warning,
-              message);
-
-    gjs_debug(GJS_DEBUG_ERROR,
-              "%sfile '%s' line %u exception %d number %d",
-              warning,
-              report->filename, report->lineno,
-              (report->flags & JSREPORT_EXCEPTION) != 0,
-              report->errorNumber);
+    g_log(G_LOG_DOMAIN, level, "JS %s: [%s %d]: %s", warning, report->filename, report->lineno, message);
 }
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index bc09330..de97ab5 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -363,7 +363,7 @@ gjs_value_debug_string(JSContext      *context,
                     return g_strdup("[out of memory copying class name]");
                 }
             } else {
-                gjs_log_exception(context, NULL);
+                gjs_log_exception(context);
                 JS_EndRequest(context);
                 return g_strdup("[unknown object]");
             }
@@ -410,8 +410,7 @@ gjs_log_object_props(JSContext      *context,
 
     props_iter = JS_NewPropertyIterator(context, obj);
     if (props_iter == NULL) {
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Failed to create property iterator for object props");
+        gjs_log_exception(context);
         goto done;
     }
 
@@ -502,100 +501,70 @@ gjs_explain_scope(JSContext  *context,
     JS_EndRequest(context);
 }
 
-static void
-log_one_exception_property(JSContext  *context,
-                           JSObject   *object,
-                           const char *name)
+JSBool
+gjs_log_exception_full(JSContext *context,
+                       jsval      exc,
+                       JSString  *message)
 {
-    jsval v;
-    char *debugstr;
+    jsval stack;
+    JSString *exc_str;
+    char *utf8_exception, *utf8_message, *utf8_stack;
 
-    if (!JS_GetProperty(context, object, name, &v))
-        return;
+    JS_BeginRequest(context);
 
-    debugstr = gjs_value_debug_string(context, v);
-    gjs_debug(GJS_DEBUG_ERROR, "  %s = '%s'", name, debugstr);
-    g_free(debugstr);
-}
+    exc_str = JS_ValueToString(context, exc);
+    if (exc_str != NULL)
+        gjs_string_to_utf8(context, STRING_TO_JSVAL(exc_str), &utf8_exception);
+    else
+        utf8_exception = NULL;
 
-void
-gjs_log_exception_props(JSContext *context,
-                        jsval      exc)
-{
-    JS_BeginRequest(context);
+    if (message != NULL)
+        gjs_string_to_utf8(context, STRING_TO_JSVAL(message), &utf8_message);
+    else
+        utf8_message = NULL;
 
-    /* This is useful when the exception was never sent to an error reporter
-     * due to JSOPTION_DONT_REPORT_UNCAUGHT, or if the exception was not
-     * a normal Error object so jsapi didn't know how to report it sensibly.
-     */
-    if (JSVAL_IS_NULL(exc)) {
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Exception was null");
-    } else if (JSVAL_IS_OBJECT(exc)) {
-        JSObject *exc_obj;
-
-        exc_obj = JSVAL_TO_OBJECT(exc);
-
-        log_one_exception_property(context, exc_obj, "message");
-        log_one_exception_property(context, exc_obj, "fileName");
-        log_one_exception_property(context, exc_obj, "lineNumber");
-        log_one_exception_property(context, exc_obj, "stack");
-    } else if (JSVAL_IS_STRING(exc)) {
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Exception was a String");
+    if (JSVAL_IS_OBJECT(exc) &&
+        gjs_object_get_property_const(context, JSVAL_TO_OBJECT(exc),
+                                      GJS_STRING_STACK, &stack))
+        gjs_string_to_utf8(context, stack, &utf8_stack);
+    else
+        utf8_stack = NULL;
+
+    if (utf8_message) {
+        if (utf8_stack)
+            g_warning("JS ERROR: %s: %s\n%s", utf8_message, utf8_exception, utf8_stack);
+        else
+            g_warning("JS ERROR: %s: %s", utf8_message, utf8_exception);
     } else {
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Exception had some strange type");
+        if (utf8_stack)
+            g_warning("JS ERROR: %s\n%s", utf8_exception, utf8_stack);
+        else
+            g_warning("JS ERROR: %s", utf8_exception);
     }
-    JS_EndRequest(context);
+
+    g_free(utf8_exception);
+    g_free(utf8_message);
+    g_free(utf8_stack);
+
+    return JS_TRUE;
 }
 
 static JSBool
 log_and_maybe_keep_exception(JSContext  *context,
-                             char      **message_p,
                              gboolean    keep)
 {
     jsval exc = JSVAL_VOID;
-    JSString *s;
-    char *message;
     JSBool retval = JS_FALSE;
 
     JS_BeginRequest(context);
 
-    if (message_p)
-        *message_p = NULL;
-
     JS_AddValueRoot(context, &exc);
     if (!JS_GetPendingException(context, &exc))
         goto out;
 
     JS_ClearPendingException(context);
 
-    s = JS_ValueToString(context, exc);
-
-    if (s == NULL) {
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Failed to convert exception to string");
-        goto out; /* Exception should be thrown already */
-    }
-
-    if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(s), &message)) {
-        gjs_debug(GJS_DEBUG_ERROR,
-                  "Failed to convert exception string to UTF-8");
-        goto out; /* Error already set */
-    }
-
-    gjs_debug(GJS_DEBUG_ERROR,
-              "Exception was: %s",
-              message);
-
-    if (message_p) {
-        *message_p = message;
-    } else {
-        g_free(message);
-    }
-
-    gjs_log_exception_props(context, exc);
+    gjs_log_exception_full(context, exc, NULL);
 
     /* We clear above and then set it back so any exceptions
      * from the logging process don't overwrite the original
@@ -614,17 +583,15 @@ log_and_maybe_keep_exception(JSContext  *context,
 }
 
 JSBool
-gjs_log_exception(JSContext  *context,
-                  char      **message_p)
+gjs_log_exception(JSContext  *context)
 {
-    return log_and_maybe_keep_exception(context, message_p, FALSE);
+    return log_and_maybe_keep_exception(context, FALSE);
 }
 
 JSBool
-gjs_log_and_keep_exception(JSContext *context,
-                           char     **message_p)
+gjs_log_and_keep_exception(JSContext *context)
 {
-    return log_and_maybe_keep_exception(context, message_p, TRUE);
+    return log_and_maybe_keep_exception(context, TRUE);
 }
 
 static void
@@ -827,13 +794,13 @@ gjs_date_from_time_t (JSContext *context, time_t time)
 
     if (!JS_GetClassObject(context, JS_GetGlobalObject(context), JSProto_Date,
                            &date_constructor))
-        gjs_fatal("Failed to lookup Date prototype");
+        g_error("Failed to lookup Date prototype");
 
     if (!JS_GetProperty(context, date_constructor, "prototype", &date_prototype))
-        gjs_fatal("Failed to get prototype from Date constructor");
+        g_error("Failed to get prototype from Date constructor");
 
     if (!JS_NewNumberValue(context, ((double) time) * 1000, &(args[0])))
-        gjs_fatal("Failed to convert time_t to number");
+        g_error("Failed to convert time_t to number");
 
     date = JS_New(context, JSVAL_TO_OBJECT (date_prototype), 1, args);
 
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 1e8aea6..6fe1df0 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -255,14 +255,15 @@ void        gjs_throw_literal                (JSContext       *context,
                                               const char      *string);
 void        gjs_throw_g_error                (JSContext       *context,
                                               GError          *error);
-JSBool      gjs_log_exception                (JSContext       *context,
-                                              char           **message_p);
-JSBool      gjs_log_and_keep_exception       (JSContext       *context,
-                                              char           **message_p);
+
+JSBool      gjs_log_exception                (JSContext       *context);
+JSBool      gjs_log_and_keep_exception       (JSContext       *context);
 JSBool      gjs_move_exception               (JSContext       *src_context,
                                               JSContext       *dest_context);
-void        gjs_log_exception_props          (JSContext       *context,
-                                              jsval            exc);
+JSBool      gjs_log_exception_full           (JSContext       *context,
+                                              jsval            exc,
+                                              JSString        *message);
+
 #ifdef __GJS_UTIL_LOG_H__
 void        gjs_log_object_props             (JSContext       *context,
                                               JSObject        *obj,
diff --git a/installed-tests/test/js/testSignals.js b/installed-tests/test/js/testSignals.js
index e0f4c83..cf41b12 100644
--- a/installed-tests/test/js/testSignals.js
+++ b/installed-tests/test/js/testSignals.js
@@ -1,5 +1,7 @@
 // application/javascript;version=1.8
 const JSUnit = imports.jsUnit;
+const GLib = imports.gi.GLib;
+
 const Signals = imports.signals;
 
 function Foo() {
@@ -120,11 +122,15 @@ function testExceptionInCallback() {
                 });
 
     // exception in callback does not effect other callbacks
+    GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+                             'JS ERROR: Exception in callback for signal: *');
     foo.emit('bar');
     JSUnit.assertEquals(1, foo.bar1Called);
     JSUnit.assertEquals(1, foo.bar2Called);
 
     // exception in callback does not disconnect the callback
+    GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+                             'JS ERROR: Exception in callback for signal: *');
     foo.emit('bar');
     JSUnit.assertEquals(2, foo.bar1Called);
     JSUnit.assertEquals(2, foo.bar2Called);
diff --git a/util/log.c b/util/log.c
index 1475d25..c2e3220 100644
--- a/util/log.c
+++ b/util/log.c
@@ -33,30 +33,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-void
-gjs_fatal(const char *format, ...)
-{
-    va_list args;
-    char *s;
-
-    va_start (args, format);
-    s = g_strdup_vprintf (format, args);
-    va_end (args);
-
-    fputs(s, stderr);
-
-    if (!g_str_has_suffix(s, "\n"))
-        fputs("\n", stderr);
-    fputs("\n", stderr);
-
-    fflush(stderr);
-
-    g_free(s);
-
-    abort();
-    exit(1); /* not reached unless there's some weird SIGABRT handler */
-}
-
 /* prefix is allowed if it's in the ;-delimited environment variable
  * GJS_DEBUG_TOPICS or if that variable is not set.
  */
@@ -95,14 +71,13 @@ is_allowed_prefix (const char *prefix)
 
 static void
 write_to_stream(FILE       *logfp,
-                gboolean    error,
                 const char *prefix,
                 const char *s)
 {
     /* seek to end to avoid truncating in case we're using shared logfile */
     (void)fseek(logfp, 0, SEEK_END);
 
-    fprintf(logfp, "%*s: %s%s", PREFIX_LENGTH, prefix, error ? "!!!   " : "", s);
+    fprintf(logfp, "%*s: %s", PREFIX_LENGTH, prefix, s);
     if (!g_str_has_suffix(s, "\n"))
         fputs("\n", logfp);
     fflush(logfp);
@@ -122,7 +97,6 @@ gjs_debug(GjsDebugTopic topic,
     const char *prefix;
     va_list args;
     char *s;
-    gboolean error;
 
     if (!checked_for_timestamp) {
         print_timestamp = gjs_environment_variable_is_set("GJS_DEBUG_TIMESTAMP");
@@ -175,15 +149,13 @@ gjs_debug(GjsDebugTopic topic,
         strace_timestamps = gjs_environment_variable_is_set("GJS_STRACE_TIMESTAMPS");
     }
 
-    /* only log errors and strace timestamps if debug
+    /* only strace timestamps if debug
      * log wasn't specifically switched on
      */
-    if ((!debug_log_enabled) &&
-        !(topic == GJS_DEBUG_ERROR ||
-          topic == GJS_DEBUG_STRACE_TIMESTAMP))
+    if (!debug_log_enabled &&
+        topic != GJS_DEBUG_STRACE_TIMESTAMP)
         return;
 
-    error = FALSE;
     switch (topic) {
     case GJS_DEBUG_STRACE_TIMESTAMP:
         /* return early if strace timestamps are disabled, avoiding
@@ -200,16 +172,9 @@ gjs_debug(GjsDebugTopic topic,
     case GJS_DEBUG_GI_USAGE:
         prefix = "JS GI USE";
         break;
-    case GJS_DEBUG_ERROR:
-        prefix = "JS ERROR";
-        error = TRUE;
-        break;
     case GJS_DEBUG_MEMORY:
         prefix = "JS MEMORY";
         break;
-    case GJS_DEBUG_LOG:
-        prefix = "JS LOG";
-        break;
     case GJS_DEBUG_CONTEXT:
         prefix = "JS CTX";
         break;
@@ -318,13 +283,7 @@ gjs_debug(GjsDebugTopic topic,
             previous = total;
         }
 
-        /* write to both stderr and logfile
-         * if it's an error
-         */
-        if (error && logfp != stderr)
-            write_to_stream(stderr, error, prefix, s);
-
-        write_to_stream(logfp, error, prefix, s);
+        write_to_stream(logfp, prefix, s);
     }
 
     g_free(s);
diff --git a/util/log.h b/util/log.h
index 05937fb..83f0338 100644
--- a/util/log.h
+++ b/util/log.h
@@ -36,9 +36,7 @@ G_BEGIN_DECLS
 typedef enum {
     GJS_DEBUG_STRACE_TIMESTAMP,
     GJS_DEBUG_GI_USAGE,
-    GJS_DEBUG_ERROR,
     GJS_DEBUG_MEMORY,
-    GJS_DEBUG_LOG,
     GJS_DEBUG_CONTEXT,
     GJS_DEBUG_IMPORTER,
     GJS_DEBUG_NATIVE,
@@ -153,9 +151,6 @@ typedef enum {
 #define gjs_debug_gsignal(format...)
 #endif
 
-void gjs_fatal(const char *format,
-               ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN;
-
 void gjs_debug(GjsDebugTopic topic,
                const char   *format,
                ...) G_GNUC_PRINTF (2, 3);



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