[gjs/wip/ptomato/mozjs45prep: 38/39] WIP - create all native objects with JS_NewObjectWithGivenProto



commit 83d311e070bd44d784750d9658278ddadc811bc3
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Apr 11 23:44:52 2017 -0700

    WIP - create all native objects with JS_NewObjectWithGivenProto

 gi/function.cpp  |   57 +++++++++++++++++----------------------------------
 gi/ns.cpp        |   53 +++++++++-------------------------------------
 gjs/importer.cpp |   60 +++++++++++++----------------------------------------
 gjs/jsapi-util.h |   25 +++++++++++++++++++--
 4 files changed, 67 insertions(+), 128 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index 5f7068a..f8bfc25 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -1497,18 +1497,20 @@ struct JSClass gjs_function_class = {
     function_call
 };
 
-JSPropertySpec gjs_function_proto_props[] = {
+static JSPropertySpec gjs_function_proto_props[] = {
     JS_PSG("length", get_num_arguments, JSPROP_PERMANENT),
     JS_PS_END
 };
 
 /* The original Function.prototype.toString complains when
    given a GIRepository function as an argument */
-JSFunctionSpec gjs_function_proto_funcs[] = {
+static JSFunctionSpec gjs_function_proto_funcs[] = {
     JS_FN("toString", function_to_string, 0, 0),
     JS_FS_END
 };
 
+static JSFunctionSpec *gjs_function_static_funcs = nullptr;
+
 static bool
 init_cached_function_data (JSContext      *context,
                            Function       *function,
@@ -1657,51 +1659,30 @@ init_cached_function_data (JSContext      *context,
     return true;
 }
 
+static bool
+gjs_builtin_function_ensure_proto(JSContext              *cx,
+                                  JS::MutableHandleObject proto)
+{
+    JS::RootedObject global(cx, gjs_get_import_global(cx));
+    proto.set(JS_GetFunctionPrototype(cx, global));
+    return true;
+}
+
+GJS_DEFINE_ENSURE_PROTO_WITH_PARENT(function, builtin_function)
+
 static JSObject*
 function_new(JSContext      *context,
              GType           gtype,
              GICallableInfo *info)
 {
     Function *priv;
-    bool found;
-
-    /* put constructor for GIRepositoryFunction() in the global namespace */
-    JS::RootedObject global(context, gjs_get_import_global(context));
 
-    if (!JS_HasProperty(context, global, gjs_function_class.name, &found))
-        return NULL;
-
-    if (!found) {
-        JSObject *prototype;
-        JS::RootedObject function_proto(context,
-                                        JS_GetFunctionPrototype(context, global));
-
-        prototype = JS_InitClass(context, global, function_proto,
-                                 &gjs_function_class,
-                                 /* constructor for instances (NULL for
-                                  * none - just name the prototype like
-                                  * Math - rarely correct)
-                                  */
-                                 gjs_function_constructor,
-                                 /* number of constructor args */
-                                 0,
-                                 /* props of prototype */
-                                 &gjs_function_proto_props[0],
-                                 /* funcs of prototype */
-                                 &gjs_function_proto_funcs[0],
-                                 /* props of constructor, MyConstructor.myprop */
-                                 NULL,
-                                 /* funcs of constructor, MyConstructor.myfunc() */
-                                 NULL);
-        if (prototype == NULL)
-            g_error("Can't init class %s", gjs_function_class.name);
-
-        gjs_debug(GJS_DEBUG_GFUNCTION, "Initialized class %s prototype %p",
-                  gjs_function_class.name, prototype);
-    }
+    JS::RootedObject prototype(context);
+    if (!gjs_function_ensure_proto(context, &prototype))
+        return nullptr;
 
     JS::RootedObject function(context,
-                              JS_NewObject(context, &gjs_function_class));
+        JS_NewObjectWithGivenProto(context, &gjs_function_class, prototype));
     if (function == NULL) {
         gjs_debug(GJS_DEBUG_GFUNCTION, "Failed to construct function");
         return NULL;
diff --git a/gi/ns.cpp b/gi/ns.cpp
index f758e2c..d4eef29 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -168,59 +168,28 @@ struct JSClass gjs_ns_class = {
     ns_finalize
 };
 
-JSPropertySpec gjs_ns_proto_props[] = {
+static JSPropertySpec gjs_ns_proto_props[] = {
     JS_PSG("__name__", get_name, GJS_MODULE_PROP_FLAGS),
     JS_PS_END
 };
 
-JSFunctionSpec gjs_ns_proto_funcs[] = {
-    JS_FS_END
-};
+static JSFunctionSpec *gjs_ns_proto_funcs = nullptr;
+static JSFunctionSpec *gjs_ns_static_funcs = nullptr;
+
+GJS_DEFINE_ENSURE_PROTO(ns)
 
 static JSObject*
 ns_new(JSContext    *context,
        const char   *ns_name)
 {
     Ns *priv;
-    bool found;
-
-    /* put constructor in the global namespace */
-    JS::RootedObject global(context, gjs_get_import_global(context));
-
-    if (!JS_HasProperty(context, global, gjs_ns_class.name, &found))
-        return NULL;
-    if (!found) {
-        JSObject *prototype;
-        prototype = JS_InitClass(context, global,
-                                 /* parent prototype JSObject* for
-                                  * prototype; NULL for
-                                  * Object.prototype
-                                  */
-                                 nullptr,
-                                 &gjs_ns_class,
-                                 /* constructor for instances (NULL for
-                                  * none - just name the prototype like
-                                  * Math - rarely correct)
-                                  */
-                                 gjs_ns_constructor,
-                                 /* number of constructor args */
-                                 0,
-                                 /* props of prototype */
-                                 &gjs_ns_proto_props[0],
-                                 /* funcs of prototype */
-                                 &gjs_ns_proto_funcs[0],
-                                 /* props of constructor, MyConstructor.myprop */
-                                 NULL,
-                                 /* funcs of constructor, MyConstructor.myfunc() */
-                                 NULL);
-        if (prototype == NULL)
-            g_error("Can't init class %s", gjs_ns_class.name);
-
-        gjs_debug(GJS_DEBUG_GNAMESPACE, "Initialized class %s prototype %p",
-                  gjs_ns_class.name, prototype);
-    }
 
-    JS::RootedObject ns(context, JS_NewObject(context, &gjs_ns_class));
+    JS::RootedObject prototype(context);
+    if (!gjs_ns_ensure_proto(context, &prototype))
+        return nullptr;
+
+    JS::RootedObject ns(context,
+        JS_NewObjectWithGivenProto(context, &gjs_ns_class, prototype));
     if (ns == NULL)
         g_error("No memory to create ns object");
 
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 1c8607c..97949d0 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -53,11 +53,13 @@ typedef struct {
     unsigned int index;
 } ImporterIterator;
 
-extern const js::Class gjs_importer_class;
+extern const js::Class gjs_importer_real_class;
 
 /* Bizarrely, the API for safely casting const js::Class * to const JSClass *
  * is called "js::Jsvalify" */
-GJS_DEFINE_PRIV_FROM_JS(Importer, (*js::Jsvalify(&gjs_importer_class)))
+static const JSClass gjs_importer_class = *js::Jsvalify(&gjs_importer_real_class);
+
+GJS_DEFINE_PRIV_FROM_JS(Importer, gjs_importer_class)
 
 static bool
 importer_to_string(JSContext *cx,
@@ -107,7 +109,7 @@ define_meta_properties(JSContext       *context,
      * on the root importer
      */
     parent_is_module = parent && JS_InstanceOf(context, parent,
-        js::Jsvalify(&gjs_importer_class), NULL);
+                                               &gjs_importer_class, nullptr);
 
     gjs_debug(GJS_DEBUG_IMPORTER, "Defining parent %p of %p '%s' is mod %d",
               parent.get(), module_obj.get(),
@@ -857,7 +859,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_class = {
+const js::Class gjs_importer_real_class = {
     "GjsFileImporter",
     JSCLASS_HAS_PRIVATE,
     NULL,  /* addProperty */
@@ -890,62 +892,30 @@ const js::Class gjs_importer_class = {
     }
 };
 
-JSPropertySpec gjs_importer_proto_props[] = {
-    JS_PS_END
-};
+static JSPropertySpec *gjs_importer_proto_props = nullptr;
+static JSFunctionSpec *gjs_importer_static_funcs = nullptr;
 
 JSFunctionSpec gjs_importer_proto_funcs[] = {
     JS_FS("toString", importer_to_string, 0, 0),
     JS_FS_END
 };
 
+GJS_DEFINE_ENSURE_PROTO(importer)
+
 static JSObject*
 importer_new(JSContext *context,
              bool       is_root)
 {
     Importer *priv;
-    bool found;
 
-    JS::RootedObject global(context, gjs_get_import_global(context));
-
-    if (!JS_HasProperty(context, global, gjs_importer_class.name, &found))
-        g_error("HasProperty call failed creating importer class");
-
-    if (!found) {
-        JSObject *prototype;
-        prototype = JS_InitClass(context, global,
-                                 /* parent prototype JSObject* for
-                                  * prototype; NULL for
-                                  * Object.prototype
-                                  */
-                                 nullptr,
-                                 js::Jsvalify(&gjs_importer_class),
-                                 /* constructor for instances (NULL for
-                                  * none - just name the prototype like
-                                  * Math - rarely correct)
-                                  */
-                                 gjs_importer_constructor,
-                                 /* number of constructor args */
-                                 0,
-                                 /* props of prototype */
-                                 &gjs_importer_proto_props[0],
-                                 /* funcs of prototype */
-                                 &gjs_importer_proto_funcs[0],
-                                 /* props of constructor, MyConstructor.myprop */
-                                 NULL,
-                                 /* funcs of constructor, MyConstructor.myfunc() */
-                                 NULL);
-        if (prototype == NULL)
-            g_error("Can't init class %s", gjs_importer_class.name);
-
-        gjs_debug(GJS_DEBUG_IMPORTER, "Initialized class %s prototype %p",
-                  gjs_importer_class.name, prototype);
-    }
+    JS::RootedObject prototype(context);
+    if (!gjs_importer_ensure_proto(context, &prototype))
+        g_error("Error creating importer prototype");
 
     JS::RootedObject importer(context,
-        JS_NewObject(context, js::Jsvalify(&gjs_importer_class)));
+        JS_NewObjectWithGivenProto(context, &gjs_importer_class, prototype));
     if (importer == NULL)
-        g_error("No memory to create importer importer");
+        g_error("No memory to create importer");
 
     priv = g_slice_new0(Importer);
     priv->is_root = is_root;
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 5014491..f19ddfb 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -32,6 +32,7 @@
 #include "jsapi-wrapper.h"
 #include "gjs/runtime.h"
 #include "gi/gtype.h"
+#include "util/log.h"
 
 class GjsAutoChar : public std::unique_ptr<char, decltype(&g_free)> {
 public:
@@ -75,7 +76,10 @@ enum {
 typedef enum {
     GJS_GLOBAL_SLOT_IMPORTS,
     GJS_GLOBAL_SLOT_PROTOTYPE_gtype,
-    GJS_GLOBAL_SLOT_BYTE_ARRAY_PROTOTYPE,
+    GJS_GLOBAL_SLOT_PROTOTYPE_function,
+    GJS_GLOBAL_SLOT_PROTOTYPE_ns,
+    GJS_GLOBAL_SLOT_PROTOTYPE_byte_array,
+    GJS_GLOBAL_SLOT_PROTOTYPE_importer,
     GJS_GLOBAL_SLOT_PROTOTYPE_cairo_context,
     GJS_GLOBAL_SLOT_PROTOTYPE_cairo_gradient,
     GJS_GLOBAL_SLOT_PROTOTYPE_cairo_image_surface,
@@ -247,6 +251,18 @@ static struct JSClass gjs_##cname##_class = { \
     NULL,  /* convert */                                                       \
     gjs_##cname##_finalize                                                     \
 }; \
+_GJS_DEFINE_ENSURE_PROTO_FULL(cname, parent_cname, ctor, gtype)
+
+#define GJS_DEFINE_ENSURE_PROTO_WITH_PARENT(cname, parent_cname)  \
+static                                                            \
+_GJS_DEFINE_ENSURE_PROTO_FULL(cname, parent_cname,                \
+                              gjs_##cname##_constructor,          \
+                              G_TYPE_NONE)
+
+#define GJS_DEFINE_ENSURE_PROTO(cname) \
+GJS_DEFINE_ENSURE_PROTO_WITH_PARENT(cname, no_parent)
+
+#define _GJS_DEFINE_ENSURE_PROTO_FULL(cname, parent_cname, ctor, gtype)        \
 bool                                                                           \
 gjs_##cname##_ensure_proto(JSContext              *cx,                         \
                            JS::MutableHandleObject proto)                      \
@@ -268,11 +284,14 @@ gjs_##cname##_ensure_proto(JSContext              *cx,                         \
                            gjs_##cname##_proto_funcs, nullptr,                 \
                            gjs_##cname##_static_funcs));                       \
     if (!proto)                                                                \
-        return false;                                                          \
+        g_error("Can't init class %s", gjs_##cname##_class.name);              \
     gjs_set_global_slot(cx, GJS_GLOBAL_SLOT_PROTOTYPE_##cname,                 \
                         JS::ObjectValue(*proto));                              \
+    gjs_debug(GJS_DEBUG_CONTEXT, "Initialized class %s prototype %p",          \
+              gjs_##cname##_class.name, proto.get());                          \
     if (gtype != G_TYPE_NONE) {                                                \
-        JS::RootedId type_id(cx, gjs_intern_string_to_id(cx, type_name));      \
+        JS::RootedId type_id(cx,                                               \
+            gjs_intern_string_to_id(cx, gjs_##cname##_class.name));            \
         JS::RootedObject ctor_obj(cx);                                         \
         if (!gjs_object_require_property(cx, global, #cname " constructor",    \
                                          type_id, &ctor_obj))                  \


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