[gjs/wip/ptomato/develop: 8/11] Use the GIVFuncInfo to hook up vfuncs instead of the GICallbackInfo



commit 05e3232703852a10f224ed51170ffb623c10c167
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sun Aug 26 00:18:16 2012 +0200

    Use the GIVFuncInfo to hook up vfuncs instead of the GICallbackInfo
    
    Using GICallbackInfo loses the flags on the virtual function, such
    as throws.
    The difference is also that GIVFuncInfo does not include the instance
    among the arguments, so we need to offset all the accesses to ffi.
    It is implicitely assumed that virtual functions are hooked on GObjects
    only.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=682701

 gi/function.cpp |   40 +++++++++++++++++++++++-----------------
 gi/object.cpp   |   12 +-----------
 2 files changed, 24 insertions(+), 28 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index 7a955e2..8bc5a94 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -169,15 +169,16 @@ set_return_ffi_arg_from_giargument (GITypeInfo  *ret_type,
 static void
 gjs_callback_closure(ffi_cif *cif,
                      void *result,
-                     void **args,
+                     void **ffi_args,
                      void *data)
 {
     JSContext *context;
     GjsCallbackTrampoline *trampoline;
-    int i, n_args, n_jsargs, n_outargs;
+    int i, n_args, n_jsargs, n_outargs, c_args_offset = 0;
     GITypeInfo ret_type;
     bool success = false;
     bool ret_type_is_void;
+    auto args = reinterpret_cast<GIArgument **>(ffi_args);
 
     trampoline = (GjsCallbackTrampoline *) data;
     g_assert(trampoline);
@@ -209,6 +210,16 @@ gjs_callback_closure(ffi_cif *cif,
 
     g_assert(n_args >= 0);
 
+    JS::RootedObject this_object(context);
+    if (trampoline->is_vfunc) {
+        auto this_gobject = static_cast<GObject *>(args[0]->v_pointer);
+        this_object = gjs_object_from_g_object(context, this_gobject);
+
+        /* "this" is not included in the GI signature, but is in the C (and
+         * FFI) signature */
+        c_args_offset = 1;
+    }
+
     n_outargs = 0;
     JS::AutoValueVector jsargs(context);
 
@@ -216,7 +227,6 @@ gjs_callback_closure(ffi_cif *cif,
         g_error("Unable to reserve space for vector");
 
     JS::RootedValue rval(context);
-    JS::RootedObject this_object(context);
 
     for (i = 0, n_jsargs = 0; i < n_args; i++) {
         GIArgInfo arg_info;
@@ -251,16 +261,18 @@ gjs_callback_closure(ffi_cif *cif,
 
                 g_callable_info_load_arg(trampoline->info, array_length_pos, &array_length_arg);
                 g_arg_info_load_type(&array_length_arg, &arg_type_info);
-                if (!gjs_value_from_g_argument(context, &length,
-                                               &arg_type_info,
-                                               (GArgument *) args[array_length_pos], true))
+                if (!gjs_value_from_g_argument(context, &length, &arg_type_info,
+                                               args[array_length_pos + c_args_offset],
+                                               true))
                     goto out;
 
                 if (!jsargs.growBy(1))
                     g_error("Unable to grow vector");
 
                 if (!gjs_value_from_explicit_array(context, jsargs[n_jsargs++],
-                                                   &type_info, (GArgument*) args[i], length.toInt32()))
+                                                   &type_info,
+                                                   args[i + c_args_offset],
+                                                   length.toInt32()))
                     goto out;
                 break;
             }
@@ -270,7 +282,8 @@ gjs_callback_closure(ffi_cif *cif,
 
                 if (!gjs_value_from_g_argument(context, jsargs[n_jsargs++],
                                                &type_info,
-                                               (GArgument *) args[i], false))
+                                               args[i + c_args_offset],
+                                               false))
                     goto out;
                 break;
             case PARAM_CALLBACK:
@@ -279,13 +292,6 @@ gjs_callback_closure(ffi_cif *cif,
             default:
                 g_assert_not_reached();
         }
-
-        if (trampoline->is_vfunc && i == 0) {
-            g_assert(n_jsargs > 0);
-            this_object = jsargs[0].toObjectOrNull();
-            jsargs.popBack();
-            n_jsargs--;
-        }
     }
 
     if (!gjs_closure_invoke(trampoline->js_function, this_object, jsargs, &rval))
@@ -334,7 +340,7 @@ gjs_callback_closure(ffi_cif *cif,
                                          GJS_ARGUMENT_ARGUMENT,
                                          GI_TRANSFER_NOTHING,
                                          true,
-                                         *(GArgument **)args[i]))
+                                         *(GIArgument **)args[i + c_args_offset]))
                 goto out;
 
             break;
@@ -387,7 +393,7 @@ gjs_callback_closure(ffi_cif *cif,
                                          GJS_ARGUMENT_ARGUMENT,
                                          GI_TRANSFER_NOTHING,
                                          true,
-                                         *(GArgument **)args[i]))
+                                         *(GIArgument **)args[i + c_args_offset]))
                 goto out;
 
             elem_idx++;
diff --git a/gi/object.cpp b/gi/object.cpp
index e47a076..950872e 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -2344,31 +2344,21 @@ gjs_hook_up_vfunc(JSContext *cx,
 
     find_vfunc_info(cx, gtype, vfunc, name, &implementor_vtable, &field_info);
     if (field_info != NULL) {
-        GITypeInfo *type_info;
-        GIBaseInfo *interface_info;
-        GICallbackInfo *callback_info;
         gint offset;
         gpointer method_ptr;
         GjsCallbackTrampoline *trampoline;
 
-        type_info = g_field_info_get_type(field_info);
-
-        interface_info = g_type_info_get_interface(type_info);
-
-        callback_info = (GICallbackInfo*)interface_info;
         offset = g_field_info_get_offset(field_info);
         method_ptr = G_STRUCT_MEMBER_P(implementor_vtable, offset);
 
         JS::RootedValue v_function(cx, JS::ObjectValue(*function));
-        trampoline = gjs_callback_trampoline_new(cx, v_function, callback_info,
+        trampoline = gjs_callback_trampoline_new(cx, v_function, vfunc,
                                                  GI_SCOPE_TYPE_NOTIFIED,
                                                  object, true);
 
         *((ffi_closure **)method_ptr) = trampoline->closure;
         priv->vfuncs.push_back(trampoline);
 
-        g_base_info_unref(interface_info);
-        g_base_info_unref(type_info);
         g_base_info_unref(field_info);
     }
 


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