[gjs: 2/21] wrapperutils: Move define_static_methods into GIWrapper



commit c8c178f1ed4f3857ed941d90035b87235064e9fa
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Jan 1 20:37:24 2019 -0700

    wrapperutils: Move define_static_methods into GIWrapper
    
    All the GIWrapper classes should use gjs_define_static_methods() to
    define static methods from the g-i information.
    
    Previously, Union objects skipped this step, so they did not have static
    methods available. Now they do.
    
    This was not done as part of the previous wrapperutils.h refactor,
    because the union static method support exposed a bug in the g-i test
    suite which was not fixed until g-i 1.59.2.

 configure.ac        |  2 +-
 gi/boxed.cpp        |  8 +++-----
 gi/boxed.h          |  2 ++
 gi/fundamental.cpp  |  3 +--
 gi/fundamental.h    |  2 ++
 gi/gerror.cpp       | 11 ++++-------
 gi/gerror.h         |  2 ++
 gi/interface.cpp    | 16 ++--------------
 gi/interface.h      |  2 ++
 gi/object.cpp       | 14 +++-----------
 gi/object.h         |  2 ++
 gi/union.h          |  2 ++
 gi/wrapperutils.cpp |  3 +++
 gi/wrapperutils.h   | 25 +++++++++++++++++++++++--
 14 files changed, 52 insertions(+), 42 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index ed4db947..ef55099c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -385,7 +385,7 @@ AC_CONFIG_LINKS([
 AC_OUTPUT
 
 # Warn about conditions that affect runtime
-PKG_CHECK_EXISTS([gobject-introspection-1.0 >= 1.57.2], [], [
+PKG_CHECK_EXISTS([gobject-introspection-1.0 >= 1.59.2], [], [
     AC_MSG_WARN([You do not have a new enough version of
 gobject-introspection to run the tests. You can still build GJS, but some
 tests will fail.])])
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 7073924a..f6db484a 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -957,13 +957,11 @@ bool BoxedPrototype::init(JSContext* context) {
 bool BoxedPrototype::define_class(JSContext* context,
                                   JS::HandleObject in_object,
                                   GIStructInfo* info) {
-    JS::RootedObject prototype(context), constructor(context);
+    JS::RootedObject prototype(context), unused_constructor(context);
     GType gtype = g_registered_type_info_get_g_type(info);
     BoxedPrototype* priv = BoxedPrototype::create_class(
-        context, in_object, info, gtype, &constructor, &prototype);
-    if (!priv || !priv->define_boxed_class_fields(context, prototype) ||
-        !gjs_define_static_methods<InfoType::Struct>(context, constructor, gtype,
-                                                     info))
+        context, in_object, info, gtype, &unused_constructor, &prototype);
+    if (!priv || !priv->define_boxed_class_fields(context, prototype))
         return false;
 
     if (gtype == G_TYPE_ERROR &&
diff --git a/gi/boxed.h b/gi/boxed.h
index 0b4a253e..2d5d20bc 100644
--- a/gi/boxed.h
+++ b/gi/boxed.h
@@ -99,6 +99,8 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
 
     GJS_JSAPI_RETURN_CONVENTION bool init(JSContext* cx);
 
+    static constexpr InfoType::Tag info_type_tag = InfoType::Struct;
+
     // Accessors
 
  public:
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index ddcaa62c..8cac0901 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -422,8 +422,7 @@ bool FundamentalPrototype::define_class(JSContext* cx,
                   priv->ns(), priv->name());
     }
 
-    return gjs_define_static_methods<InfoType::Object>(cx, constructor, gtype,
-                                                       info);
+    return true;
 }
 
 /*
diff --git a/gi/fundamental.h b/gi/fundamental.h
index 38201d6a..5c0d5298 100644
--- a/gi/fundamental.h
+++ b/gi/fundamental.h
@@ -91,6 +91,8 @@ class FundamentalPrototype
 
     GJS_JSAPI_RETURN_CONVENTION bool init(JSContext* cx);
 
+    static constexpr InfoType::Tag info_type_tag = InfoType::Object;
+
  public:
     GJS_JSAPI_RETURN_CONVENTION
     static FundamentalPrototype* for_gtype(JSContext* cx, GType gtype);
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index 2d9ec9b8..00c20cea 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -238,13 +238,10 @@ bool ErrorPrototype::define_class(JSContext* context,
     // prototype of GLib.Error; and create_class() will not define it since we
     // supply a parent in get_parent_proto().
     const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
-    if (!JS_DefineFunctionById(context, prototype, atoms.to_string(),
-                               &ErrorBase::to_string, 0, GJS_MODULE_PROP_FLAGS))
-        return false;
-
-    return gjs_define_enum_values(context, constructor, info) &&
-           gjs_define_static_methods<InfoType::Enum>(context, constructor,
-                                                     G_TYPE_ERROR, info);
+    return JS_DefineFunctionById(context, prototype, atoms.to_string(),
+                                 &ErrorBase::to_string, 0,
+                                 GJS_MODULE_PROP_FLAGS) &&
+           gjs_define_enum_values(context, constructor, info);
 }
 
 GJS_USE
diff --git a/gi/gerror.h b/gi/gerror.h
index 4e36032a..a78afdef 100644
--- a/gi/gerror.h
+++ b/gi/gerror.h
@@ -116,6 +116,8 @@ class ErrorPrototype : public GIWrapperPrototype<ErrorBase, ErrorPrototype,
 
     GQuark m_domain;
 
+    static constexpr InfoType::Tag info_type_tag = InfoType::Enum;
+
     explicit ErrorPrototype(GIEnumInfo* info, GType gtype);
     ~ErrorPrototype(void);
 
diff --git a/gi/interface.cpp b/gi/interface.cpp
index a759080f..ee3bcd6c 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -148,20 +148,8 @@ gjs_define_interface_class(JSContext              *context,
                            JS::MutableHandleObject constructor)
 {
     JS::RootedObject prototype(context);
-
-    if (!InterfacePrototype::create_class(context, in_object, info, gtype,
-                                          constructor, &prototype))
-        return false;
-
-    /* If we have no GIRepository information, then this interface was defined
-     * from within GJS and therefore has no C static methods to be defined. */
-    if (info) {
-        if (!gjs_define_static_methods<InfoType::Interface>(
-                context, constructor, gtype, info))
-            return false;
-    }
-
-    return true;
+    return !!InterfacePrototype::create_class(context, in_object, info, gtype,
+                                              constructor, &prototype);
 }
 
 bool
diff --git a/gi/interface.h b/gi/interface.h
index 7d100e90..dec7452a 100644
--- a/gi/interface.h
+++ b/gi/interface.h
@@ -93,6 +93,8 @@ class InterfacePrototype
     // the GTypeInterface vtable wrapped by this JS object
     GTypeInterface* m_vtable;
 
+    static constexpr InfoType::Tag info_type_tag = InfoType::Interface;
+
     explicit InterfacePrototype(GIInterfaceInfo* info, GType gtype);
     ~InterfacePrototype(void);
 
diff --git a/gi/object.cpp b/gi/object.cpp
index 8272c569..5404fe15 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -2000,17 +2000,9 @@ bool ObjectPrototype::define_class(JSContext* context,
     /* Hook_up_vfunc can't be included in gjs_object_instance_proto_funcs
      * because it's a custom symbol. */
     const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
-    if (!JS_DefineFunctionById(context, prototype, atoms.hook_up_vfunc(),
-                               &ObjectBase::hook_up_vfunc, 3,
-                               GJS_MODULE_PROP_FLAGS))
-        return false;
-
-    if (info)
-        if (!gjs_define_static_methods<InfoType::Object>(context, constructor,
-                                                         gtype, info))
-            return false;
-
-    return true;
+    return JS_DefineFunctionById(context, prototype, atoms.hook_up_vfunc(),
+                                 &ObjectBase::hook_up_vfunc, 3,
+                                 GJS_MODULE_PROP_FLAGS);
 }
 
 /*
diff --git a/gi/object.h b/gi/object.h
index 0c81d2e6..8ee35358 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -206,6 +206,8 @@ class ObjectPrototype
     GJS_JSAPI_RETURN_CONVENTION bool init(JSContext* cx);
     ~ObjectPrototype();
 
+    static constexpr InfoType::Tag info_type_tag = InfoType::Object;
+
  public:
     GJS_USE
     static ObjectPrototype* for_gtype(GType gtype);
diff --git a/gi/union.h b/gi/union.h
index 36dbddce..958ea86a 100644
--- a/gi/union.h
+++ b/gi/union.h
@@ -59,6 +59,8 @@ class UnionPrototype : public GIWrapperPrototype<UnionBase, UnionPrototype,
                                     GIUnionInfo>;
     friend class GIWrapperBase<UnionBase, UnionPrototype, UnionInstance>;
 
+    static constexpr InfoType::Tag info_type_tag = InfoType::Union;
+
     explicit UnionPrototype(GIUnionInfo* info, GType gtype);
     ~UnionPrototype(void);
 
diff --git a/gi/wrapperutils.cpp b/gi/wrapperutils.cpp
index 82ff4632..c62292c1 100644
--- a/gi/wrapperutils.cpp
+++ b/gi/wrapperutils.cpp
@@ -121,6 +121,7 @@ DECLARE_POLICY(Enum, enum, no_type_struct)
 DECLARE_POLICY(Interface, interface, g_interface_info_get_iface_struct)
 DECLARE_POLICY(Object, object, g_object_info_get_class_struct)
 DECLARE_POLICY(Struct, struct, no_type_struct)
+DECLARE_POLICY(Union, union, no_type_struct)
 
 #undef DECLARE_POLICY
 
@@ -176,3 +177,5 @@ template bool gjs_define_static_methods<InfoType::Object>(
     JSContext* cx, JS::HandleObject constructor, GType gtype, GIBaseInfo* info);
 template bool gjs_define_static_methods<InfoType::Struct>(
     JSContext* cx, JS::HandleObject constructor, GType gtype, GIBaseInfo* info);
+template bool gjs_define_static_methods<InfoType::Union>(
+    JSContext* cx, JS::HandleObject constructor, GType gtype, GIBaseInfo* info);
diff --git a/gi/wrapperutils.h b/gi/wrapperutils.h
index 19f6a68b..7eff199e 100644
--- a/gi/wrapperutils.h
+++ b/gi/wrapperutils.h
@@ -52,7 +52,7 @@ bool gjs_wrapper_define_gtype_prop(JSContext* cx, JS::HandleObject constructor,
 G_END_DECLS
 
 namespace InfoType {
-enum Tag { Enum, Interface, Object, Struct };
+enum Tag { Enum, Interface, Object, Struct, Union };
 }
 
 struct GjsTypecheckNoThrow {};
@@ -748,7 +748,7 @@ class GIWrapperPrototype : public Base {
     GJS_JSAPI_RETURN_CONVENTION
     bool init(JSContext*) { return true; }
 
-    // The following three methods are private because they are used only in
+    // The following four methods are private because they are used only in
     // create_class().
 
  private:
@@ -861,6 +861,22 @@ class GIWrapperPrototype : public Base {
         return true;
     }
 
+    /*
+     * GIWrapperPrototype::define_static_methods:
+     *
+     * Defines all introspectable static methods on @constructor, including
+     * class methods for objects, and interface methods for interfaces. See
+     * gjs_define_static_methods() for details.
+     *
+     * It requires Prototype to have an info_type_tag member to indicate
+     * the correct template specialization of gjs_define_static_methods().
+     */
+    GJS_JSAPI_RETURN_CONVENTION
+    bool define_static_methods(JSContext* cx, JS::HandleObject constructor) {
+        return gjs_define_static_methods<Prototype::info_type_tag>(
+            cx, constructor, m_gtype, m_info);
+    }
+
  public:
     /**
      * GIWrapperPrototype::create_class:
@@ -921,6 +937,11 @@ class GIWrapperPrototype : public Base {
                 return nullptr;
         }
 
+        if (!priv->is_custom_js_class()) {
+            if (!priv->define_static_methods(cx, constructor))
+                return nullptr;
+        }
+
         JS_SetPrivate(prototype, priv);
         return priv;
     }


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