[gjs/burninate-macros: 2/13] importer: Remove JSClass macros



commit a3b5d3ee882dbe6278f0c883d5fa608965eea8b4
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Apr 7 22:17:53 2020 -0700

    importer: Remove JSClass macros
    
    FIXME: Need commit message
    FIXME: do we really need the IsRoot bit? Can the GjsContext determine if
    an importer object is the root importer instead, so we only need one
    pointer in one place instead of a JS::Value on every importer?

 gjs/importer.cpp  | 141 +++++++++++++++++++-----------------------------------
 gjs/mem-private.h |   1 -
 2 files changed, 50 insertions(+), 92 deletions(-)
---
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index d294301c..18edd6f4 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -56,10 +56,10 @@
 
 #include "gjs/atoms.h"
 #include "gjs/context-private.h"
+#include "gjs/global.h"
 #include "gjs/importer.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/mem-private.h"
 #include "gjs/module.h"
 #include "gjs/native.h"
 #include "util/log.h"
@@ -67,33 +67,31 @@
 
 #define MODULE_INIT_FILENAME "__init__.js"
 
-typedef struct {
-    bool is_root;
-} Importer;
+enum ImporterSlot { IsRoot, Last };
 
 extern const JSClass gjs_importer_class;
 
-GJS_DEFINE_PRIV_FROM_JS(Importer, gjs_importer_class)
-
 GJS_JSAPI_RETURN_CONVENTION
 static JSObject* gjs_define_importer(JSContext*, JS::HandleObject, const char*,
                                      const std::vector<std::string>&, bool);
 
