]> spindle.queued.net Git - midori/commitdiff
Provide a javascript style Gtk.binding and add g_return_if_fail
authorChristian Dywan <christian@twotoasts.de>
Wed, 7 May 2008 01:05:22 +0000 (03:05 +0200)
committerChristian Dywan <christian@twotoasts.de>
Wed, 7 May 2008 01:05:22 +0000 (03:05 +0200)
src/gjs.c
src/gjs.h
src/main.c

index f7e2320e86d0d4f606851d31f248d6bb723502c3..36dd45a762edaa157b7a3c62d274671a78a2d9ee 100644 (file)
--- a/src/gjs.c
+++ b/src/gjs.c
@@ -11,6 +11,7 @@
 
 #include "gjs.h"
 
+#include <gmodule.h>
 #include <glib/gi18n.h>
 
 #define G_OBJECT_NAME(object) G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object))
@@ -21,6 +22,9 @@ gjs_script_eval (JSContextRef js_context,
                  const gchar* script,
                  gchar**      exception)
 {
+    g_return_val_if_fail (js_context, FALSE);
+    g_return_val_if_fail (script, FALSE);
+
     JSStringRef js_script = JSStringCreateWithUTF8CString (script);
     JSValueRef js_exception = NULL;
     JSValueRef js_value = JSEvaluateScript (js_context, js_script,
@@ -42,6 +46,9 @@ gjs_script_check_syntax (JSContextRef js_context,
                          const gchar* script,
                          gchar**      exception)
 {
+    g_return_val_if_fail (js_context, FALSE);
+    g_return_val_if_fail (script, FALSE);
+
     JSStringRef js_script = JSStringCreateWithUTF8CString (script);
     JSValueRef js_exception = NULL;
     bool result = JSCheckScriptSyntax (js_context, js_script, NULL,
@@ -62,6 +69,9 @@ gjs_script_from_file (JSContextRef js_context,
                       const gchar* filename,
                       gchar**      exception)
 {
+    g_return_val_if_fail (js_context, FALSE);
+    g_return_val_if_fail (filename, FALSE);
+
     gboolean result = FALSE;
     gchar* script;
     GError* error = NULL;
@@ -71,7 +81,7 @@ gjs_script_from_file (JSContextRef js_context,
             result = TRUE;
         g_free (script);
     }
-    else
+    else if (error)
     {
         *exception = g_strdup (error->message);
         g_error_free (error);
@@ -145,108 +155,76 @@ _js_object_set_property (JSContextRef js_context,
     JSStringRelease (js_name);
 }
 
-static JSObjectRef
-_js_object_call_as_constructor_cb (JSContextRef     js_context,
-                                   JSObjectRef      js_object,
-                                   size_t           n_arguments,
-                                   const JSValueRef js_arguments[],
-                                   JSValueRef*      js_exception)
-{
-    gchar* type_name = JSObjectGetPrivate (js_object);
-    if (type_name)
-    {
-        GType type = g_type_from_name (type_name);
-        if (type)
-            return gjs_object_new (js_context, g_object_new (type, NULL));
-    }
-    return JSValueMakeNull (js_context);
-}
-
 static JSValueRef
 _js_class_get_property_cb (JSContextRef js_context,
                            JSObjectRef  js_object,
                            JSStringRef  js_property,
                            JSValueRef*  js_exception)
 {
-    if (js_object == JSContextGetGlobalObject (js_context))
+    GObject* object = JSObjectGetPrivate (js_object);
+
+    g_return_val_if_fail (object, JSValueMakeNull (js_context));
+
+    JSValueRef js_result = NULL;
+    gchar* property = gjs_string_utf8 (js_property);
+    GParamSpec* pspec = g_object_class_find_property (
+        G_OBJECT_GET_CLASS (object), property);
+    if (!pspec)
     {
-        gchar* property = gjs_string_utf8 (js_property);
-        GType type = g_type_from_name (property);
-        if (type)
-        {
-            JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
-            js_class_def.className = g_strdup (property);
-            js_class_def.callAsConstructor = _js_object_call_as_constructor_cb;
-            JSClassRef js_class = JSClassCreate (&js_class_def);
-            return JSObjectMake (js_context, js_class, property);
-        }
+        gchar* message = g_strdup_printf (_("%s has no property '%s'"),
+            G_OBJECT_NAME (object), property);
+        JSStringRef js_message = JSStringCreateWithUTF8CString (message);
+        *js_exception = JSValueMakeString (js_context, js_message);
+        JSStringRelease (js_message);
+        g_free (message);
         g_free (property);
         return JSValueMakeNull (js_context);
     }
-    GObject* object = JSObjectGetPrivate (js_object);
-    JSValueRef js_result = NULL;
-    if (object)
+    if (!(pspec->flags & G_PARAM_READABLE))
     {
-        gchar* property = gjs_string_utf8 (js_property);
-        GParamSpec* pspec = g_object_class_find_property (
-            G_OBJECT_GET_CLASS (object), property);
-        if (!pspec)
-        {
-            gchar* message = g_strdup_printf (_("%s has no property '%s'"),
-                G_OBJECT_NAME (object), property);
-            JSStringRef js_message = JSStringCreateWithUTF8CString (message);
-            *js_exception = JSValueMakeString (js_context, js_message);
-            JSStringRelease (js_message);
-            g_free (message);
-            g_free (property);
-            return JSValueMakeNull (js_context);
-        }
-        if (!(pspec->flags & G_PARAM_READABLE))
-        {
-            g_free (property);
-            return JSValueMakeUndefined (js_context);
-        }
-        GType type = G_PARAM_SPEC_TYPE (pspec);
-        if (type == G_TYPE_PARAM_STRING)
-        {
-            gchar* value;
-            g_object_get (object, property, &value, NULL);
-            if (value)
-            {
-                JSStringRef js_string = JSStringCreateWithUTF8CString (value);
-                js_result = JSValueMakeString (js_context, js_string);
-            }
-        }
-        else if (type == G_TYPE_PARAM_INT
-            || type == G_TYPE_PARAM_UINT)
-        {
-            gint value;
-            g_object_get (object, property, &value, NULL);
-            js_result = JSValueMakeNumber (js_context, value);
-        }
-        else if (type == G_TYPE_PARAM_BOOLEAN)
-        {
-            gboolean value;
-            g_object_get (object, property, &value, NULL);
-            js_result = JSValueMakeBoolean (js_context, value ? true : false);
-        }
-        else if (type == G_TYPE_PARAM_OBJECT)
-        {
-            GObject* value;
-            g_object_get (object, property, &value, NULL);
-            if (value)
-                js_result = gjs_object_new (js_context, value);
-        }
-        else if (type == G_TYPE_PARAM_ENUM)
+        g_free (property);
+        return JSValueMakeUndefined (js_context);
+    }
+    GType type = G_PARAM_SPEC_TYPE (pspec);
+    if (type == G_TYPE_PARAM_STRING)
+    {
+        gchar* value;
+        g_object_get (object, property, &value, NULL);
+        if (value)
         {
-            gint value;
-            g_object_get (object, property, &value, NULL);
-            js_result = JSValueMakeNumber (js_context, value);
+            JSStringRef js_string = JSStringCreateWithUTF8CString (value);
+            js_result = JSValueMakeString (js_context, js_string);
         }
-        else
-            js_result = JSValueMakeUndefined (js_context);
-        g_free (property);
     }
+    else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT)
+    {
+        gint value;
+        g_object_get (object, property, &value, NULL);
+        js_result = JSValueMakeNumber (js_context, value);
+    }
+    else if (type == G_TYPE_PARAM_BOOLEAN)
+    {
+        gboolean value;
+        g_object_get (object, property, &value, NULL);
+        js_result = JSValueMakeBoolean (js_context, value ? true : false);
+    }
+    else if (type == G_TYPE_PARAM_OBJECT)
+    {
+        GObject* value;
+        g_object_get (object, property, &value, NULL);
+        if (value)
+            js_result = gjs_object_new (js_context,
+                G_OBJECT_NAME (value), value);
+    }
+    else if (type == G_TYPE_PARAM_ENUM)
+    {
+        gint value;
+        g_object_get (object, property, &value, NULL);
+        js_result = JSValueMakeNumber (js_context, value);
+    }
+    else
+        js_result = JSValueMakeUndefined (js_context);
+    g_free (property);
     return js_result ? js_result : JSValueMakeNull (js_context);
 }
 
@@ -258,80 +236,79 @@ _js_class_set_property_cb (JSContextRef js_context,
                            JSValueRef*  js_exception)
 {
     GObject* object = JSObjectGetPrivate (js_object);
+
+    g_return_val_if_fail (object, false);
+
     bool result = false;
-    if (object)
+    gchar* property = gjs_string_utf8 (js_property);
+    GParamSpec* pspec = g_object_class_find_property (
+        G_OBJECT_GET_CLASS (object), property);
+    if (!pspec)
     {
-        gchar* property = gjs_string_utf8 (js_property);
-        GParamSpec* pspec = g_object_class_find_property (
-            G_OBJECT_GET_CLASS (object), property);
-        if (!pspec)
-        {
-            gchar* message = g_strdup_printf (_("%s has no property '%s'"),
-                G_OBJECT_NAME (object), property);
-            JSStringRef js_message = JSStringCreateWithUTF8CString (message);
-            *js_exception = JSValueMakeString (js_context, js_message);
-            JSStringRelease (js_message);
-            g_free (message);
-            g_free (property);
-            return false;
-        }
-        if (!(pspec->flags & G_PARAM_WRITABLE))
-        {
-            g_free (property);
-            return false;
-        }
-        GType type = G_PARAM_SPEC_TYPE (pspec);
-        if (type == G_TYPE_PARAM_STRING)
-        {
-            JSStringRef js_string_value = JSValueToStringCopy (js_context,
-                js_value, js_exception);
-            if (js_string_value)
-            {
-                gchar* string_value = gjs_string_utf8 (js_string_value);
-                g_object_set (object, property, string_value, NULL);
-                g_free (string_value);
-            }
-        }
-        else if (type == G_TYPE_PARAM_INT
-            || type == G_TYPE_PARAM_UINT)
-        {
-            int value = JSValueToNumber (js_context, js_value,
-                                          js_exception);
-            g_object_set (object, property, value, NULL);
-        }
-        else if (type == G_TYPE_PARAM_BOOLEAN)
-        {
-            bool value = JSValueToBoolean (js_context, js_value);
-            g_object_set (object, property, value ? TRUE : FALSE, NULL);
-        }
-        else if (type == G_TYPE_PARAM_OBJECT)
+        gchar* message = g_strdup_printf (_("%s has no property '%s'"),
+            G_OBJECT_NAME (object), property);
+        JSStringRef js_message = JSStringCreateWithUTF8CString (message);
+        *js_exception = JSValueMakeString (js_context, js_message);
+        JSStringRelease (js_message);
+        g_free (message);
+        g_free (property);
+        return false;
+    }
+    if (!(pspec->flags & G_PARAM_WRITABLE))
+    {
+        g_free (property);
+        return false;
+    }
+    GType type = G_PARAM_SPEC_TYPE (pspec);
+    if (type == G_TYPE_PARAM_STRING)
+    {
+        JSStringRef js_string_value = JSValueToStringCopy (js_context,
+            js_value, js_exception);
+        if (js_string_value)
         {
-            JSObjectRef js_object_value = JSValueToObject (
-                js_context, js_value, NULL);
-            GObject* object_value = JSObjectGetPrivate (js_object_value);
-            if (object_value)
-                g_object_set (object, property, object_value, NULL);
-            else
-            {
-                gchar* message = g_strdup_printf (_("%s cannot be assigned to %s.%s"),
-                "[object]", G_OBJECT_NAME (object), property);
-                JSStringRef js_message = JSStringCreateWithUTF8CString (message);
-                *js_exception = JSValueMakeString (js_context, js_message);
-                JSStringRelease (js_message);
-                g_free (message);
-            }
+            gchar* string_value = gjs_string_utf8 (js_string_value);
+            g_object_set (object, property, string_value, NULL);
+            g_free (string_value);
         }
+    }
+    else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT)
+    {
+        int value = JSValueToNumber (js_context, js_value,
+                                      js_exception);
+        g_object_set (object, property, value, NULL);
+    }
+    else if (type == G_TYPE_PARAM_BOOLEAN)
+    {
+        bool value = JSValueToBoolean (js_context, js_value);
+        g_object_set (object, property, value ? TRUE : FALSE, NULL);
+    }
+    else if (type == G_TYPE_PARAM_OBJECT)
+    {
+        JSObjectRef js_object_value = JSValueToObject (
+            js_context, js_value, NULL);
+        GObject* object_value = JSObjectGetPrivate (js_object_value);
+        if (object_value)
+            g_object_set (object, property, object_value, NULL);
         else
         {
-            gchar* message = g_strdup_printf (_("%s.%s cannot be accessed"),
-                G_OBJECT_NAME (object), property);
+            gchar* message = g_strdup_printf (_("%s cannot be assigned to %s.%s"),
+            "[object]", G_OBJECT_NAME (object), property);
             JSStringRef js_message = JSStringCreateWithUTF8CString (message);
             *js_exception = JSValueMakeString (js_context, js_message);
             JSStringRelease (js_message);
             g_free (message);
         }
-        g_free (property);
     }
+    else
+    {
+        gchar* message = g_strdup_printf (_("%s.%s cannot be accessed"),
+            G_OBJECT_NAME (object), property);
+        JSStringRef js_message = JSStringCreateWithUTF8CString (message);
+        *js_exception = JSValueMakeString (js_context, js_message);
+        JSStringRelease (js_message);
+        g_free (message);
+    }
+    g_free (property);
     return result;
 }
 
@@ -344,20 +321,20 @@ _js_object_call_as_function_cb (JSContextRef     js_context,
                                 JSValueRef*      js_exception)
 {
     GObject* object = JSObjectGetPrivate (js_this);
-    if (object)
+
+    g_return_val_if_fail (object, JSValueMakeNull (js_context));
+
+    if (!n_arguments)
     {
-        if (!n_arguments)
-        {
-            gtk_widget_show (GTK_WIDGET (object));
-        }
-        else if (n_arguments == 1)
-        {
-            JSObjectRef js_arg1 = JSValueToObject (
-                js_context, js_arguments[0], NULL);
-            GObject* arg1 = JSObjectGetPrivate (js_arg1);
-            if (arg1)
-                gtk_container_add (GTK_CONTAINER (object), GTK_WIDGET (arg1));
-        }
+        gtk_widget_show (GTK_WIDGET (object));
+    }
+    else if (n_arguments == 1)
+    {
+        JSObjectRef js_arg1 = JSValueToObject (
+            js_context, js_arguments[0], NULL);
+        GObject* arg1 = JSObjectGetPrivate (js_arg1);
+        if (arg1)
+            gtk_container_add (GTK_CONTAINER (object), GTK_WIDGET (arg1));
     }
 
     return JSValueMakeUndefined (js_context);
@@ -377,10 +354,14 @@ _js_object_add_function (JSContextRef js_context,
 
 JSObjectRef
 gjs_object_new (JSContextRef js_context,
+                const gchar* name,
                 gpointer     instance)
 {
+    g_return_val_if_fail (js_context, NULL);
+    g_return_val_if_fail (name, NULL);
+
     JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
-    js_class_def.className = g_strdup (G_OBJECT_NAME (instance));
+    js_class_def.className = g_strdup (name);
     js_class_def.getPropertyNames = _js_class_get_property_names_cb;
     js_class_def.hasProperty = _js_class_has_property_cb;
     js_class_def.getProperty = _js_class_get_property_cb;
@@ -397,3 +378,120 @@ gjs_object_new (JSContextRef js_context,
     }
     return js_object;
 }
+
+static JSObjectRef
+_js_object_call_as_constructor_cb (JSContextRef     js_context,
+                                   JSObjectRef      js_object,
+                                   size_t           n_arguments,
+                                   const JSValueRef js_arguments[],
+                                   JSValueRef*      js_exception)
+{
+    const gchar* type_name = JSObjectGetPrivate (js_object);
+
+    g_return_val_if_fail (type_name, NULL);
+
+    GType type = g_type_from_name (type_name);
+    if (type)
+        return gjs_object_new (js_context, type_name, g_object_new (type, NULL));
+    return NULL;
+}
+
+static bool
+_js_module_has_property_cb (JSContextRef js_context,
+                            JSObjectRef  js_object,
+                            JSStringRef  js_property)
+{
+    const gchar* namespace = JSObjectGetPrivate (js_object);
+
+    g_return_val_if_fail (namespace, false);
+
+    gchar* property = gjs_string_utf8 (js_property);
+    gchar* type_name = g_strdup_printf ("%s%s", namespace, property);
+
+    GType type = g_type_from_name (type_name);
+    if (!type)
+    {
+        GModule* module = g_module_open (NULL,
+            G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+        typedef GType (*gjs_get_type_func)(void);
+        // FIXME: Insert a space between each capital letter
+        gchar* type_func_name = g_strdup_printf ("%s_%s_get_type",
+                                                 namespace, property);
+        gchar* type_func_name_small = g_utf8_strdown (type_func_name, -1);
+        gjs_get_type_func type_func;
+        if (g_module_symbol (module,
+            (const gchar*)type_func_name_small, &type_func))
+        {
+            type = type_func ();
+            g_type_class_peek (type);
+        }
+        g_free (type_func_name_small);
+        g_free (type_func_name);
+        g_module_close (module);
+    }
+    bool result = type ? true : false;
+    g_free (type_name);
+    g_free (property);
+    return result;
+}
+
+static JSValueRef
+_js_module_get_property_cb (JSContextRef js_context,
+                            JSObjectRef  js_object,
+                            JSStringRef  js_property,
+                            JSValueRef*  js_exception)
+{
+    const gchar* namespace = JSObjectGetPrivate (js_object);
+
+    g_return_val_if_fail (namespace, JSValueMakeNull (js_context));
+
+    gchar* property = gjs_string_utf8 (js_property);
+    gchar* type_name = g_strdup_printf ("%s%s", namespace, property);
+    GType type = g_type_from_name (type_name);
+    JSValueRef result;
+    if (type)
+    {
+        JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
+        js_class_def.className = g_strdup (type_name);
+        js_class_def.callAsConstructor = _js_object_call_as_constructor_cb;
+        JSClassRef js_class = JSClassCreate (&js_class_def);
+        result = JSObjectMake (js_context, js_class, type_name);
+    }
+    else
+    {
+        result = JSValueMakeNull (js_context);
+        g_free (type_name);
+    }
+    g_free (property);
+    return result;
+}
+
+JSObjectRef
+gjs_module_new (JSContextRef js_context,
+                const gchar* namespace)
+{
+    g_return_val_if_fail (js_context, NULL);
+    g_return_val_if_fail (namespace, NULL);
+
+    JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
+    js_class_def.className = g_strdup (namespace);
+    js_class_def.hasProperty = _js_module_has_property_cb;
+    js_class_def.getProperty = _js_module_get_property_cb;
+    JSClassRef js_class = JSClassCreate (&js_class_def);
+    JSObjectRef js_module = JSObjectMake (js_context, js_class, namespace);
+    return js_module;
+}
+
+JSGlobalContextRef
+gjs_global_context_new (void)
+{
+    JSGlobalContextRef js_context = JSGlobalContextCreate (NULL);
+    JSObjectRef js_gjs = gjs_object_new (js_context, "GJS", NULL);
+    _js_object_set_property (js_context, JSContextGetGlobalObject (js_context),
+                             "gjs", js_gjs);
+
+    JSObjectRef js_gtk = gjs_module_new (js_context, "Gtk");
+    _js_object_set_property (js_context, JSContextGetGlobalObject (js_context),
+                             "Gtk", js_gtk);
+    return js_context;
+}
index 75d846c12098e4ab0686e436bc761040f7b6a284..47e9fced2c05950048594f1a3b37ec4e0c7db206 100644 (file)
--- a/src/gjs.h
+++ b/src/gjs.h
@@ -37,10 +37,11 @@ gjs_string_utf8 (JSStringRef js_string);
 
 JSObjectRef
 gjs_object_new (JSContextRef context,
+                const gchar* name,
                 gpointer     instance);
 
-gchar*
-gjs_string_utf8 (JSStringRef       js_string);
+JSGlobalContextRef
+gjs_global_context_new (void);
 
 G_END_DECLS
 
index f319c3d1c3f667202c89bb5ad4c30d275daca1a7..f0949748962750690a87836934f779fd03b9c4e6 100644 (file)
@@ -315,7 +315,7 @@ main (int argc, char** argv)
     // Standalone gjs support
     if (argc > 1 && argv[1] && g_str_has_suffix (argv[1], ".js"))
     {
-        JSGlobalContextRef js_context = JSGlobalContextCreate (NULL);
+        JSGlobalContextRef js_context = gjs_global_context_new ();
         gchar* exception = NULL;
         gjs_script_from_file (js_context, argv[1], &exception);
         JSGlobalContextRelease (js_context);
@@ -489,7 +489,7 @@ main (int argc, char** argv)
     katze_xbel_item_unref (_session);
 
     // Load extensions
-    JSGlobalContextRef js_context = JSGlobalContextCreate (NULL);
+    JSGlobalContextRef js_context = gjs_global_context_new ();
     // FIXME: We want to honor system installed addons as well
     gchar* addon_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME,
                                           "extensions", NULL);