[gjs] Call JS_SetLocaleCallbacks()
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Subject: [gjs] Call JS_SetLocaleCallbacks()
- Date: Tue, 5 May 2009 16:24:58 -0400 (EDT)
commit c1dd7fcfbda1c69e59eecdca4e22b775244edb26
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Thu Apr 30 16:33:51 2009 -0400
Call JS_SetLocaleCallbacks()
SpiderMonkey doesn't implement locale handling for functions
like String.toLocaleLowerCase itself; it depends on a set of
"callbacks" being set on the context.
gjs/context.c: Implement locale callbacks in terms of GLib
js/testLocale.js: tests for locale handling
http://bugzilla.gnome.org/show_bug.cgi?id=580865
---
Makefile-test.am | 1 +
gjs/context.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++
test/js/testLocale.js | 44 ++++++++++++++++++
3 files changed, 163 insertions(+), 0 deletions(-)
diff --git a/Makefile-test.am b/Makefile-test.am
index 66495f6..141046b 100644
--- a/Makefile-test.am
+++ b/Makefile-test.am
@@ -112,6 +112,7 @@ EXTRA_DIST += \
test/js/testGI.js \
test/js/testImporter.js \
test/js/testLang.js \
+ test/js/testLocale.js \
test/js/testMainloop.js \
test/js/testSignals.js \
test/js/testTweener.js
diff --git a/gjs/context.c b/gjs/context.c
index 5e500b0..ec7013a 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -304,6 +304,122 @@ gjs_context_finalize(GObject *object)
G_OBJECT_CLASS(gjs_context_parent_class)->finalize(object);
}
+/* Implementations of locale-specific operations; these are used
+ * in the implementation of String.localeCompare(), Date.toLocaleDateString(),
+ * and so forth. We take the straight-forward approach of converting
+ * to UTF-8, using the appropriate GLib functions, and converting
+ * back if necessary.
+ */
+static JSBool
+gjs_locale_to_upper_case (JSContext *context,
+ JSString *src,
+ jsval *retval)
+{
+ JSBool success = JS_FALSE;
+ char *utf8 = NULL;
+ char *upper_case_utf8 = NULL;
+
+ if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src), &utf8))
+ goto out;
+
+ upper_case_utf8 = g_utf8_strup (utf8, -1);
+
+ if (!gjs_string_from_utf8(context, upper_case_utf8, -1, retval))
+ goto out;
+
+ success = JS_TRUE;
+
+out:
+ g_free(utf8);
+ g_free(upper_case_utf8);
+
+ return success;
+}
+
+static JSBool
+gjs_locale_to_lower_case (JSContext *context,
+ JSString *src,
+ jsval *retval)
+{
+ JSBool success = JS_FALSE;
+ char *utf8 = NULL;
+ char *lower_case_utf8 = NULL;
+
+ if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src), &utf8))
+ goto out;
+
+ lower_case_utf8 = g_utf8_strdown (utf8, -1);
+
+ if (!gjs_string_from_utf8(context, lower_case_utf8, -1, retval))
+ goto out;
+
+ success = JS_TRUE;
+
+out:
+ g_free(utf8);
+ g_free(lower_case_utf8);
+
+ return success;
+}
+
+static JSBool
+gjs_locale_compare (JSContext *context,
+ JSString *src_1,
+ JSString *src_2,
+ jsval *retval)
+{
+ JSBool success = JS_FALSE;
+ char *utf8_1 = NULL, *utf8_2 = NULL;
+ int result;
+
+ if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(src_1), &utf8_1) ||
+ !gjs_string_to_utf8(context, STRING_TO_JSVAL(src_2), &utf8_2))
+ goto out;
+
+ result = g_utf8_collate (utf8_1, utf8_2);
+ *retval = INT_TO_JSVAL(result);
+
+ success = JS_TRUE;
+
+out:
+ g_free(utf8_1);
+ g_free(utf8_2);
+
+ return success;
+}
+
+static JSBool
+gjs_locale_to_unicode (JSContext *context,
+ char *src,
+ jsval *retval)
+{
+ JSBool success;
+ char *utf8;
+ GError *error = NULL;
+
+ utf8 = g_locale_to_utf8(src, -1, NULL, NULL, &error);
+ if (!utf8) {
+ gjs_throw(context,
+ "Failed to convert locale string to UTF8: %s",
+ error->message);
+ g_error_free(error);
+ return JS_FALSE;
+ }
+
+ success = gjs_string_from_utf8(context, utf8, -1, retval);
+ g_free (utf8);
+
+ return success;
+}
+
+static JSLocaleCallbacks gjs_locale_callbacks =
+{
+ gjs_locale_to_upper_case,
+ gjs_locale_to_lower_case,
+ gjs_locale_compare,
+ gjs_locale_to_unicode
+};
+
static GObject*
gjs_context_constructor (GType type,
guint n_construct_properties,
@@ -345,6 +461,8 @@ gjs_context_constructor (GType type,
JSOPTION_DONT_REPORT_UNCAUGHT |
JSOPTION_STRICT);
+ JS_SetLocaleCallbacks(js_context->context, &gjs_locale_callbacks);
+
JS_SetErrorReporter(js_context->context, gjs_error_reporter);
/* set ourselves as the private data */
diff --git a/test/js/testLocale.js b/test/js/testLocale.js
new file mode 100644
index 0000000..1984efe
--- /dev/null
+++ b/test/js/testLocale.js
@@ -0,0 +1,44 @@
+// tests for JS_SetLocaleCallbacks().
+
+function testToLocaleDateString() {
+ let date = new Date();
+ // %A is the weekday name, this tests locale_to_unicode
+ // we're basically just testing for a non-crash, since
+ // we'd have to run in a specific locale to have any
+ // idea about the result.
+ date.toLocaleDateString("%A");
+}
+
+function testToLocaleLowerCase() {
+ assertEquals("aaa", "AAA".toLocaleLowerCase());
+
+ // String conversion is implemented internally to GLib,
+ // and is more-or-less independent of locale. (A few
+ // characters are handled specially for a few locales,
+ // like i in Turkish. But not A WITH ACUTE)
+ assertEquals("\u00e1", "\u00c1".toLocaleLowerCase());
+
+ // Unpaired surrogate, can't be converted to UTF-8
+ assertRaises(function() { "\ud800".toLocaleLowerCase(); });
+}
+
+function testToLocaleUpperCase() {
+ assertEquals("AAA", "aaa".toLocaleUpperCase());
+ assertEquals("\u00c1", "\u00e1".toLocaleUpperCase());
+ assertRaises(function() { "\ud800".toLocaleUpperCase(); });
+}
+
+function testToLocaleCompare() {
+ // GLib calls out to libc for collation, so we can't really
+ // assume anything - we could even be running in the
+ // C locale. The below is pretty safe.
+ assertEquals(-1, "a".localeCompare("b"));
+ assertEquals( 0, "a".localeCompare("a"));
+ assertEquals( 1, "b".localeCompare("a"));
+
+ // Again test error handling when conversion fails
+ assertRaises(function() { "\ud800".localeCompare("a"); });
+ assertRaises(function() { "a".localeCompare("\ud800"); });
+}
+
+gjstestRun();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]