[gjs: 2/12] ns: Remove JSClass macros




commit 5171a90cd2716a9c8fe07da23ff71fe36fbd6305
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Apr 7 17:09:45 2020 -0700

    ns: Remove JSClass macros
    
    Port Ns to use the CWrapper template, instead of the
    GJS_DEFINE_PRIV_FROM_JS family of macros.

 gi/ns.cpp | 164 ++++++++++++++++++++++++++++----------------------------------
 1 file changed, 74 insertions(+), 90 deletions(-)
---
diff --git a/gi/ns.cpp b/gi/ns.cpp
index c8b352bb..1b3a10d8 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -18,35 +18,72 @@
 #include <js/Utility.h>  // for UniqueChars
 #include <jsapi.h>       // for JS_GetPrivate, JS_NewObjectWithGivenProto
 
+#include "gi/cwrapper.h"
 #include "gi/ns.h"
 #include "gi/repo.h"
 #include "gjs/atoms.h"
 #include "gjs/context-private.h"
-#include "gjs/jsapi-class.h"
+#include "gjs/global.h"
 #include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 #include "gjs/mem-private.h"
 #include "util/log.h"
 
-struct Ns : GjsAutoChar {
+class Ns : private GjsAutoChar, public CWrapper<Ns> {
+    friend CWrapperPointerOps<Ns>;
+    friend CWrapper<Ns>;
+
+    static constexpr auto PROTOTYPE_SLOT = GjsGlobalSlot::PROTOTYPE_ns;
+    static constexpr GjsDebugTopic DEBUG_TOPIC = GJS_DEBUG_GNAMESPACE;
+
     explicit Ns(const char* ns_name)
         : GjsAutoChar(const_cast<char*>(ns_name), GjsAutoTakeOwnership()) {}
-};
 
-extern struct JSClass gjs_ns_class;
+    // JSClass operations
+
+    GJS_JSAPI_RETURN_CONVENTION
+    bool resolve_impl(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
+                      bool* resolved);
+
+    GJS_JSAPI_RETURN_CONVENTION
+    bool new_enumerate_impl(JSContext* cx, JS::HandleObject obj,
+                            JS::MutableHandleIdVector properties,
+                            bool only_enumerable);
+
+    static void finalize_impl(JSFreeOp* fop, Ns* priv);
+
+    // Properties and methods
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static bool get_name(JSContext* cx, unsigned argc, JS::Value* vp);
 
-GJS_DEFINE_PRIV_FROM_JS(Ns, gjs_ns_class)
+    static const JSClassOps class_ops;
+    static const JSPropertySpec proto_props[];
+
+    static constexpr js::ClassSpec class_spec = {
+        nullptr,  // createConstructor
+        nullptr,  // createPrototype
+        nullptr,  // constructorFunctions
+        nullptr,  // constructorProperties
+        nullptr,  // prototypeFunctions
+        Ns::proto_props,
+        nullptr,  // finishInit
+        js::ClassSpec::DontDefineConstructor};
+
+    static constexpr JSClass klass = {
+        "GIRepositoryNamespace",
+        JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE, &Ns::class_ops,
+        &Ns::class_spec};
+
+ public:
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* create(JSContext* cx, const char* ns_name);
+};
 
 /* The *resolved out parameter, on success, should be false to indicate that id
  * was not resolved; and true if id was resolved. */
