[gjs/wip/ptomato/mozjs45prep: 10/39] jsapi-util: GJS_DEFINE_PROTO stores protos in global slots



commit 13ce7247d3effcf9bee64a6bda023da99e208646
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun Apr 9 16:19:48 2017 -0700

    jsapi-util: GJS_DEFINE_PROTO stores protos in global slots
    
    This refactors the GJS_DEFINE_PROTO family of macros to store the created
    prototype objects in slots on the global object. We split up the
    gjs_WHATEVER_create_proto() function into two functions: one that actually
    creates the prototype or returns it if already found in a global slot,
    called gjs_WHATEVER_ensure_proto(); and one that defines a constructor,
    accessible from JS, as a property on a module object, called
    gjs_WHATEVER_define_constructor(). (gjs_WHATEVER_create_proto() was kind of
    a misnomer since it returned the constructor, not the prototype, and so we
    do a corresponding rename in cairo-image-surface.cpp, for clarity.)
    
    gjs_WHATEVER_define_constructor() is not necessary for every class; we only
    need to call it if we actually want to define the constructor as a property
    on a module object. Therefore we split it out into its own macro,
    GJS_EXPORT_PROTO. This macro takes a "js_name" parameter, which is the name
    of the property to define. Previously, the JS name was passed to the
    gjs_WHATEVER_create_proto() function. It's better to keep that definition
    together with the rest of the information about the class, fixed at compile
    time.
    
    We also add two macros, GJS_DEFINE_PROTO_WITH_PARENT and
    GJS_DEFINE_PROTO_ABSTRACT_WITH_PARENT, which also move the definition of
    the parent to compile time rather than runtime, and keep it in the same
    place as the rest of each class's macro definition. Similarly, previously
    we had to pass the parent prototype object to gjs_WHATEVER_create_proto().
    
    This mostly affects the cairo module.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=614413

 gi/gtype.cpp                      |   23 +++-----
 gjs/jsapi-util.h                  |  119 ++++++++++++++++++++++++++++--------
 modules/cairo-context.cpp         |   13 +++-
 modules/cairo-gradient.cpp        |    5 +-
 modules/cairo-image-surface.cpp   |   21 +++++--
 modules/cairo-linear-gradient.cpp |   11 +++-
 modules/cairo-path.cpp            |    8 ++-
 modules/cairo-pattern.cpp         |    5 +-
 modules/cairo-pdf-surface.cpp     |   11 +++-
 modules/cairo-private.h           |   94 +++++++++++------------------
 modules/cairo-ps-surface.cpp      |   12 +++-
 modules/cairo-radial-gradient.cpp |   11 +++-
 modules/cairo-region.cpp          |   13 +++-
 modules/cairo-solid-pattern.cpp   |   12 +++-
 modules/cairo-surface-pattern.cpp |   11 +++-
 modules/cairo-surface.cpp         |   11 +++-
 modules/cairo-svg-surface.cpp     |   11 +++-
 modules/cairo.cpp                 |   68 +++++++--------------
 18 files changed, 278 insertions(+), 181 deletions(-)
---
diff --git a/gi/gtype.cpp b/gi/gtype.cpp
index be84ae9..4e4b428 100644
--- a/gi/gtype.cpp
+++ b/gi/gtype.cpp
@@ -34,11 +34,7 @@
 static bool weak_pointer_callback = false;
 static std::set<GType> weak_pointer_list;
 
-static JSObject *
-gjs_gtype_create_proto(JSContext       *context,
-                       JS::HandleObject module,
-                       const char      *proto_name,
-                       JS::HandleObject parent);
+static bool gjs_gtype_ensure_proto(JSContext *, JS::MutableHandleObject);
 
 GJS_DEFINE_PROTO_ABSTRACT("GIRepositoryGType", gtype, 0);
 
