[gjs/wip/ptomato/mozjs52: 9/20] js: New JSClass struct layout



commit 253d1fc6601607ef91ed1751be324498cae645ee
Author: Philip Chimento <philip chimento gmail com>
Date:   Mon May 1 22:44:34 2017 -0700

    js: New JSClass struct layout
    
    Instead of the various operation hooks being members of JSClass directly,
    now JSClass contains a pointer to a JSClassOps struct. The JSClassOps
    instead contains the function pointers to the operation hooks.
    
    For importer.cpp, we still use the internal js::Class instead of JSClass.
    This also contains a pointer to another struct, JSObjectOps, which we still
    need for our internal lazy enumerate hook.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=784196

 gi/boxed.cpp                |   21 ++++++++++--------
 gi/function.cpp             |   11 ++++++---
 gi/fundamental.cpp          |   15 ++++++-------
 gi/gerror.cpp               |   11 ++++++---
 gi/interface.cpp            |   11 ++++++---
 gi/ns.cpp                   |   10 ++++++--
 gi/object.cpp               |   11 ++++++---
 gi/param.cpp                |   11 ++++++---
 gi/repo.cpp                 |   10 ++++++--
 gi/union.cpp                |   10 ++++++--
 gjs/byteArray.cpp           |   11 ++++++---
 gjs/global.cpp              |   11 +++++++--
 gjs/importer.cpp            |   49 ++++++++++++++++++++++---------------------
 gjs/jsapi-class.h           |    9 +++++--
 gjs/jsapi-dynamic-class.cpp |    4 +-
 gjs/module.cpp              |   11 +++++++--
 test/gjs-test-rooting.cpp   |   10 ++++++--
 17 files changed, 138 insertions(+), 88 deletions(-)
