[gjs/burninate-macros: 6/13] gtype: Remove JSClass macros



commit ddd5438fce4f45f0c0c10016a0c81822c897d500
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Apr 7 23:53:00 2020 -0700

    gtype: Remove JSClass macros
    
    FIXME: Need commit message
    FIXME: Is "Type" really the best name?
    FIXME: Make the template more typesafe?

 gi/arg.cpp                           |   8 +--
 gi/function.cpp                      |   2 +-
 gi/gtype.cpp                         | 123 +++++++++++++----------------------
 gi/gtype.h                           |  67 ++++++++++++++++---
 gi/private.cpp                       |  13 ++--
 gi/value.cpp                         |   4 +-
 gi/wrapperutils.cpp                  |   2 +-
 installed-tests/js/testGTypeClass.js |  10 ---
 8 files changed, 115 insertions(+), 114 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index ba706021..4e51921a 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -983,7 +983,7 @@ gjs_gtypearray_to_array(JSContext   *context,
         }
 
         elem_obj = &elem.toObject();
-        if (!gjs_gtype_get_actual_gtype(context, elem_obj, &gtype))
+        if (!Type::get_actual_gtype(context, elem_obj, &gtype))
             return false;
         if (gtype == G_TYPE_INVALID) {
             gjs_throw(context, "Invalid element in GType array");
@@ -1647,7 +1647,7 @@ static bool value_to_interface_gi_argument(
         if (interface_type == GI_INFO_TYPE_STRUCT &&
             g_struct_info_is_gtype_struct(interface_info)) {
             GType actual_gtype;
-            if (!gjs_gtype_get_actual_gtype(cx, obj, &actual_gtype))
+            if (!Type::get_actual_gtype(cx, obj, &actual_gtype))
                 return false;
 
             if (actual_gtype == G_TYPE_NONE) {
@@ -1937,7 +1937,7 @@ gjs_value_to_g_argument(JSContext      *context,
         if (value.isObjectOrNull()) {
             GType gtype;
             JS::RootedObject obj(context, value.toObjectOrNull());
-            if (!gjs_gtype_get_actual_gtype(context, obj, &gtype)) {
+            if (!Type::get_actual_gtype(context, obj, &gtype)) {
                 wrong = true;
                 break;
             }
@@ -2950,7 +2950,7 @@ gjs_value_from_g_argument (JSContext             *context,
         if (gtype == 0)
             return true;  /* value_p is set to JS null */
 
-        JS::RootedObject obj(context, gjs_gtype_create_gtype_wrapper(context, gtype));
+        JS::RootedObject obj(context, Type::create(context, gtype));
         if (!obj)
             return false;
 
diff --git a/gi/function.cpp b/gi/function.cpp
index 19594529..25bd62b7 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -663,7 +663,7 @@ gjs_fill_method_instance(JSContext       *context,
             GType actual_gtype;
             gpointer klass;
 
-            if (!gjs_gtype_get_actual_gtype(context, obj, &actual_gtype))
+            if (!Type::get_actual_gtype(context, obj, &actual_gtype))
                 return false;
 
             if (actual_gtype == G_TYPE_NONE) {
diff --git a/gi/gtype.cpp b/gi/gtype.cpp
index 70cbe245..d74c7024 100644
--- a/gi/gtype.cpp
+++ b/gi/gtype.cpp
@@ -46,39 +46,29 @@
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util.h"
 
-GJS_USE static JSObject* gjs_gtype_get_proto(JSContext* cx) G_GNUC_UNUSED;
-GJS_JSAPI_RETURN_CONVENTION
-static bool gjs_gtype_define_proto(JSContext *, JS::HandleObject,
-                                   JS::MutableHandleObject);
-
-GJS_DEFINE_PROTO_ABSTRACT("GIRepositoryGType", gtype,
-                          JSCLASS_FOREGROUND_FINALIZE);
-
-/* priv_from_js adds a "*", so this returns "void *" */
-GJS_DEFINE_PRIV_FROM_JS(void, gjs_gtype_class);
+// clang-format off
+const JSClass Type::klass = {
+    "GIRepositoryGType",
+    JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE,
+    &Type::class_ops
+};
+// clang-format on
 
-static void gjs_gtype_finalize(JSFreeOp*, JSObject*) {
-    // No private data is allocated, it's stuffed directly in the private field
-    // of JSObject, so nothing to free
-}
+const js::ClassSpec Type::class_spec = {nullptr,  // createConstructor
+                                        nullptr,  // createPrototype
+                                        nullptr,  // constructorFunctions
+                                        nullptr,  // constructorProperties
+                                        Type::proto_funcs,
+                                        Type::proto_props,
+                                        nullptr,  // finishInit
+                                        js::ClassSpec::DontDefineConstructor};
 
 GJS_JSAPI_RETURN_CONVENTION
-static bool
-to_string_func(JSContext *cx,
-               unsigned   argc,
-               JS::Value *vp)
-{
-    GJS_GET_PRIV(cx, argc, vp, rec, obj, void, priv);
-    GType gtype = GPOINTER_TO_SIZE(priv);
-
-    if (gtype == 0) {
-        JS::RootedString str(cx,
-                             JS_AtomizeString(cx, "[object GType prototype]"));
-        if (!str)
-            return false;
-        rec.rval().setString(str);
-        return true;
-    }
+bool Type::to_string(JSContext* cx, unsigned argc, JS::Value* vp) {
+    GJS_GET_THIS(cx, argc, vp, rec, obj);
+    GType gtype = Type::value(cx, obj, rec);
+    if (gtype == 0)
+        return false;
 
     GjsAutoChar strval = g_strdup_printf("[object GType for '%s']",
                                          g_type_name(gtype));
@@ -86,40 +76,26 @@ to_string_func(JSContext *cx,
 }
 
 GJS_JSAPI_RETURN_CONVENTION
-static bool
-get_name_func (JSContext *context,
-               unsigned   argc,
-               JS::Value *vp)
-{
-    GJS_GET_PRIV(context, argc, vp, rec, obj, void, priv);
-    GType gtype;
-
-    gtype = GPOINTER_TO_SIZE(priv);
-
-    if (gtype == 0) {
-        rec.rval().setNull();
-        return true;
-    }
+bool Type::get_name(JSContext* context, unsigned argc, JS::Value* vp) {
+    GJS_GET_THIS(context, argc, vp, rec, obj);
+    GType gtype = Type::value(context, obj, rec);
+    if (gtype == 0)
+        return false;
+
     return gjs_string_from_utf8(context, g_type_name(gtype), rec.rval());
 }
 
 /* Properties */
-JSPropertySpec gjs_gtype_proto_props[] = {
-    JS_PSG("name", get_name_func, JSPROP_PERMANENT),
+const JSPropertySpec Type::proto_props[] = {
+    JS_PSG("name", &Type::get_name, JSPROP_PERMANENT),
     JS_PS_END,
 };
 
 /* Functions */
-JSFunctionSpec gjs_gtype_proto_funcs[] = {
-    JS_FN("toString", to_string_func, 0, 0),
-    JS_FS_END};
+const JSFunctionSpec Type::proto_funcs[] = {
+    JS_FN("toString", &Type::to_string, 0, 0), JS_FS_END};
 
-JSFunctionSpec gjs_gtype_static_funcs[] = { JS_FS_END };
-
-JSObject *
-gjs_gtype_create_gtype_wrapper (JSContext *context,
-                                GType      gtype)
-{
+JSObject* Type::create(JSContext* context, GType gtype) {
     g_assert(((void) "Attempted to create wrapper object for invalid GType",
               gtype != 0));
 
@@ -132,12 +108,12 @@ gjs_gtype_create_gtype_wrapper (JSContext *context,
     if (p.found())
         return p->value();
 
-    JS::RootedObject proto(context);
-    if (!gjs_gtype_define_proto(context, nullptr, &proto))
+    JS::RootedObject proto(context, Type::create_prototype(context));
+    if (!proto)
         return nullptr;
 
     JS::RootedObject gtype_wrapper(
-        context, JS_NewObjectWithGivenProto(context, &gjs_gtype_class, proto));
+        context, JS_NewObjectWithGivenProto(context, &Type::klass, proto));
     if (!gtype_wrapper)
         return nullptr;
 
@@ -148,13 +124,12 @@ gjs_gtype_create_gtype_wrapper (JSContext *context,
     return gtype_wrapper;
 }
 
-GJS_JSAPI_RETURN_CONVENTION
-static bool _gjs_gtype_get_actual_gtype(JSContext* context,
-                                        const GjsAtoms& atoms,
-                                        JS::HandleObject object,
-                                        GType* gtype_out, int recurse) {
-    if (JS_InstanceOf(context, object, &gjs_gtype_class, nullptr)) {
-        *gtype_out = GPOINTER_TO_SIZE(priv_from_js(context, object));
+bool Type::_get_actual_gtype(JSContext* context, const GjsAtoms& atoms,
+                             JS::HandleObject object, GType* gtype_out,
+                             int recurse) {
+    GType gtype = Type::value(context, object);
+    if (gtype > 0) {
+        *gtype_out = gtype;
         return true;
     }
 
@@ -174,16 +149,16 @@ static bool _gjs_gtype_get_actual_gtype(JSContext* context,
 
     if (recurse > 0 && gtype_val.isObject()) {
         JS::RootedObject gtype_obj(context, &gtype_val.toObject());
-        return _gjs_gtype_get_actual_gtype(context, atoms, gtype_obj,
-                                           gtype_out, recurse - 1);
+        return _get_actual_gtype(context, atoms, gtype_obj, gtype_out,
+                                 recurse - 1);
     }
 
     *gtype_out = G_TYPE_INVALID;
     return true;
 }
 
-bool gjs_gtype_get_actual_gtype(JSContext* context, JS::HandleObject object,
-                                GType* gtype_out) {
+bool Type::get_actual_gtype(JSContext* context, JS::HandleObject object,
+                            GType* gtype_out) {
     g_assert(gtype_out && "Missing return location");
 
     /* 2 means: recurse at most three times (including this
@@ -195,13 +170,5 @@ bool gjs_gtype_get_actual_gtype(JSContext* context, JS::HandleObject object,
      */
 
     const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
-    return _gjs_gtype_get_actual_gtype(context, atoms, object, gtype_out, 2);
-}
-
-bool
-gjs_typecheck_gtype (JSContext             *context,
-                     JS::HandleObject       obj,
-                     bool                   throw_error)
-{
-    return do_base_typecheck(context, obj, throw_error);
+    return _get_actual_gtype(context, atoms, object, gtype_out, 2);
 }
diff --git a/gi/gtype.h b/gi/gtype.h
index ceb1b94b..eba8e9b2 100644
--- a/gi/gtype.h
+++ b/gi/gtype.h
@@ -28,22 +28,69 @@
 #include <config.h>
 
 #include <glib-object.h>
+#include <glib.h>  // for GPOINTER_TO_SIZE
 
+#include <js/PropertySpec.h>
+#include <js/RootingAPI.h>
 #include <js/TypeDecls.h>
 
+#include "gjs/jsapi-class.h"
 #include "gjs/macros.h"
 
-GJS_JSAPI_RETURN_CONVENTION
-JSObject * gjs_gtype_create_gtype_wrapper (JSContext *context,
-                                           GType      gtype);
+class GjsAtoms;
+namespace JS {
+class CallArgs;
+}
+namespace js {
+struct ClassSpec;
+}
+struct JSClass;
 
-GJS_JSAPI_RETURN_CONVENTION
-bool gjs_gtype_get_actual_gtype(JSContext* context, JS::HandleObject object,
-                                GType* gtype_out);
+// Unfortunately, named "Type" because "GType" is already taken
+class Type;
+using TypeBase = NativeObject<Type, void, GJS_GLOBAL_SLOT_PROTOTYPE_gtype>;
 
-GJS_USE
-bool        gjs_typecheck_gtype         (JSContext             *context,
-                                         JS::HandleObject       obj,
-                                         bool                   throw_error);
+class Type : public TypeBase {
+    friend TypeBase;
+
+    // No private data is allocated, it's stuffed directly in the private field
+    // of JSObject, so nothing to free
+    static void finalize_impl(JSFreeOp*, void*) {}
+
+    static const JSClass klass;
+    static const JSPropertySpec proto_props[];
+    static const JSFunctionSpec proto_funcs[];
+    static const js::ClassSpec class_spec;
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static GType value(JSContext* cx, JS::HandleObject obj,
+                       JS::CallArgs& args) {
+        return GPOINTER_TO_SIZE(Type::for_js(cx, obj, args));
+    }
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static GType value(JSContext* cx, JS::HandleObject obj) {
+        return GPOINTER_TO_SIZE(Type::for_js(cx, obj));
+    }
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static bool to_string(JSContext* cx, unsigned argc, JS::Value* vp);
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static bool get_name(JSContext* cx, unsigned argc, JS::Value* vp);
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static bool _get_actual_gtype(JSContext* cx, const GjsAtoms& atoms,
+                                  JS::HandleObject object, GType* gtype_out,
+                                  int recurse);
+
+ public:
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* create(JSContext* cx, GType gtype);
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static bool get_actual_gtype(JSContext* cx, JS::HandleObject object,
+                                 GType* gtype_out);
+};
 
 #endif  // GI_GTYPE_H_
diff --git a/gi/private.cpp b/gi/private.cpp
index 9159776d..be9b641a 100644
--- a/gi/private.cpp
+++ b/gi/private.cpp
@@ -65,7 +65,7 @@ static bool gjs_override_property(JSContext* cx, unsigned argc, JS::Value* vp) {
         return false;
 
     GType gtype;
-    if (!gjs_gtype_get_actual_gtype(cx, type, &gtype))
+    if (!Type::get_actual_gtype(cx, type, &gtype))
         return false;
     if (gtype == G_TYPE_INVALID) {
         gjs_throw(cx, "Invalid parameter type was not a GType");
@@ -179,7 +179,7 @@ static bool get_interface_gtypes(JSContext* cx, JS::HandleObject interfaces,
 
         JS::RootedObject iface(cx, &iface_val.toObject());
         GType iface_type;
-        if (!gjs_gtype_get_actual_gtype(cx, iface, &iface_type))
+        if (!Type::get_actual_gtype(cx, iface, &iface_type))
             return false;
         if (iface_type == G_TYPE_INVALID) {
             gjs_throw(
@@ -354,9 +354,6 @@ static bool gjs_signal_new(JSContext* cx, unsigned argc, JS::Value* vp) {
                              &params_obj))
         return false;
 
-    if (!gjs_typecheck_gtype(cx, gtype_obj, true))
-        return false;
-
     /* we only support standard accumulators for now */
     GSignalAccumulator accumulator;
     switch (accumulator_enum) {
@@ -372,7 +369,7 @@ static bool gjs_signal_new(JSContext* cx, unsigned argc, JS::Value* vp) {
     }
 
     GType return_type;
-    if (!gjs_gtype_get_actual_gtype(cx, return_gtype_obj, &return_type))
+    if (!Type::get_actual_gtype(cx, return_gtype_obj, &return_type))
         return false;
 
     if (accumulator == g_signal_accumulator_true_handled &&
@@ -397,12 +394,12 @@ static bool gjs_signal_new(JSContext* cx, unsigned argc, JS::Value* vp) {
         }
 
         JS::RootedObject gjs_gtype(cx, &gtype_val.toObject());
-        if (!gjs_gtype_get_actual_gtype(cx, gjs_gtype, &params[ix]))
+        if (!Type::get_actual_gtype(cx, gjs_gtype, &params[ix]))
             return false;
     }
 
     GType gtype;
-    if (!gjs_gtype_get_actual_gtype(cx, gtype_obj, &gtype))
+    if (!Type::get_actual_gtype(cx, gtype_obj, &gtype))
         return false;
 
     unsigned signal_id = g_signal_newv(
diff --git a/gi/value.cpp b/gi/value.cpp
index 580797da..95e95c47 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -355,7 +355,7 @@ static bool gjs_value_guess_g_type(JSContext* context, JS::Value value,
     }
     if (value.isObject()) {
         JS::RootedObject obj(context, &value.toObject());
-        return gjs_gtype_get_actual_gtype(context, obj, gtype_out);
+        return Type::get_actual_gtype(context, obj, gtype_out);
     }
 
     *gtype_out = G_TYPE_INVALID;
@@ -693,7 +693,7 @@ gjs_value_to_g_value_internal(JSContext      *context,
             return throw_expect_type(context, value, "GType object");
 
         JS::RootedObject obj(context, &value.toObject());
-        if (!gjs_gtype_get_actual_gtype(context, obj, &type))
+        if (!Type::get_actual_gtype(context, obj, &type))
             return false;
         g_value_set_gtype(gvalue, type);
     } else if (g_type_is_a(gtype, G_TYPE_POINTER)) {
diff --git a/gi/wrapperutils.cpp b/gi/wrapperutils.cpp
index 50238fef..8272bc90 100644
--- a/gi/wrapperutils.cpp
+++ b/gi/wrapperutils.cpp
@@ -95,7 +95,7 @@ bool gjs_wrapper_throw_readonly_field(JSContext* cx, GType gtype,
 
 bool gjs_wrapper_define_gtype_prop(JSContext* cx, JS::HandleObject constructor,
                                    GType gtype) {
-    JS::RootedObject gtype_obj(cx, gjs_gtype_create_gtype_wrapper(cx, gtype));
+    JS::RootedObject gtype_obj(cx, Type::create(cx, gtype));
     if (!gtype_obj)
         return false;
 
diff --git a/installed-tests/js/testGTypeClass.js b/installed-tests/js/testGTypeClass.js
index 3bfe2cd3..05663bf4 100644
--- a/installed-tests/js/testGTypeClass.js
+++ b/installed-tests/js/testGTypeClass.js
@@ -59,13 +59,3 @@ describe('GType marshalling', function () {
         expect(GObject.type_parent(GObject.TYPE_STRING)).toBeNull();
     });
 });
-
-describe('GType prototype object', function () {
-    it('has no name', function () {
-        expect(GIRepositoryGType.name).toBeNull();
-    });
-
-    it('has a string representation', function () {
-        expect(GIRepositoryGType.toString()).toEqual('[object GType prototype]');
-    });
-});


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