@@ -150,31 +146,28 @@ JSObject *
 gjs_gtype_create_gtype_wrapper (JSContext *context,
                                 GType      gtype)
 {
-    JS_BeginRequest(context);
-
-    /* put constructor for GIRepositoryGType() in the global namespace */
-    JS::RootedObject global(context, gjs_get_import_global(context));
-    JS::RootedObject proto(context,
-        gjs_gtype_create_proto(context, global, "GIRepositoryGType", JS::NullPtr()));
+    JSAutoRequest ar(context);
 
     auto heap_wrapper =
         static_cast<JS::Heap<JSObject *> *>(g_type_get_qdata(gtype, gjs_get_gtype_wrapper_quark()));
     if (heap_wrapper != nullptr)
-        goto out;
+        return *heap_wrapper;
+
+    JS::RootedObject proto(context);
+    if (!gjs_gtype_ensure_proto(context, &proto))
+        return nullptr;
 
     heap_wrapper = new JS::Heap<JSObject *>();
     *heap_wrapper = JS_NewObjectWithGivenProto(context, &gjs_gtype_class, proto,
                                                JS::NullPtr());
     if (*heap_wrapper == nullptr)
-        goto out;
+        return nullptr;
 
     JS_SetPrivate(*heap_wrapper, GSIZE_TO_POINTER(gtype));
     ensure_weak_pointer_callback(context);
     g_type_set_qdata(gtype, gjs_get_gtype_wrapper_quark(), heap_wrapper);
     weak_pointer_list.insert(gtype);
 
- out:
-    JS_EndRequest(context);
     return *heap_wrapper;
 }
 
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 0e537c7..b1058a2 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -74,7 +74,22 @@ enum {
 
 typedef enum {
     GJS_GLOBAL_SLOT_IMPORTS,
+    GJS_GLOBAL_SLOT_PROTOTYPE_gtype,
     GJS_GLOBAL_SLOT_BYTE_ARRAY_PROTOTYPE,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_context,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_gradient,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_image_surface,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_linear_gradient,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_path,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_pattern,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_pdf_surface,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_ps_surface,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_radial_gradient,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_region,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_solid_pattern,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_surface,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_surface_pattern,
+    GJS_GLOBAL_SLOT_PROTOTYPE_cairo_svg_surface,
     GJS_GLOBAL_SLOT_LAST,
 } GjsGlobalSlot;
 
@@ -167,6 +182,15 @@ typedef struct GjsRootedArray GjsRootedArray;
         return false;                                     \
     type *priv = priv_from_js(cx, to)
 
+/* Helper for GJS_DEFINE_PROTO_* macros with no parent */
+static inline bool
+gjs_no_parent_ensure_proto(JSContext              *cx,
+                           JS::MutableHandleObject proto)
+{
+    proto.set(nullptr);
+    return true;
+}
+
 /**
  * GJS_DEFINE_PROTO:
  * @tn: The name of the prototype, as a string
@@ -177,7 +201,7 @@ typedef struct GjsRootedArray GjsRootedArray;
  */
 #define GJS_DEFINE_PROTO(tn, cn, flags) \
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cn); \
-_GJS_DEFINE_PROTO_FULL(tn, cn, gjs_##cn##_constructor, G_TYPE_NONE, flags)
+_GJS_DEFINE_PROTO_FULL(tn, cn, no_parent, gjs_##cn##_constructor, G_TYPE_NONE, flags)
 
 /**
  * GJS_DEFINE_PROTO_ABSTRACT:
@@ -189,20 +213,27 @@ _GJS_DEFINE_PROTO_FULL(tn, cn, gjs_##cn##_constructor, G_TYPE_NONE, flags)
  * you won't be able to instantiate it using the new keyword
  */
 #define GJS_DEFINE_PROTO_ABSTRACT(tn, cn, flags) \
-_GJS_DEFINE_PROTO_FULL(tn, cn, NULL, G_TYPE_NONE, flags)
+_GJS_DEFINE_PROTO_FULL(tn, cn, no_parent, nullptr, G_TYPE_NONE, flags)
 
 #define GJS_DEFINE_PROTO_WITH_GTYPE(tn, cn, gtype, flags)   \
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cn); \
-_GJS_DEFINE_PROTO_FULL(tn, cn, gjs_##cn##_constructor, gtype, flags)
+_GJS_DEFINE_PROTO_FULL(tn, cn, no_parent, gjs_##cn##_constructor, gtype, flags)
 
 #define GJS_DEFINE_PROTO_ABSTRACT_WITH_GTYPE(tn, cn, gtype, flags)   \
-_GJS_DEFINE_PROTO_FULL(tn, cn, NULL, gtype, flags)
+_GJS_DEFINE_PROTO_FULL(tn, cn, no_parent, nullptr, gtype, flags)
+
+#define GJS_DEFINE_PROTO_WITH_PARENT(tn, cn, parent_cn, flags)    \
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cn);                                    \
+_GJS_DEFINE_PROTO_FULL(tn, cn, parent_cn, gjs_##cn##_constructor, \
+                       G_TYPE_NONE, flags)
 
-#define _GJS_DEFINE_PROTO_FULL(type_name, cname, ctor, gtype, jsclass_flags)     \
+#define GJS_DEFINE_PROTO_ABSTRACT_WITH_PARENT(tn, cn, parent_cn, flags) \
+_GJS_DEFINE_PROTO_FULL(tn, cn, parent_cn, nullptr, G_TYPE_NONE, flags)
+
+#define _GJS_DEFINE_PROTO_FULL(type_name, cname, parent_cname, ctor, gtype, jsclass_flags) \
 extern JSPropertySpec gjs_##cname##_proto_props[]; \
 extern JSFunctionSpec gjs_##cname##_proto_funcs[]; \
 static void gjs_##cname##_finalize(JSFreeOp *fop, JSObject *obj); \
-static JS::PersistentRootedObject gjs_##cname##_prototype;                     \
 static struct JSClass gjs_##cname##_class = { \
     type_name, \
     JSCLASS_HAS_PRIVATE | jsclass_flags,                                       \
@@ -215,11 +246,58 @@ static struct JSClass gjs_##cname##_class = { \
     NULL,  /* convert */                                                       \
     gjs_##cname##_finalize                                                     \
 }; \
+bool                                                                           \
+gjs_##cname##_ensure_proto(JSContext              *cx,                         \
+                           JS::MutableHandleObject proto)                      \
+{                                                                              \
+    JS::RootedValue v_proto(cx,                                                \
+        gjs_get_global_slot(cx, GJS_GLOBAL_SLOT_PROTOTYPE_##cname));           \
+    if (!v_proto.isUndefined()) {                                              \
+        g_assert(((void) "Someone stored some weird value in a global slot",   \
+                  v_proto.isObject()));                                        \
+        proto.set(&v_proto.toObject());                                        \
+        return true;                                                           \
+    }                                                                          \
+    JS::RootedObject parent_proto(cx);                                         \
+    if (!gjs_##parent_cname##_ensure_proto(cx, &parent_proto))                 \
+        return false;                                                          \
+    JS::RootedObject global(cx, gjs_get_import_global(cx));                    \
+    proto.set(JS_InitClass(cx, global, parent_proto, &gjs_##cname##_class,     \
+                           ctor, 0, gjs_##cname##_proto_props,                 \
+                           gjs_##cname##_proto_funcs, nullptr, nullptr));      \
+    if (!proto)                                                                \
+        return false;                                                          \
+    gjs_set_global_slot(cx, GJS_GLOBAL_SLOT_PROTOTYPE_##cname,                 \
+                        JS::ObjectValue(*proto));                              \
+    if (gtype != G_TYPE_NONE) {                                                \
+        JS::RootedId type_id(cx, gjs_intern_string_to_id(cx, type_name));      \
+        JS::RootedObject ctor_obj(cx);                                         \
+        if (!gjs_object_require_property(cx, global, #cname " constructor",    \
+                                         type_id, &ctor_obj))                  \
+            return false;                                                      \
+        JS::RootedObject gtype_obj(cx,                                         \
+            gjs_gtype_create_gtype_wrapper(cx, gtype));                        \
+        if (!JS_DefineProperty(cx, ctor_obj, "$gtype", gtype_obj,              \
+                               JSPROP_PERMANENT))                              \
+            return false;                                                      \
+    }                                                                          \
+    return true;                                                               \
+}
+
+/**
+ * GJS_EXPORT_PROTO:
+ * @cname: The name of the prototype, separated by _
+ * @js_name: The name of the class as seen from JS code, as a string
+ *
+ * Defines a function gjs_<cname>_define_constructor(JSContext *, HandleObject)
+ * which calls gjs_<cname>_ensure_proto() to make sure the prototype and
+ * constructor have been created, then defines the constructor as a property
+ * on the given object with the name @js_name.
+ */
+#define GJS_EXPORT_PROTO(cname, js_name)                                       \
 JSObject *                                                                     \
-gjs_##cname##_create_proto(JSContext *context,                                 \
-                           JS::HandleObject module,                            \
-                           const char      *proto_name,                        \
-                           JS::HandleObject parent)                            \
+gjs_##cname##_define_constructor(JSContext       *context,                     \
+                                 JS::HandleObject module)                      \
 { \
     JS::RootedObject rval(context);                                            \
     JS::RootedObject global(context, gjs_get_import_global(context));          \
@@ -228,16 +306,9 @@ gjs_##cname##_create_proto(JSContext *context,                                 \
     bool found = false;                                                        \
     if (!JS_AlreadyHasOwnPropertyById(context, global, class_name, &found))    \
         return nullptr;                                                        \
-    if (!found) {                                                              \
-        gjs_##cname##_prototype.init(context);                                 \
-        gjs_##cname##_prototype =                                              \
-            JS_InitClass(context, global, parent, &gjs_##cname##_class, ctor,  \
-                         0, &gjs_##cname##_proto_props[0],                     \
-                         &gjs_##cname##_proto_funcs[0],                        \
-                         nullptr, nullptr);                                    \
-        if (!gjs_##cname##_prototype)                                          \
-            return nullptr;                                                    \
-    } \
+    JS::RootedObject proto(context);                                           \
+    if (!gjs_##cname##_ensure_proto(context, &proto))                          \
+        return nullptr;                                                        \
     if (!gjs_object_require_property( \
             context, global, NULL, \
             class_name, &rval)) { \
@@ -245,15 +316,9 @@ gjs_##cname##_create_proto(JSContext *context,                                 \
     } \
     if (found)                                                                 \
         return rval;                                                           \
-    if (!JS_DefineProperty(context, module, proto_name,                        \
+    if (!JS_DefineProperty(context, module, js_name,                           \
                            rval, GJS_MODULE_PROP_FLAGS))                       \
         return nullptr;                                                        \
-    if (gtype != G_TYPE_NONE) { \
-        JS::RootedObject gtype_obj(context,                                    \
-            gjs_gtype_create_gtype_wrapper(context, gtype));                   \
-        JS_DefineProperty(context, rval, "$gtype", gtype_obj,                  \
-                          JSPROP_PERMANENT);                                   \
-    } \
     return rval; \
 }
 
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index cb01bf7..717c8c8 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -237,7 +237,12 @@ typedef struct {
     cairo_t * cr;
 } GjsCairoContext;
 
-GJS_DEFINE_PROTO_WITH_GTYPE("CairoContext", cairo_context, CAIRO_GOBJECT_TYPE_CONTEXT, 
JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_context_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_GTYPE("CairoContext", cairo_context,
+                            CAIRO_GOBJECT_TYPE_CONTEXT,
+                            JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_context, "Context")
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoContext, gjs_cairo_context_class);
 
 static void
@@ -922,9 +927,11 @@ JSObject *
 gjs_cairo_context_from_context(JSContext *context,
                                cairo_t *cr)
 {
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_context_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_context_class,
-                                   gjs_cairo_context_prototype));
+        JS_NewObjectWithGivenProto(context, &gjs_cairo_context_class, proto));
     if (!object)
         return NULL;
 
diff --git a/modules/cairo-gradient.cpp b/modules/cairo-gradient.cpp
index 7bd6999..c259735 100644
--- a/modules/cairo-gradient.cpp
+++ b/modules/cairo-gradient.cpp
@@ -27,7 +27,10 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO_ABSTRACT("CairoGradient", cairo_gradient, JSCLASS_BACKGROUND_FINALIZE)
+GJS_DEFINE_PROTO_ABSTRACT_WITH_PARENT("CairoGradient", cairo_gradient,
+                                      cairo_pattern,
+                                      JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_gradient, "Gradient")
 
 static void
 gjs_cairo_gradient_finalize(JSFreeOp *fop,
diff --git a/modules/cairo-image-surface.cpp b/modules/cairo-image-surface.cpp
index f2253ae..97f3fc9 100644
--- a/modules/cairo-image-surface.cpp
+++ b/modules/cairo-image-surface.cpp
@@ -28,7 +28,11 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO("CairoImageSurface", cairo_image_surface, JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_image_surface_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_PARENT("CairoImageSurface", cairo_image_surface,
+                             cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_image_surface, "ImageSurface")
 
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_image_surface)
 {
@@ -87,9 +91,12 @@ createFromPNG_func(JSContext *context,
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface), "surface"))
         return false;
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_image_surface_ensure_proto(context, &proto))
+        return false;
     JS::RootedObject surface_wrapper(context,
         JS_NewObjectWithGivenProto(context, &gjs_cairo_image_surface_class,
-                                   gjs_cairo_image_surface_prototype));
+                                   proto));
     if (!surface_wrapper) {
         gjs_throw(context, "failed to create surface");
         return false;
@@ -215,9 +222,12 @@ gjs_cairo_image_surface_from_surface(JSContext       *context,
     g_return_val_if_fail(surface != NULL, NULL);
     g_return_val_if_fail(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_image_surface_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
         JS_NewObjectWithGivenProto(context, &gjs_cairo_image_surface_class,
-                                   gjs_cairo_image_surface_prototype));
+                                   proto));
     if (!object) {
         gjs_throw(context, "failed to create image surface");
         return NULL;
@@ -230,10 +240,9 @@ gjs_cairo_image_surface_from_surface(JSContext       *context,
 
 void
 gjs_cairo_image_surface_init(JSContext       *cx,
-                             JS::HandleObject proto)
+                             JS::HandleObject ctor)
 {
-
-    if (!JS_DefineFunction(cx, proto, "createFromPNG", createFromPNG_func,
+    if (!JS_DefineFunction(cx, ctor, "createFromPNG", createFromPNG_func,
                            1, GJS_MODULE_PROP_FLAGS))
         return;
 }
diff --git a/modules/cairo-linear-gradient.cpp b/modules/cairo-linear-gradient.cpp
index 27d5854..f35571e 100644
--- a/modules/cairo-linear-gradient.cpp
+++ b/modules/cairo-linear-gradient.cpp
@@ -27,7 +27,11 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO("CairoLinearGradient", cairo_linear_gradient, JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_linear_gradient_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_PARENT("CairoLinearGradient", cairo_linear_gradient,
+                             cairo_gradient, JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_linear_gradient, "LinearGradient")
 
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_linear_gradient)
 {
@@ -81,9 +85,12 @@ gjs_cairo_linear_gradient_from_pattern(JSContext       *context,
     g_return_val_if_fail(pattern != NULL, NULL);
     g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_LINEAR, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_linear_gradient_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
         JS_NewObjectWithGivenProto(context, &gjs_cairo_linear_gradient_class,
-                                   gjs_cairo_linear_gradient_prototype));
+                                   proto));
     if (!object) {
         gjs_throw(context, "failed to create linear gradient pattern");
         return NULL;
diff --git a/modules/cairo-path.cpp b/modules/cairo-path.cpp
index c08a14a..aed5d81 100644
--- a/modules/cairo-path.cpp
+++ b/modules/cairo-path.cpp
@@ -33,6 +33,8 @@ typedef struct {
     cairo_path_t    *path;
 } GjsCairoPath;
 
+static bool gjs_cairo_path_ensure_proto(JSContext *, JS::MutableHandleObject);
+
 GJS_DEFINE_PROTO_ABSTRACT("CairoPath", cairo_path, JSCLASS_BACKGROUND_FINALIZE)
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoPath, gjs_cairo_path_class)
 
@@ -74,9 +76,11 @@ gjs_cairo_path_from_path(JSContext    *context,
     g_return_val_if_fail(context != NULL, NULL);
     g_return_val_if_fail(path != NULL, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_path_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_path_class,
-                                   gjs_cairo_path_prototype));
+        JS_NewObjectWithGivenProto(context, &gjs_cairo_path_class, proto));
     if (!object) {
         gjs_throw(context, "failed to create path");
         return NULL;
diff --git a/modules/cairo-pattern.cpp b/modules/cairo-pattern.cpp
index 5c3ef12..8d816dc 100644
--- a/modules/cairo-pattern.cpp
+++ b/modules/cairo-pattern.cpp
@@ -35,7 +35,10 @@ typedef struct {
     cairo_pattern_t *pattern;
 } GjsCairoPattern;
 
-GJS_DEFINE_PROTO_ABSTRACT_WITH_GTYPE("CairoPattern", cairo_pattern, CAIRO_GOBJECT_TYPE_PATTERN, 
JSCLASS_BACKGROUND_FINALIZE)
+GJS_DEFINE_PROTO_ABSTRACT_WITH_GTYPE("CairoPattern", cairo_pattern,
+                                     CAIRO_GOBJECT_TYPE_PATTERN,
+                                     JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_pattern, "Pattern")
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoPattern, gjs_cairo_pattern_class)
 
 static void
diff --git a/modules/cairo-pdf-surface.cpp b/modules/cairo-pdf-surface.cpp
index d8d399e..890954f 100644
--- a/modules/cairo-pdf-surface.cpp
+++ b/modules/cairo-pdf-surface.cpp
@@ -30,7 +30,11 @@
 #if CAIRO_HAS_PDF_SURFACE
 #include <cairo-pdf.h>
 
-GJS_DEFINE_PROTO("CairoPDFSurface", cairo_pdf_surface, JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_pdf_surface_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_PARENT("CairoPDFSurface", cairo_pdf_surface,
+                             cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_pdf_surface, "PDFSurface")
 
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_pdf_surface)
 {
@@ -87,9 +91,12 @@ gjs_cairo_pdf_surface_from_surface(JSContext       *context,
     g_return_val_if_fail(surface != NULL, NULL);
     g_return_val_if_fail(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_PDF, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_pdf_surface_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
         JS_NewObjectWithGivenProto(context, &gjs_cairo_pdf_surface_class,
-                                   gjs_cairo_pdf_surface_prototype));
+                                   proto));
     if (!object) {
         gjs_throw(context, "failed to create pdf surface");
         return NULL;
diff --git a/modules/cairo-private.h b/modules/cairo-private.h
index 2435ed3..27261e3 100644
--- a/modules/cairo-private.h
+++ b/modules/cairo-private.h
@@ -30,17 +30,13 @@ bool             gjs_cairo_check_status                 (JSContext       *contex
                                                          cairo_status_t   status,
                                                          const char      *name);
 
-JSObject *gjs_cairo_region_create_proto(JSContext       *cx,
-                                        JS::HandleObject module,
-                                        const char      *proto_name,
-                                        JS::HandleObject parent);
+JSObject *gjs_cairo_region_define_constructor(JSContext       *cx,
+                                              JS::HandleObject module);
 
 void             gjs_cairo_region_init                  (JSContext       *context);
 
-JSObject *gjs_cairo_context_create_proto(JSContext       *cx,
-                                         JS::HandleObject module,
-                                         const char      *proto_name,
-                                         JS::HandleObject parent);
+JSObject *gjs_cairo_context_define_constructor(JSContext       *cx,
+                                               JS::HandleObject module);
 
 cairo_t *        gjs_cairo_context_get_context          (JSContext       *context,
                                                          JS::HandleObject object);
@@ -49,23 +45,17 @@ JSObject *       gjs_cairo_context_from_context         (JSContext       *contex
 void             gjs_cairo_context_init                 (JSContext       *context);
 void             gjs_cairo_surface_init                 (JSContext       *context);
 
-
-/* cairo_path_t */
-JSObject *gjs_cairo_path_create_proto(JSContext       *cx,
-                                      JS::HandleObject module,
-                                      const char      *proto_name,
-                                      JS::HandleObject parent);
-
 JSObject *       gjs_cairo_path_from_path               (JSContext       *context,
                                                          cairo_path_t    *path);
 cairo_path_t *   gjs_cairo_path_get_path                (JSContext       *context,
                                                          JSObject        *path_wrapper);
 
 /* surface */
-JSObject *gjs_cairo_surface_create_proto(JSContext       *cx,
-                                         JS::HandleObject module,
-                                         const char      *proto_name,
-                                         JS::HandleObject parent);
+bool gjs_cairo_surface_ensure_proto(JSContext              *cx,
+                                    JS::MutableHandleObject proto);
+
+JSObject *gjs_cairo_surface_define_constructor(JSContext       *cx,
+                                               JS::HandleObject module);
 
 void             gjs_cairo_surface_construct            (JSContext       *context,
                                                          JS::HandleObject object,
@@ -78,10 +68,8 @@ cairo_surface_t* gjs_cairo_surface_get_surface          (JSContext       *contex
                                                          JSObject        *object);
 
 /* image surface */
-JSObject *gjs_cairo_image_surface_create_proto(JSContext       *cx,
-                                               JS::HandleObject module,
-                                               const char      *proto_name,
-                                               JS::HandleObject parent);
+JSObject *gjs_cairo_image_surface_define_constructor(JSContext       *cx,
+                                                     JS::HandleObject module);
 
 void             gjs_cairo_image_surface_init           (JSContext       *context,
                                                          JS::HandleObject proto);
@@ -91,39 +79,34 @@ JSObject *       gjs_cairo_image_surface_from_surface   (JSContext       *contex
 
 /* postscript surface */
 #ifdef CAIRO_HAS_PS_SURFACE
-JSObject *gjs_cairo_ps_surface_create_proto(JSContext       *cx,
-                                            JS::HandleObject module,
-                                            const char      *proto_name,
-                                            JS::HandleObject parent);
+JSObject *gjs_cairo_ps_surface_define_constructor(JSContext       *cx,
+                                                  JS::HandleObject module);
 #endif
 JSObject *       gjs_cairo_ps_surface_from_surface       (JSContext       *context,
                                                           cairo_surface_t *surface);
 
 /* pdf surface */
 #ifdef CAIRO_HAS_PDF_SURFACE
-JSObject *gjs_cairo_pdf_surface_create_proto(JSContext       *cx,
-                                             JS::HandleObject module,
-                                             const char      *proto_name,
-                                             JS::HandleObject parent);
+JSObject *gjs_cairo_pdf_surface_define_constructor(JSContext       *cx,
+                                                   JS::HandleObject module);
 #endif
 JSObject *       gjs_cairo_pdf_surface_from_surface     (JSContext       *context,
                                                          cairo_surface_t *surface);
 
 /* svg surface */
 #ifdef CAIRO_HAS_SVG_SURFACE
-JSObject *gjs_cairo_svg_surface_create_proto(JSContext       *cx,
-                                             JS::HandleObject module,
-                                             const char      *proto_name,
-                                             JS::HandleObject parent);
+JSObject *gjs_cairo_svg_surface_define_constructor(JSContext       *cx,
+                                                   JS::HandleObject module);
 #endif
 JSObject *       gjs_cairo_svg_surface_from_surface     (JSContext       *context,
                                                          cairo_surface_t *surface);
 
 /* pattern */
-JSObject *gjs_cairo_pattern_create_proto(JSContext       *cx,
-                                         JS::HandleObject module,
-                                         const char      *proto_name,
-                                         JS::HandleObject parent);
+bool gjs_cairo_pattern_ensure_proto(JSContext              *cx,
+                                    JS::MutableHandleObject proto);
+
+JSObject *gjs_cairo_pattern_define_constructor(JSContext       *cx,
+                                               JS::HandleObject module);
 
 void             gjs_cairo_pattern_construct            (JSContext       *context,
                                                          JS::HandleObject object,
@@ -136,43 +119,36 @@ cairo_pattern_t* gjs_cairo_pattern_get_pattern          (JSContext       *contex
                                                          JSObject        *object);
 
 /* gradient */
-JSObject *gjs_cairo_gradient_create_proto(JSContext       *cx,
-                                          JS::HandleObject module,
-                                          const char      *proto_name,
-                                          JS::HandleObject parent);
+bool gjs_cairo_gradient_ensure_proto(JSContext              *cx,
+                                     JS::MutableHandleObject proto);
+
+JSObject *gjs_cairo_gradient_define_constructor(JSContext       *cx,
+                                                JS::HandleObject module);
 
 /* linear gradient */
-JSObject *gjs_cairo_linear_gradient_create_proto(JSContext       *cx,
-                                                 JS::HandleObject module,
-                                                 const char      *proto_name,
-                                                 JS::HandleObject parent);
+JSObject *gjs_cairo_linear_gradient_define_constructor(JSContext       *cx,
+                                                       JS::HandleObject module);
 
 JSObject *       gjs_cairo_linear_gradient_from_pattern (JSContext       *context,
                                                          cairo_pattern_t *pattern);
 
 /* radial gradient */
-JSObject *gjs_cairo_radial_gradient_create_proto(JSContext       *cx,
-                                                 JS::HandleObject module,
-                                                 const char      *proto_name,
-                                                 JS::HandleObject parent);
+JSObject *gjs_cairo_radial_gradient_define_constructor(JSContext       *cx,
+                                                       JS::HandleObject module);
 
 JSObject *       gjs_cairo_radial_gradient_from_pattern (JSContext       *context,
                                                          cairo_pattern_t *pattern);
 
 /* surface pattern */
-JSObject *gjs_cairo_surface_pattern_create_proto(JSContext       *cx,
-                                                 JS::HandleObject module,
-                                                 const char      *proto_name,
-                                                 JS::HandleObject parent);
+JSObject *gjs_cairo_surface_pattern_define_constructor(JSContext       *cx,
+                                                       JS::HandleObject module);
 
 JSObject *       gjs_cairo_surface_pattern_from_pattern (JSContext       *context,
                                                          cairo_pattern_t *pattern);
 
 /* solid pattern */
-JSObject *gjs_cairo_solid_pattern_create_proto(JSContext       *cx,
-                                               JS::HandleObject module,
-                                               const char      *proto_name,
-                                               JS::HandleObject parent);
+JSObject *gjs_cairo_solid_pattern_define_constructor(JSContext       *cx,
+                                                     JS::HandleObject module);
 
 JSObject *       gjs_cairo_solid_pattern_from_pattern   (JSContext       *context,
                                                          cairo_pattern_t *pattern);
diff --git a/modules/cairo-ps-surface.cpp b/modules/cairo-ps-surface.cpp
index d9aa54d..16df958 100644
--- a/modules/cairo-ps-surface.cpp
+++ b/modules/cairo-ps-surface.cpp
@@ -30,7 +30,11 @@
 #if CAIRO_HAS_PS_SURFACE
 #include <cairo-ps.h>
 
-GJS_DEFINE_PROTO("CairoPSSurface", cairo_ps_surface, JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_ps_surface_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_PARENT("CairoPSSurface", cairo_ps_surface, cairo_surface,
+                             JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_ps_surface, "PSSurface")
 
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_ps_surface)
 {
@@ -96,9 +100,11 @@ gjs_cairo_ps_surface_from_surface(JSContext       *context,
     g_return_val_if_fail(surface != NULL, NULL);
     g_return_val_if_fail(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_PS, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_ps_surface_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_ps_surface_class,
-                                   gjs_cairo_ps_surface_prototype));
+        JS_NewObjectWithGivenProto(context, &gjs_cairo_ps_surface_class, proto));
     if (!object) {
         gjs_throw(context, "failed to create ps surface");
         return NULL;
diff --git a/modules/cairo-radial-gradient.cpp b/modules/cairo-radial-gradient.cpp
index 8dc87cd..49811e5 100644
--- a/modules/cairo-radial-gradient.cpp
+++ b/modules/cairo-radial-gradient.cpp
@@ -27,7 +27,11 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO("CairoRadialGradient", cairo_radial_gradient, JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_radial_gradient_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_PARENT("CairoRadialGradient", cairo_radial_gradient,
+                             cairo_gradient, JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_radial_gradient, "RadialGradient")
 
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_radial_gradient)
 {
@@ -83,9 +87,12 @@ gjs_cairo_radial_gradient_from_pattern(JSContext       *context,
     g_return_val_if_fail(pattern != NULL, NULL);
     g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_RADIAL, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_radial_gradient_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
         JS_NewObjectWithGivenProto(context, &gjs_cairo_radial_gradient_class,
-                                   gjs_cairo_radial_gradient_prototype));
+                                   proto));
     if (!object) {
         gjs_throw(context, "failed to create radial gradient pattern");
         return NULL;
diff --git a/modules/cairo-region.cpp b/modules/cairo-region.cpp
index 6de92b2..e91f909 100644
--- a/modules/cairo-region.cpp
+++ b/modules/cairo-region.cpp
@@ -36,7 +36,12 @@ typedef struct {
     cairo_region_t *region;
 } GjsCairoRegion;
 
-GJS_DEFINE_PROTO_WITH_GTYPE("CairoRegion", cairo_region, CAIRO_GOBJECT_TYPE_REGION, 
JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_region_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_GTYPE("CairoRegion", cairo_region,
+                            CAIRO_GOBJECT_TYPE_REGION,
+                            JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_region, "Region")
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoRegion, gjs_cairo_region_class);
 
 static cairo_region_t *
@@ -276,9 +281,11 @@ static JSObject *
 gjs_cairo_region_from_region(JSContext *context,
                              cairo_region_t *region)
 {
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_region_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_region_class,
-                                   gjs_cairo_region_prototype));
+        JS_NewObjectWithGivenProto(context, &gjs_cairo_region_class, proto));
     if (!object)
         return NULL;
 
diff --git a/modules/cairo-solid-pattern.cpp b/modules/cairo-solid-pattern.cpp
index f6a3d19..6a99ecf 100644
--- a/modules/cairo-solid-pattern.cpp
+++ b/modules/cairo-solid-pattern.cpp
@@ -27,7 +27,12 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO_ABSTRACT("CairoSolidPattern", cairo_solid_pattern, JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_solid_pattern_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_ABSTRACT_WITH_PARENT("CairoSolidPattern", cairo_solid_pattern,
+                                      cairo_pattern,
+                                      JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_solid_pattern, "SolidPattern")
 
 static void
 gjs_cairo_solid_pattern_finalize(JSFreeOp *fop,
@@ -111,9 +116,12 @@ gjs_cairo_solid_pattern_from_pattern(JSContext       *context,
     g_return_val_if_fail(pattern != NULL, NULL);
     g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_SOLID, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_solid_pattern_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
         JS_NewObjectWithGivenProto(context, &gjs_cairo_solid_pattern_class,
-                                   gjs_cairo_solid_pattern_prototype));
+                                   proto));
     if (!object) {
         gjs_throw(context, "failed to create solid pattern");
         return NULL;
diff --git a/modules/cairo-surface-pattern.cpp b/modules/cairo-surface-pattern.cpp
index a6ddc76..5cc729f 100644
--- a/modules/cairo-surface-pattern.cpp
+++ b/modules/cairo-surface-pattern.cpp
@@ -27,7 +27,11 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO("CairoSurfacePattern", cairo_surface_pattern, JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_surface_pattern_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_PARENT("CairoSurfacePattern", cairo_surface_pattern,
+                             cairo_pattern, JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_surface_pattern, "SurfacePattern")
 
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_surface_pattern)
 {
@@ -186,9 +190,12 @@ gjs_cairo_surface_pattern_from_pattern(JSContext       *context,
     g_return_val_if_fail(pattern != NULL, NULL);
     g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_SURFACE, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_surface_pattern_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
         JS_NewObjectWithGivenProto(context, &gjs_cairo_surface_pattern_class,
-                                   gjs_cairo_surface_pattern_prototype));
+                                   proto));
     if (!object) {
         gjs_throw(context, "failed to create surface pattern");
         return NULL;
diff --git a/modules/cairo-surface.cpp b/modules/cairo-surface.cpp
index 9d2d0f7..e9479d1 100644
--- a/modules/cairo-surface.cpp
+++ b/modules/cairo-surface.cpp
@@ -36,7 +36,10 @@ typedef struct {
     cairo_surface_t *surface;
 } GjsCairoSurface;
 
-GJS_DEFINE_PROTO_ABSTRACT_WITH_GTYPE("CairoSurface", cairo_surface, CAIRO_GOBJECT_TYPE_SURFACE, 
JSCLASS_BACKGROUND_FINALIZE)
+GJS_DEFINE_PROTO_ABSTRACT_WITH_GTYPE("CairoSurface", cairo_surface,
+                                     CAIRO_GOBJECT_TYPE_SURFACE,
+                                     JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_surface, "Surface")
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoSurface, gjs_cairo_surface_class)
 
 static void
@@ -205,9 +208,11 @@ gjs_cairo_surface_from_surface(JSContext       *context,
     if (type == CAIRO_SURFACE_TYPE_SVG)
         return gjs_cairo_svg_surface_from_surface(context, surface);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_surface_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_surface_class,
-                                   gjs_cairo_surface_prototype));
+        JS_NewObjectWithGivenProto(context, &gjs_cairo_surface_class, proto));
     if (!object) {
         gjs_throw(context, "failed to create surface");
         return NULL;
diff --git a/modules/cairo-svg-surface.cpp b/modules/cairo-svg-surface.cpp
index 5a1af1f..6e9bfa3 100644
--- a/modules/cairo-svg-surface.cpp
+++ b/modules/cairo-svg-surface.cpp
@@ -30,7 +30,11 @@
 #if CAIRO_HAS_SVG_SURFACE
 #include <cairo-svg.h>
 
-GJS_DEFINE_PROTO("CairoSVGSurface", cairo_svg_surface, JSCLASS_BACKGROUND_FINALIZE)
+static bool gjs_cairo_svg_surface_ensure_proto(JSContext *, JS::MutableHandleObject);
+
+GJS_DEFINE_PROTO_WITH_PARENT("CairoSVGSurface", cairo_svg_surface,
+                             cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
+GJS_EXPORT_PROTO(cairo_svg_surface, "SVGSurface")
 
 GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_svg_surface)
 {
@@ -87,9 +91,12 @@ gjs_cairo_svg_surface_from_surface(JSContext       *context,
     g_return_val_if_fail(surface != NULL, NULL);
     g_return_val_if_fail(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_SVG, NULL);
 
+    JS::RootedObject proto(context);
+    if (!gjs_cairo_svg_surface_ensure_proto(context, &proto))
+        return nullptr;
     JS::RootedObject object(context,
         JS_NewObjectWithGivenProto(context, &gjs_cairo_svg_surface_class,
-                                   gjs_cairo_svg_surface_prototype));
+                                   proto));
     if (!object) {
         gjs_throw(context, "failed to create svg surface");
         return NULL;
diff --git a/modules/cairo.cpp b/modules/cairo.cpp
index 02c202f..82ca6a3 100644
--- a/modules/cairo.cpp
+++ b/modules/cairo.cpp
@@ -56,67 +56,43 @@ gjs_cairo_check_status(JSContext      *context,
 }
 
 bool
-gjs_js_define_cairo_stuff(JSContext              *context,
+gjs_js_define_cairo_stuff(JSContext              *cx,
                           JS::MutableHandleObject module)
 {
-    module.set(JS_NewObject(context, NULL));
+    module.set(JS_NewObject(cx, NULL));
 
-    if (!gjs_cairo_region_create_proto(context, module, "Region", JS::NullPtr()))
+    if (!gjs_cairo_region_define_constructor(cx, module))
         return false;
-    gjs_cairo_region_init(context);
+    gjs_cairo_region_init(cx);
 
-    if (!gjs_cairo_context_create_proto(context, module, "Context", JS::NullPtr()))
+    if (!gjs_cairo_context_define_constructor(cx, module))
         return false;
-    gjs_cairo_context_init(context);
+    gjs_cairo_context_init(cx);
 
-    JS::RootedObject surface_proto(context,
-        gjs_cairo_surface_create_proto(context, module, "Surface", JS::NullPtr()));
-    if (!surface_proto)
+    if (!gjs_cairo_surface_define_constructor(cx, module))
         return false;
-    gjs_cairo_surface_init(context);
+    gjs_cairo_surface_init(cx);
 
-    JS::RootedObject image_surface_proto(context,
-        gjs_cairo_image_surface_create_proto(context, module, "ImageSurface", surface_proto));
-    if (!image_surface_proto)
+    JS::RootedObject image_surface_ctor(cx,
+        gjs_cairo_image_surface_define_constructor(cx, module));
+    if (!image_surface_ctor)
         return false;
-    gjs_cairo_image_surface_init(context, image_surface_proto);
+    gjs_cairo_image_surface_init(cx, image_surface_ctor);
 
+    return
 #if CAIRO_HAS_PS_SURFACE
-    if (!gjs_cairo_ps_surface_create_proto(context, module, "PSSurface", surface_proto))
-        return false;
+        gjs_cairo_ps_surface_define_constructor(cx, module) &&
 #endif
-
 #if CAIRO_HAS_PDF_SURFACE
-    if (!gjs_cairo_pdf_surface_create_proto(context, module, "PDFSurface", surface_proto))
-        return false;
+        gjs_cairo_pdf_surface_define_constructor(cx, module) &&
 #endif
-
 #if CAIRO_HAS_SVG_SURFACE
-    if (!gjs_cairo_svg_surface_create_proto(context, module, "SVGSurface", surface_proto))
-        return false;
+        gjs_cairo_svg_surface_define_constructor(cx, module) &&
 #endif
-
-    JS::RootedObject pattern_proto(context,
-        gjs_cairo_pattern_create_proto(context, module, "Pattern", JS::NullPtr()));
-    if (!pattern_proto)
-        return false;
-
-    JS::RootedObject gradient_proto(context,
-        gjs_cairo_gradient_create_proto(context, module, "Gradient", pattern_proto));
-    if (!gradient_proto)
-        return false;
-
-    if (!gjs_cairo_linear_gradient_create_proto(context, module, "LinearGradient", gradient_proto))
-        return false;
-
-    if (!gjs_cairo_radial_gradient_create_proto(context, module, "RadialGradient", gradient_proto))
-        return false;
-
-    if (!gjs_cairo_surface_pattern_create_proto(context, module, "SurfacePattern", pattern_proto))
-        return false;
-
-    if (!gjs_cairo_solid_pattern_create_proto(context, module, "SolidPattern", pattern_proto))
-        return false;
-
-    return true;
+        gjs_cairo_pattern_define_constructor(cx, module) &&
+        gjs_cairo_gradient_define_constructor(cx, module) &&
+        gjs_cairo_linear_gradient_define_constructor(cx, module) &&
+        gjs_cairo_radial_gradient_define_constructor(cx, module) &&
+        gjs_cairo_surface_pattern_define_constructor(cx, module) &&
+        gjs_cairo_solid_pattern_define_constructor(cx, module);
 }



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