-GJS_JSAPI_RETURN_CONVENTION
-static bool
-ns_resolve(JSContext       *context,
-           JS::HandleObject obj,
-           JS::HandleId     id,
-           bool            *resolved)
-{
-    Ns *priv;
+bool Ns::resolve_impl(JSContext* context, JS::HandleObject obj, JS::HandleId id,
+                      bool* resolved) {
     bool defined;
 
     if (!JSID_IS_STRING(id)) {
@@ -61,16 +98,6 @@ ns_resolve(JSContext       *context,
         return true;
     }
 
-    priv = priv_from_js(context, obj);
-    gjs_debug_jsprop(GJS_DEBUG_GNAMESPACE,
-                     "Resolve prop '%s' hook, obj %s, priv %p",
-                     gjs_debug_id(id).c_str(), gjs_debug_object(obj).c_str(), priv);
-
-    if (!priv) {
-        *resolved = false;  /* we are the prototype, or have the wrong class */
-        return true;
-    }
-
     JS::UniqueChars name;
     if (!gjs_get_string_id(context, id, &name))
         return false;
@@ -80,7 +107,7 @@ ns_resolve(JSContext       *context,
     }
 
     GjsAutoBaseInfo info =
-        g_irepository_find_by_name(nullptr, priv->get(), name.get());
+        g_irepository_find_by_name(nullptr, get(), name.get());
     if (!info) {
         *resolved = false; /* No property defined, but no error either */
         return true;
@@ -101,24 +128,18 @@ ns_resolve(JSContext       *context,
     return true;
 }
 
-GJS_JSAPI_RETURN_CONVENTION
-static bool ns_new_enumerate(JSContext* cx, JS::HandleObject obj,
-                             JS::MutableHandleIdVector properties,
-                             bool only_enumerable [[maybe_unused]]) {
-    Ns* priv = priv_from_js(cx, obj);
-
-    if (!priv) {
-        return true;
-    }
-
-    int n = g_irepository_get_n_infos(nullptr, priv->get());
+bool Ns::new_enumerate_impl(JSContext* cx,
+                            JS::HandleObject obj [[maybe_unused]],
+                            JS::MutableHandleIdVector properties,
+                            bool only_enumerable [[maybe_unused]]) {
+    int n = g_irepository_get_n_infos(nullptr, get());
     if (!properties.reserve(properties.length() + n)) {
         JS_ReportOutOfMemory(cx);
         return false;
     }
 
     for (int k = 0; k < n; k++) {
-        GjsAutoBaseInfo info = g_irepository_get_info(nullptr, priv->get(), k);
+        GjsAutoBaseInfo info = g_irepository_get_info(nullptr, get(), k);
         const char* name = info.name();
 
         jsid id = gjs_intern_string_to_id(cx, name);
@@ -130,85 +151,48 @@ static bool ns_new_enumerate(JSContext* cx, JS::HandleObject obj,
     return true;
 }
 
-GJS_JSAPI_RETURN_CONVENTION
-static bool
-get_name (JSContext *context,
-          unsigned   argc,
-          JS::Value *vp)
-{
-    GJS_GET_PRIV(context, argc, vp, args, obj, Ns, priv);
-
-    if (!priv)
-        return false;
-
-    return gjs_string_from_utf8(context, priv->get(), args.rval());
+bool Ns::get_name(JSContext* cx, unsigned argc, JS::Value* vp) {
+    GJS_GET_WRAPPER_PRIV(cx, argc, vp, args, this_obj, Ns, priv);
+    return gjs_string_from_utf8(cx, priv->get(), args.rval());
 }
 
-GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(ns)
-
-static void ns_finalize(JSFreeOp*, JSObject* obj) {
-    Ns *priv;
-
-    priv = (Ns *)JS_GetPrivate(obj);
-    gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE,
-                        "finalize, obj %p priv %p", obj, priv);
-    if (!priv)
-        return; /* we are the prototype, not a real instance */
-
+void Ns::finalize_impl(JSFreeOp*, Ns* priv) {
+    g_assert(priv && "Finalize called on wrong object");
     GJS_DEC_COUNTER(ns);
     delete priv;
 }
 
-/* The bizarre thing about this vtable is that it applies to both
- * instances of the object, and to the prototype that instances of the
- * class have.
- */
 // clang-format off
-static const struct JSClassOps gjs_ns_class_ops = {
+const JSClassOps Ns::class_ops = {
     nullptr,  // addProperty
     nullptr,  // deleteProperty
     nullptr,  // enumerate
-    ns_new_enumerate,
-    ns_resolve,
+    &Ns::new_enumerate,
+    &Ns::resolve,
     nullptr,  // mayResolve
-    ns_finalize};
-
-struct JSClass gjs_ns_class = {
-    "GIRepositoryNamespace",
-    JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE,
-    &gjs_ns_class_ops
+    &Ns::finalize,
 };
 
-static JSPropertySpec gjs_ns_proto_props[] = {
+const JSPropertySpec Ns::proto_props[] = {
     JS_STRING_SYM_PS(toStringTag, "GIRepositoryNamespace", JSPROP_READONLY),
-    JS_PSG("__name__", get_name, GJS_MODULE_PROP_FLAGS),
+    JS_PSG("__name__", &Ns::get_name, GJS_MODULE_PROP_FLAGS),
     JS_PS_END
 };
 // clang-format on
 
-static JSFunctionSpec *gjs_ns_proto_funcs = nullptr;
-static JSFunctionSpec *gjs_ns_static_funcs = nullptr;
-
-GJS_DEFINE_PROTO_FUNCS(ns)
-
-GJS_JSAPI_RETURN_CONVENTION
-static JSObject*
-ns_new(JSContext    *context,
-       const char   *ns_name)
-{
-    JS::RootedObject proto(context);
-    if (!gjs_ns_define_proto(context, nullptr, &proto))
+JSObject* Ns::create(JSContext* cx, const char* ns_name) {
+    JS::RootedObject proto(cx, Ns::create_prototype(cx));
+    if (!proto)
         return nullptr;
 
-    JS::RootedObject ns(context,
-        JS_NewObjectWithGivenProto(context, &gjs_ns_class, proto));
+    JS::RootedObject ns(cx, JS_NewObjectWithGivenProto(cx, &Ns::klass, proto));
     if (!ns)
         return nullptr;
 
     auto* priv = new Ns(ns_name);
     GJS_INC_COUNTER(ns);
 
-    g_assert(!priv_from_js(context, ns));
+    g_assert(!JS_GetPrivate(ns));
     JS_SetPrivate(ns, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE, "ns constructor, obj %p priv %p",
@@ -221,5 +205,5 @@ JSObject*
 gjs_create_ns(JSContext    *context,
               const char   *ns_name)
 {
-    return ns_new(context, ns_name);
+    return Ns::create(context, ns_name);
 }


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