+static bool importer_is_root(JSObject* importer) {
+    return JS_GetReservedSlot(importer, ImporterSlot::IsRoot).toBoolean();
+}
+
 GJS_JSAPI_RETURN_CONVENTION
 static bool
 importer_to_string(JSContext *cx,
                    unsigned   argc,
                    JS::Value *vp)
 {
-    GJS_GET_PRIV(cx, argc, vp, args, importer, Importer, priv);
+    GJS_GET_THIS(cx, argc, vp, args, importer);
 
     GjsAutoChar output;
 
     const JSClass* klass = JS_GetClass(importer);
 
-    if (!priv) {
-        output = g_strdup_printf("[%s prototype]", klass->name);
-    } else if (priv->is_root) {
+    if (importer_is_root(importer)) {
         output = g_strdup_printf("[%s root]", klass->name);
     } else {
         const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
@@ -469,7 +467,7 @@ import_file_on_module(JSContext       *context,
 }
 
 GJS_JSAPI_RETURN_CONVENTION
-static bool do_import(JSContext* context, JS::HandleObject obj, Importer* priv,
+static bool do_import(JSContext* context, JS::HandleObject obj,
                       JS::HandleId id) {
     JS::RootedObject search_path(context);
     guint32 search_path_len;
@@ -502,7 +500,7 @@ static bool do_import(JSContext* context, JS::HandleObject obj, Importer* priv,
     }
 
     /* First try importing an internal module like gi */
-    if (priv->is_root && gjs_is_registered_native_module(name.get())) {
+    if (importer_is_root(obj) && gjs_is_registered_native_module(name.get())) {
         if (!gjs_import_native_module(context, obj, name.get()))
             return false;
 
@@ -612,25 +610,15 @@ static bool do_import(JSContext* context, JS::HandleObject obj, Importer* priv,
     return false;
 }
 
-/* Note that in a for ... in loop, this will be called first on the object,
- * then on its prototype.
- */
 GJS_JSAPI_RETURN_CONVENTION
 static bool importer_new_enumerate(JSContext* context, JS::HandleObject object,
                                    JS::MutableHandleIdVector properties,
                                    bool enumerable_only G_GNUC_UNUSED) {
-    Importer *priv;
     guint32 search_path_len;
     guint32 i;
     bool is_array;
     const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
 
-    priv = priv_from_js(context, object);
-
-    if (!priv)
-        /* we are enumerating the prototype properties */
-        return true;
-
     JS::RootedObject search_path(context);
     if (!gjs_object_require_property(context, object, "importer",
                                      atoms.search_path(), &search_path))
@@ -740,8 +728,6 @@ importer_resolve(JSContext        *context,
                  JS::HandleId      id,
                  bool             *resolved)
 {
-    Importer *priv;
-
     if (!JSID_IS_STRING(id)) {
         *resolved = false;
         return true;
@@ -754,104 +740,40 @@ importer_resolve(JSContext        *context,
         return true;
     }
 
-    priv = priv_from_js(context, obj);
-
     gjs_debug_jsprop(GJS_DEBUG_IMPORTER,
                      "Resolve prop '%s' hook, obj %s, priv %p",
                      gjs_debug_id(id).c_str(), gjs_debug_object(obj).c_str(), priv);
-    if (!priv) {
-        /* we are the prototype, or have the wrong class */
-        *resolved = false;
-        return true;
-    }
 
     if (!JSID_IS_STRING(id)) {
         *resolved = false;
         return true;
     }
 
-    if (!do_import(context, obj, priv, id))
+    if (!do_import(context, obj, id))
         return false;
 
     *resolved = true;
     return true;
 }
 
-GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(importer)
-
-static void importer_finalize(JSFreeOp*, JSObject* obj) {
-    Importer *priv;
-
-    priv = (Importer*) JS_GetPrivate(obj);
-    gjs_debug_lifecycle(GJS_DEBUG_IMPORTER,
-                        "finalize, obj %p priv %p", obj, priv);
-    if (!priv)
-        return; /* we are the prototype, not a real instance */
-
-    GJS_DEC_COUNTER(importer);
-    g_slice_free(Importer, 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.
- */
 static const JSClassOps gjs_importer_class_ops = {
     nullptr,  // addProperty
     nullptr,  // deleteProperty
     nullptr,  // enumerate
     importer_new_enumerate,
     importer_resolve,
-    nullptr,  // mayResolve
-    importer_finalize
 };
 
 const JSClass gjs_importer_class = {
     "GjsFileImporter",
-    JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE,
+    JSCLASS_HAS_RESERVED_SLOTS(ImporterSlot::Last),
     &gjs_importer_class_ops,
 };
 
-static JSPropertySpec *gjs_importer_proto_props = nullptr;
-static JSFunctionSpec *gjs_importer_static_funcs = nullptr;
-
 JSFunctionSpec gjs_importer_proto_funcs[] = {
     JS_FN("toString", importer_to_string, 0, 0),
     JS_FS_END};
 
-GJS_DEFINE_PROTO_FUNCS(importer)
-
-GJS_JSAPI_RETURN_CONVENTION
-static JSObject*
-importer_new(JSContext *context,
-             bool       is_root)
-{
-    Importer *priv;
-
-    JS::RootedObject proto(context);
-    if (!gjs_importer_define_proto(context, nullptr, &proto))
-        return nullptr;
-
-    JS::RootedObject importer(context,
-        JS_NewObjectWithGivenProto(context, &gjs_importer_class, proto));
-    if (!importer)
-        return nullptr;
-
-    priv = g_slice_new0(Importer);
-    priv->is_root = is_root;
-
-    GJS_INC_COUNTER(importer);
-
-    g_assert(priv_from_js(context, importer) == NULL);
-    JS_SetPrivate(importer, priv);
-
-    gjs_debug_lifecycle(GJS_DEBUG_IMPORTER,
-                        "importer constructor, obj %p priv %p", importer.get(),
-                        priv);
-
-    return importer;
-}
-
 GJS_USE
 static const std::vector<std::string>& gjs_get_search_path(void) {
     static std::vector<std::string> gjs_search_path;
@@ -904,6 +826,28 @@ static const std::vector<std::string>& gjs_get_search_path(void) {
     return gjs_search_path;
 }
 
+GJS_JSAPI_RETURN_CONVENTION
+static JSObject* gjs_importer_define_proto(JSContext* cx) {
+    // If we've been here more than once, we already have the proto
+    JS::RootedValue v_proto(
+        cx, gjs_get_global_slot(cx, GJS_GLOBAL_SLOT_PROTOTYPE_importer));
+    if (!v_proto.isUndefined()) {
+        g_assert(v_proto.isObject() &&
+                 "Someone stored some weird value in a global slot");
+        return &v_proto.toObject();
+    }
+
+    JS::RootedObject proto(cx, JS_NewPlainObject(cx));
+    if (!proto || !JS_DefineFunctions(cx, proto, gjs_importer_proto_funcs))
+        return nullptr;
+    gjs_set_global_slot(cx, GJS_GLOBAL_SLOT_PROTOTYPE_importer,
+                        JS::ObjectValue(*proto));
+
+    gjs_debug(GJS_DEBUG_CONTEXT, "Initialized class %s prototype %p",
+              gjs_importer_class.name, proto.get());
+    return proto;
+}
+
 GJS_JSAPI_RETURN_CONVENTION
 static JSObject* gjs_create_importer(
     JSContext* context, const char* importer_name,
@@ -917,7 +861,22 @@ static JSObject* gjs_create_importer(
                             gjs_search_path.end());
     }
 
-    JS::RootedObject importer(context, importer_new(context, is_root));
+    JS::RootedObject proto(context, gjs_importer_define_proto(context));
+    if (!proto)
+        return nullptr;
+
+    JS::RootedObject importer(
+        context,
+        JS_NewObjectWithGivenProto(context, &gjs_importer_class, proto));
+    if (!importer)
+        return nullptr;
+
+    JS_SetReservedSlot(importer, ImporterSlot::IsRoot,
+                       JS::BooleanValue(is_root));
+
+    gjs_debug_lifecycle(GJS_DEBUG_IMPORTER,
+                        "importer constructor, obj %p priv %p", importer.get(),
+                        priv);
 
     /* API users can replace this property from JS, is the idea */
     if (!gjs_define_string_array(
diff --git a/gjs/mem-private.h b/gjs/mem-private.h
index f46d4025..c4480e65 100644
--- a/gjs/mem-private.h
+++ b/gjs/mem-private.h
@@ -41,7 +41,6 @@ typedef struct {
     macro(fundamental_prototype)    \
     macro(gerror_instance)          \
     macro(gerror_prototype)         \
-    macro(importer)                 \
     macro(interface)                \
     macro(module)                   \
     macro(ns)                       \


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