---
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 361165c..b31920f 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -913,16 +913,8 @@ boxed_trace(JSTracer *tracer,
 /* 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.
- *
- * We allocate 1 reserved slot; this is typically unused, but if the
- * boxed is for a nested structure inside a parent structure, the
- * reserved slot is used to hold onto the parent Javascript object and
- * make sure it doesn't get freed.
  */
-struct JSClass gjs_boxed_class = {
-    "GObject_Boxed",
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_HAS_RESERVED_SLOTS(1),
+static const struct JSClassOps gjs_boxed_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -937,6 +929,17 @@ struct JSClass gjs_boxed_class = {
     boxed_trace
 };
 
+/* We allocate 1 reserved slot; this is typically unused, but if the
+ * boxed is for a nested structure inside a parent structure, the
+ * reserved slot is used to hold onto the parent Javascript object and
+ * make sure it doesn't get freed.
+ */
+struct JSClass gjs_boxed_class = {
+    "GObject_Boxed",
+    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
+    &gjs_boxed_class_ops
+};
+
 JSPropertySpec gjs_boxed_proto_props[] = {
     JS_PS_END
 };
diff --git a/gi/function.cpp b/gi/function.cpp
index 074904d..70306cd 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -1483,10 +1483,7 @@ function_to_string (JSContext *context,
  * instances of the object, and to the prototype that instances of the
  * class have.
  */
-struct JSClass gjs_function_class = {
-    "GIRepositoryFunction", /* means "new GIRepositoryFunction()" works */
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_BACKGROUND_FINALIZE,
+static const struct JSClassOps gjs_function_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -1498,6 +1495,12 @@ struct JSClass gjs_function_class = {
     function_call
 };
 
+struct JSClass gjs_function_class = {
+    "GIRepositoryFunction", /* means "new GIRepositoryFunction()" works */
+    JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+    &gjs_function_class_ops
+};
+
 static JSPropertySpec gjs_function_proto_props[] = {
     JS_PSG("length", get_num_arguments, JSPROP_PERMANENT),
     JS_PS_END
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index dcacd1b..96a7fc5 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -543,15 +543,8 @@ fundamental_trace(JSTracer *tracer,
  * tell, it would only be used if no constructor were provided to
  * JS_InitClass. The constructor from JS_InitClass is not applied to
  * the prototype unless JSCLASS_CONSTRUCT_PROTOTYPE is in flags.
- *
- * We allocate 1 reserved slot; this is typically unused, but if the
- * fundamental is for a nested structure inside a parent structure, the
- * reserved slot is used to hold onto the parent Javascript object and
- * make sure it doesn't get freed.
  */
-struct JSClass gjs_fundamental_instance_class = {
-    "GFundamental_Object",
-    JSCLASS_HAS_PRIVATE,
+static const struct JSClassOps gjs_fundamental_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -566,6 +559,12 @@ struct JSClass gjs_fundamental_instance_class = {
     fundamental_trace
 };
 
+struct JSClass gjs_fundamental_instance_class = {
+    "GFundamental_Object",
+    JSCLASS_HAS_PRIVATE,
+    &gjs_fundamental_class_ops
+};
+
 static JSPropertySpec gjs_fundamental_instance_proto_props[] = {
     JS_PS_END
 };
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index e6f894d..7a63e17 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -267,10 +267,7 @@ error_constructor_value_of(JSContext *context,
  * instances of the object, and to the prototype that instances of the
  * class have.
  */
-struct JSClass gjs_error_class = {
-    "GLib_Error",
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_BACKGROUND_FINALIZE,
+static const struct JSClassOps gjs_error_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -281,6 +278,12 @@ struct JSClass gjs_error_class = {
     error_finalize
 };
 
+struct JSClass gjs_error_class = {
+    "GLib_Error",
+    JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+    &gjs_error_class_ops
+};
+
 /* We need to shadow all fields of GError, to prevent calling the getter from GBoxed
    (which would trash memory accessing the instance private data) */
 JSPropertySpec gjs_error_proto_props[] = {
diff --git a/gi/interface.cpp b/gi/interface.cpp
index 40a4209..361f5bc 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -157,10 +157,7 @@ interface_resolve(JSContext       *context,
     return true;
 }
 
-struct JSClass gjs_interface_class = {
-    "GObject_Interface",
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_BACKGROUND_FINALIZE,
+static const struct JSClassOps gjs_interface_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -171,6 +168,12 @@ struct JSClass gjs_interface_class = {
     interface_finalize
 };
 
+struct JSClass gjs_interface_class = {
+    "GObject_Interface",
+    JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+    &gjs_interface_class_ops
+};
+
 JSPropertySpec gjs_interface_proto_props[] = {
     JS_PS_END
 };
diff --git a/gi/ns.cpp b/gi/ns.cpp
index 6c7b756..5fc9ca0 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -151,9 +151,7 @@ ns_finalize(JSFreeOp *fop,
  * instances of the object, and to the prototype that instances of the
  * class have.
  */
-struct JSClass gjs_ns_class = {
-    "GIRepositoryNamespace",
-    JSCLASS_HAS_PRIVATE,
+static const struct JSClassOps gjs_ns_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -164,6 +162,12 @@ struct JSClass gjs_ns_class = {
     ns_finalize
 };
 
+struct JSClass gjs_ns_class = {
+    "GIRepositoryNamespace",
+    JSCLASS_HAS_PRIVATE,
+    &gjs_ns_class_ops
+};
+
 static JSPropertySpec gjs_ns_proto_props[] = {
     JS_PSG("__name__", get_name, GJS_MODULE_PROP_FLAGS),
     JS_PS_END
diff --git a/gi/object.cpp b/gi/object.cpp
index 37447fe..bb1ce33 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1793,9 +1793,7 @@ to_string_func(JSContext *context,
                                      priv->gobj, rec.rval());
 }
 
-struct JSClass gjs_object_instance_class = {
-    "GObject_Object",
-    JSCLASS_HAS_PRIVATE,
+static const struct JSClassOps gjs_object_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     object_instance_get_prop,
@@ -1808,7 +1806,12 @@ struct JSClass gjs_object_instance_class = {
     NULL,
     NULL,
     object_instance_trace,
-    
+};
+
+struct JSClass gjs_object_instance_class = {
+    "GObject_Object",
+    JSCLASS_HAS_PRIVATE,
+    &gjs_object_class_ops
 };
 
 static bool
diff --git a/gi/param.cpp b/gi/param.cpp
index 1693858..2806d2a 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -142,10 +142,7 @@ param_finalize(JSFreeOp *fop,
  * instances of the object, and to the prototype that instances of the
  * class have.
  */
-struct JSClass gjs_param_class = {
-    "GObject_ParamSpec",
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_BACKGROUND_FINALIZE,
+static const struct JSClassOps gjs_param_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -156,6 +153,12 @@ struct JSClass gjs_param_class = {
     param_finalize
 };
 
+struct JSClass gjs_param_class = {
+    "GObject_ParamSpec",
+    JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+    &gjs_param_class_ops
+};
+
 JSPropertySpec gjs_param_proto_props[] = {
     JS_PS_END
 };
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 517858f..fce4193 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -216,9 +216,7 @@ repo_finalize(JSFreeOp *fop,
  * instances of the object, and to the prototype that instances of the
  * class have.
  */
-struct JSClass gjs_repo_class = {
-    "GIRepository", /* means "new GIRepository()" works */
-    JSCLASS_HAS_PRIVATE,
+static const struct JSClassOps gjs_repo_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -229,6 +227,12 @@ struct JSClass gjs_repo_class = {
     repo_finalize
 };
 
+struct JSClass gjs_repo_class = {
+    "GIRepository", /* means "new GIRepository()" works */
+    JSCLASS_HAS_PRIVATE,
+    &gjs_repo_class_ops,
+};
+
 static JSPropertySpec *gjs_repo_proto_props = nullptr;
 static JSFunctionSpec *gjs_repo_proto_funcs = nullptr;
 static JSFunctionSpec *gjs_repo_static_funcs = nullptr;
diff --git a/gi/union.cpp b/gi/union.cpp
index f358524..aa54a1f 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -287,9 +287,7 @@ to_string_func(JSContext *context,
  * instances of the object, and to the prototype that instances of the
  * class have.
  */
-struct JSClass gjs_union_class = {
-    "GObject_Union",
-    JSCLASS_HAS_PRIVATE,
+static const struct JSClassOps gjs_union_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -300,6 +298,12 @@ struct JSClass gjs_union_class = {
     union_finalize
 };
 
+struct JSClass gjs_union_class = {
+    "GObject_Union",
+    JSCLASS_HAS_PRIVATE,
+    &gjs_union_class_ops
+};
+
 JSPropertySpec gjs_union_proto_props[] = {
     JS_PS_END
 };
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 1fbd787..88b38e2 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -55,10 +55,7 @@ static void   byte_array_finalize      (JSFreeOp     *fop,
 
 static JSObject *gjs_byte_array_get_proto(JSContext *);
 
-struct JSClass gjs_byte_array_class = {
-    "ByteArray",
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_BACKGROUND_FINALIZE,
+static const struct JSClassOps gjs_byte_array_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     byte_array_get_prop,
@@ -69,6 +66,12 @@ struct JSClass gjs_byte_array_class = {
     byte_array_finalize
 };
 
+struct JSClass gjs_byte_array_class = {
+    "ByteArray",
+    JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+    &gjs_byte_array_class_ops
+};
+
 bool
 gjs_typecheck_bytearray(JSContext       *context,
                         JS::HandleObject object,
diff --git a/gjs/global.cpp b/gjs/global.cpp
index 7993b7e..f0503b2 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -172,9 +172,7 @@ gjs_printerr(JSContext *context,
 }
 
 class GjsGlobal {
-    static constexpr JSClass klass = {
-        "GjsGlobal",
-        JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(GJS_GLOBAL_SLOT_LAST),
+    static constexpr JSClassOps class_ops = {
         nullptr,  /* addProperty */
         nullptr,  /* deleteProperty */
         nullptr,  /* getProperty */
@@ -189,6 +187,12 @@ class GjsGlobal {
         JS_GlobalObjectTraceHook
     };
 
+    static constexpr JSClass klass = {
+        "GjsGlobal",
+        JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(GJS_GLOBAL_SLOT_LAST),
+        &GjsGlobal::class_ops,
+    };
+
     static constexpr JSFunctionSpec static_funcs[] = {
         JS_FS("log", gjs_log, 1, GJS_MODULE_PROP_FLAGS),
         JS_FS("logError", gjs_log_error, 2, GJS_MODULE_PROP_FLAGS),
@@ -347,5 +351,6 @@ gjs_get_global_slot(JSContext    *cx,
     return JS_GetReservedSlot(global, JSCLASS_GLOBAL_SLOT_COUNT + slot);
 }
 
+decltype(GjsGlobal::class_ops) constexpr GjsGlobal::class_ops;
 decltype(GjsGlobal::klass) constexpr GjsGlobal::klass;
 decltype(GjsGlobal::static_funcs) constexpr GjsGlobal::static_funcs;
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index eec0681..c4b2b96 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -830,9 +830,7 @@ importer_finalize(js::FreeOp *fop,
  * instances of the object, and to the prototype that instances of the
  * class have.
  */
-const js::Class gjs_importer_real_class = {
-    "GjsFileImporter",
-    JSCLASS_HAS_PRIVATE,
+static const js::ClassOps gjs_importer_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -840,27 +838,30 @@ const js::Class gjs_importer_real_class = {
     NULL,  /* enumerate (see below) */
     importer_resolve,
     nullptr,  /* mayResolve */
-    importer_finalize,
-    NULL,  /* call */
-    NULL,  /* hasInstance */
-    NULL,  /* construct */
-    NULL,  /* trace */
-    JS_NULL_CLASS_SPEC,
-    JS_NULL_CLASS_EXT,
-    {
-        NULL,  /* lookupProperty */
-        NULL,  /* defineProperty */
-        NULL,  /* hasProperty */
-        NULL,  /* getProperty */
-        NULL,  /* setProperty */
-        NULL,  /* getOwnPropertyDescriptor */
-        NULL,  /* deleteProperty */
-        NULL,  /* watch */
-        NULL,  /* unwatch */
-        NULL,  /* getElements */
-        importer_enumerate,
-        NULL,  /* thisObject */
-    }
+    importer_finalize
+};
+
+static const js::ObjectOps gjs_importer_object_ops = {
+    NULL,  /* lookupProperty */
+    NULL,  /* defineProperty */
+    NULL,  /* hasProperty */
+    NULL,  /* getProperty */
+    NULL,  /* setProperty */
+    NULL,  /* getOwnPropertyDescriptor */
+    NULL,  /* deleteProperty */
+    NULL,  /* watch */
+    NULL,  /* unwatch */
+    NULL,  /* getElements */
+    importer_enumerate
+};
+
+const js::Class gjs_importer_real_class = {
+    "GjsFileImporter",
+    JSCLASS_HAS_PRIVATE,
+    &gjs_importer_class_ops,
+    nullptr,
+    nullptr,
+    &gjs_importer_object_ops
 };
 
 static JSPropertySpec *gjs_importer_proto_props = nullptr;
diff --git a/gjs/jsapi-class.h b/gjs/jsapi-class.h
index 8b773ed..29c44be 100644
--- a/gjs/jsapi-class.h
+++ b/gjs/jsapi-class.h
@@ -171,9 +171,7 @@ extern JSPropertySpec gjs_##cname##_proto_props[];                           \
 extern JSFunctionSpec gjs_##cname##_proto_funcs[];                           \
 extern JSFunctionSpec gjs_##cname##_static_funcs[];                          \
 static void gjs_##cname##_finalize(JSFreeOp *fop, JSObject *obj);            \
-static struct JSClass gjs_##cname##_class = {                                \
-    type_name,                                                               \
-    JSCLASS_HAS_PRIVATE | jsclass_flags,                                     \
+static const struct JSClassOps gjs_##cname##_class_ops = {                   \
     nullptr,  /* addProperty */                                              \
     nullptr,  /* deleteProperty */                                           \
     nullptr,  /* getProperty */                                              \
@@ -183,6 +181,11 @@ static struct JSClass gjs_##cname##_class = {                                \
     nullptr,  /* mayResolve */                                               \
     gjs_##cname##_finalize                                                   \
 };                                                                           \
+static struct JSClass gjs_##cname##_class = {                                \
+    type_name,                                                               \
+    JSCLASS_HAS_PRIVATE | jsclass_flags,                                     \
+    &gjs_##cname##_class_ops                                                 \
+};                                                                           \
 _GJS_DEFINE_GET_PROTO(cname)                                                 \
 _GJS_DEFINE_DEFINE_PROTO(cname, parent_cname, ctor, gtype)
 
diff --git a/gjs/jsapi-dynamic-class.cpp b/gjs/jsapi-dynamic-class.cpp
index d0e947b..a660c19 100644
--- a/gjs/jsapi-dynamic-class.cpp
+++ b/gjs/jsapi-dynamic-class.cpp
@@ -88,7 +88,7 @@ gjs_init_class_dynamic(JSContext              *context,
         goto out;
 
     /* Bypass resolve hooks when defining the initial properties */
-    if (clasp->resolve) {
+    if (clasp->cOps->resolve) {
         JSPropertySpec *ps_iter;
         JSFunctionSpec *fs_iter;
         for (ps_iter = proto_ps; ps_iter && ps_iter->name; ps_iter++)
@@ -115,7 +115,7 @@ gjs_init_class_dynamic(JSContext              *context,
     if (static_fs && !JS_DefineFunctions(context, constructor, static_fs))
         goto out;
 
-    if (!clasp->resolve) {
+    if (!clasp->cOps->resolve) {
         if (!JS_LinkConstructorAndPrototype(context, constructor, prototype))
             goto out;
     } else {
diff --git a/gjs/module.cpp b/gjs/module.cpp
index e58206b..5028d06 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -145,9 +145,7 @@ class GjsModule {
         delete priv(module);
     }
 
-    static constexpr JSClass klass = {
-        "GjsModule",
-        JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+    static constexpr JSClassOps class_ops = {
         nullptr,  /* addProperty */
         nullptr,  /* deleteProperty */
         nullptr,  /* getProperty */
@@ -158,6 +156,12 @@ class GjsModule {
         &GjsModule::finalize,
     };
 
+    static constexpr JSClass klass = {
+        "GjsModule",
+        JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+        &GjsModule::class_ops,
+    };
+
 public:
 
     /* Carries out the import operation */
@@ -205,3 +209,4 @@ gjs_module_import(JSContext       *cx,
 }
 
 decltype(GjsModule::klass) constexpr GjsModule::klass;
+decltype(GjsModule::class_ops) constexpr GjsModule::class_ops;
diff --git a/test/gjs-test-rooting.cpp b/test/gjs-test-rooting.cpp
index 8e2ab1d..7ab5f4a 100644
--- a/test/gjs-test-rooting.cpp
+++ b/test/gjs-test-rooting.cpp
@@ -26,9 +26,7 @@ test_obj_finalize(JSFreeOp *fop,
     *finalized_p = true;
 }
 
-static JSClass test_obj_class = {
-    "TestObj",
-    JSCLASS_HAS_PRIVATE,
+static const JSClassOps test_obj_class_ops = {
     NULL,  /* addProperty */
     NULL,  /* deleteProperty */
     NULL,  /* getProperty */
@@ -39,6 +37,12 @@ static JSClass test_obj_class = {
     test_obj_finalize
 };
 
+static JSClass test_obj_class = {
+    "TestObj",
+    JSCLASS_HAS_PRIVATE,
+    &test_obj_class_ops
+};
+
 static JSObject *
 test_obj_new(GjsRootingFixture *fx)
 {


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