216 lines
6.2 KiB
Diff
216 lines
6.2 KiB
Diff
commit 52593563c9e9873231f5fdae3dc1668460bee37e
|
|
Author: Colin Walters <walters@verbum.org>
|
|
Date: Wed Dec 1 17:11:16 2010 -0500
|
|
|
|
gjs_value_debug_string: Always return UTF-8
|
|
|
|
Returning whatever JS_GetStringBytes gave us will blow up if
|
|
the string contains non-UTF8 characters and we're trying to g_print
|
|
to a UTF-8 terminal (the standard case). Since this is just a
|
|
debugging string, import a copy of _g_utf8_make_valid which
|
|
squashes it to UTF-8 in a useful way.
|
|
|
|
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
|
|
index 11c890a..714b91e 100644
|
|
--- a/gjs/jsapi-util.c
|
|
+++ b/gjs/jsapi-util.c
|
|
@@ -755,12 +755,20 @@ gjs_define_string_array(JSContext *context,
|
|
return array;
|
|
}
|
|
|
|
-const char*
|
|
+/**
|
|
+ * gjs_value_debug_string:
|
|
+ * @context:
|
|
+ * @value: Any JavaScript value
|
|
+ *
|
|
+ * Returns: A UTF-8 encoded string describing @value
|
|
+ */
|
|
+char*
|
|
gjs_value_debug_string(JSContext *context,
|
|
jsval value)
|
|
{
|
|
JSString *str;
|
|
const char *bytes;
|
|
+ char *debugstr;
|
|
|
|
JS_BeginRequest(context);
|
|
|
|
@@ -778,14 +786,14 @@ gjs_value_debug_string(JSContext *context,
|
|
str = JS_NewStringCopyZ(context, klass->name);
|
|
JS_ClearPendingException(context);
|
|
if (str == NULL) {
|
|
- return "[out of memory copying class name]";
|
|
+ return g_strdup("[out of memory copying class name]");
|
|
}
|
|
} else {
|
|
gjs_log_exception(context, NULL);
|
|
- return "[unknown object]";
|
|
+ return g_strdup("[unknown object]");
|
|
}
|
|
} else {
|
|
- return "[unknown non-object]";
|
|
+ return g_strdup("[unknown non-object]");
|
|
}
|
|
}
|
|
|
|
@@ -795,7 +803,9 @@ gjs_value_debug_string(JSContext *context,
|
|
|
|
JS_EndRequest(context);
|
|
|
|
- return bytes;
|
|
+ debugstr = _gjs_g_utf8_make_valid(bytes);
|
|
+
|
|
+ return debugstr;
|
|
}
|
|
|
|
void
|
|
@@ -829,6 +839,7 @@ gjs_log_object_props(JSContext *context,
|
|
while (!JSID_IS_VOID(prop_id)) {
|
|
jsval propval;
|
|
const char *name;
|
|
+ char *debugstr;
|
|
|
|
if (!gjs_get_string_id(context, prop_id, &name))
|
|
goto next;
|
|
@@ -836,10 +847,12 @@ gjs_log_object_props(JSContext *context,
|
|
if (!gjs_object_get_property(context, obj, name, &propval))
|
|
goto next;
|
|
|
|
+ debugstr = gjs_value_debug_string(context, propval);
|
|
gjs_debug(topic,
|
|
"%s%s = '%s'",
|
|
prefix, name,
|
|
- gjs_value_debug_string(context, propval));
|
|
+ debugstr);
|
|
+ g_free(debugstr);
|
|
|
|
next:
|
|
prop_id = JSID_VOID;
|
|
@@ -859,6 +872,7 @@ gjs_explain_scope(JSContext *context,
|
|
JSObject *global;
|
|
JSObject *parent;
|
|
GString *chain;
|
|
+ char *debugstr;
|
|
|
|
gjs_debug(GJS_DEBUG_SCOPE,
|
|
"=== %s ===",
|
|
@@ -874,14 +888,16 @@ gjs_explain_scope(JSContext *context,
|
|
"");
|
|
|
|
global = JS_GetGlobalObject(context);
|
|
+ debugstr = gjs_value_debug_string(context, OBJECT_TO_JSVAL(global));
|
|
gjs_debug(GJS_DEBUG_SCOPE,
|
|
" Global: %p %s",
|
|
- global, gjs_value_debug_string(context, OBJECT_TO_JSVAL(global)));
|
|
+ global, debugstr);
|
|
+ g_free(debugstr);
|
|
|
|
parent = JS_GetScopeChain(context);
|
|
chain = g_string_new(NULL);
|
|
while (parent != NULL) {
|
|
- const char *debug;
|
|
+ char *debug;
|
|
debug = gjs_value_debug_string(context, OBJECT_TO_JSVAL(parent));
|
|
|
|
if (chain->len > 0)
|
|
@@ -889,6 +905,7 @@ gjs_explain_scope(JSContext *context,
|
|
|
|
g_string_append_printf(chain, "%p %s",
|
|
parent, debug);
|
|
+ g_free(debug);
|
|
parent = JS_GetParent(context, parent);
|
|
}
|
|
gjs_debug(GJS_DEBUG_SCOPE,
|
|
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
|
|
index 424cded..b7c6a8b 100644
|
|
--- a/gjs/jsapi-util.h
|
|
+++ b/gjs/jsapi-util.h
|
|
@@ -267,7 +267,7 @@ void gjs_log_object_props (JSContext *context,
|
|
GjsDebugTopic topic,
|
|
const char *prefix);
|
|
#endif
|
|
-const char* gjs_value_debug_string (JSContext *context,
|
|
+char* gjs_value_debug_string (JSContext *context,
|
|
jsval value);
|
|
void gjs_explain_scope (JSContext *context,
|
|
const char *title);
|
|
diff --git a/util/glib.c b/util/glib.c
|
|
index 316e6e0..b79e75f 100644
|
|
--- a/util/glib.c
|
|
+++ b/util/glib.c
|
|
@@ -21,10 +21,12 @@
|
|
* IN THE SOFTWARE.
|
|
*/
|
|
|
|
-#include <config.h>
|
|
+#include <string.h>
|
|
|
|
#include "glib.h"
|
|
|
|
+#include <config.h>
|
|
+
|
|
typedef struct {
|
|
void *key;
|
|
void *value;
|
|
@@ -125,6 +127,46 @@ gjs_g_strv_concat(char ***strv_array, int len)
|
|
return (char**)g_ptr_array_free(array, FALSE);
|
|
}
|
|
|
|
+gchar *
|
|
+_gjs_g_utf8_make_valid (const gchar *name)
|
|
+{
|
|
+ GString *string;
|
|
+ const gchar *remainder, *invalid;
|
|
+ gint remaining_bytes, valid_bytes;
|
|
+
|
|
+ g_return_val_if_fail (name != NULL, NULL);
|
|
+
|
|
+ string = NULL;
|
|
+ remainder = name;
|
|
+ remaining_bytes = strlen (name);
|
|
+
|
|
+ while (remaining_bytes != 0)
|
|
+ {
|
|
+ if (g_utf8_validate (remainder, remaining_bytes, &invalid))
|
|
+ break;
|
|
+ valid_bytes = invalid - remainder;
|
|
+
|
|
+ if (string == NULL)
|
|
+ string = g_string_sized_new (remaining_bytes);
|
|
+
|
|
+ g_string_append_len (string, remainder, valid_bytes);
|
|
+ /* append U+FFFD REPLACEMENT CHARACTER */
|
|
+ g_string_append (string, "\357\277\275");
|
|
+
|
|
+ remaining_bytes -= valid_bytes + 1;
|
|
+ remainder = invalid + 1;
|
|
+ }
|
|
+
|
|
+ if (string == NULL)
|
|
+ return g_strdup (name);
|
|
+
|
|
+ g_string_append (string, remainder);
|
|
+
|
|
+ g_assert (g_utf8_validate (string->str, -1, NULL));
|
|
+
|
|
+ return g_string_free (string, FALSE);
|
|
+}
|
|
+
|
|
#if GJS_BUILD_TESTS
|
|
|
|
void
|
|
diff --git a/util/glib.h b/util/glib.h
|
|
index 7bdc01a..5be171f 100644
|
|
--- a/util/glib.h
|
|
+++ b/util/glib.h
|
|
@@ -28,6 +28,8 @@
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
+gchar * _gjs_g_utf8_make_valid (const gchar *name);
|
|
+
|
|
gboolean gjs_g_hash_table_remove_one (GHashTable *hash,
|
|
void **key_p,
|
|
void **value_p);
|