[gjs: 9/12] cairo: Remove JSClass macros from CairoSurface and subclasses




commit aa77cf29c7ffcbc190b9b183b51b73113f407323
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue May 12 09:25:01 2020 -0700

    cairo: Remove JSClass macros from CairoSurface and subclasses
    
    Remove the usage of the GJS_DEFINE_PRIV_FROM_JS and GJS_DEFINE_PROTO
    families of macros from the Cairo surface wrapper types. Use CWrapper
    instead, for more type safety and less boilerplate.

 modules/cairo-context.cpp         |  15 +--
 modules/cairo-image-surface.cpp   |  89 +++----------
 modules/cairo-pdf-surface.cpp     |  76 +++--------
 modules/cairo-private.h           | 263 ++++++++++++++++++++++++++++++--------
 modules/cairo-ps-surface.cpp      |  77 +++--------
 modules/cairo-surface-pattern.cpp |   3 +-
 modules/cairo-surface.cpp         | 122 +++++-------------
 modules/cairo-svg-surface.cpp     |  77 +++--------
 modules/cairo.cpp                 |  25 ++--
 9 files changed, 336 insertions(+), 411 deletions(-)
---
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index 92033b2f..696af554 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -255,8 +255,7 @@ cairo_t* CairoContext::constructor_impl(JSContext* context,
                              "surface", &surface_wrapper))
         return nullptr;
 
-    cairo_surface_t* surface =
-        gjs_cairo_surface_get_surface(context, surface_wrapper);
+    cairo_surface_t* surface = CairoSurface::for_js(context, surface_wrapper);
     if (!surface)
         return nullptr;
 
@@ -486,8 +485,7 @@ maskSurface_func(JSContext *context,
                              "y", &y))
         return false;
 
-    cairo_surface_t* surface =
-        gjs_cairo_surface_get_surface(context, surface_wrapper);
+    cairo_surface_t* surface = CairoSurface::for_js(context, surface_wrapper);
     if (!surface)
         return false;
 
@@ -604,8 +602,7 @@ setSourceSurface_func(JSContext *context,
                              "y", &y))
         return false;
 
-    cairo_surface_t* surface =
-        gjs_cairo_surface_get_surface(context, surface_wrapper);
+    cairo_surface_t* surface = CairoSurface::for_js(context, surface_wrapper);
     if (!surface)
         return false;
 
@@ -742,7 +739,6 @@ getTarget_func(JSContext *context,
     _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, rec, obj);
 
     cairo_surface_t *surface;
-    JSObject *surface_wrapper;
 
     if (argc > 0) {
         gjs_throw(context, "Context.getTarget() takes no arguments");
@@ -754,7 +750,7 @@ getTarget_func(JSContext *context,
         return false;
 
     /* surface belongs to the context, so keep the reference */
-    surface_wrapper = gjs_cairo_surface_from_surface(context, surface);
+    JSObject* surface_wrapper = CairoSurface::from_c_ptr(context, surface);
     if (!surface_wrapper) {
         /* exception already set */
         return false;
@@ -774,7 +770,6 @@ getGroupTarget_func(JSContext *context,
     _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, rec, obj);
 
     cairo_surface_t *surface;
-    JSObject *surface_wrapper;
 
     if (argc > 0) {
         gjs_throw(context, "Context.getGroupTarget() takes no arguments");
@@ -786,7 +781,7 @@ getGroupTarget_func(JSContext *context,
         return false;
 
     /* surface belongs to the context, so keep the reference */
-    surface_wrapper = gjs_cairo_surface_from_surface(context, surface);
+    JSObject* surface_wrapper = CairoSurface::from_c_ptr(context, surface);
     if (!surface_wrapper) {
         /* exception already set */
         return false;
diff --git a/modules/cairo-image-surface.cpp b/modules/cairo-image-surface.cpp
index 0a880093..1ec8da4b 100644
--- a/modules/cairo-image-surface.cpp
+++ b/modules/cairo-image-surface.cpp
@@ -5,64 +5,47 @@
 #include <config.h>
 
 #include <cairo.h>
-#include <glib.h>
 
 #include <js/CallArgs.h>
-#include <js/Class.h>
 #include <js/PropertyDescriptor.h>  // for JSPROP_READONLY
 #include <js/PropertySpec.h>
 #include <js/RootingAPI.h>
 #include <js/TypeDecls.h>
 #include <jsapi.h>  // for JS_NewObjectWithGivenProto
+#include <jspubtd.h>  // for JSProtoKey
 
-#include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 #include "modules/cairo-private.h"
 
-[[nodiscard]] static JSObject* gjs_cairo_image_surface_get_proto(JSContext*);
-
-GJS_DEFINE_PROTO_WITH_PARENT("ImageSurface", cairo_image_surface,
-                             cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
+JSObject* CairoImageSurface::new_proto(JSContext* cx, JSProtoKey) {
+    JS::RootedObject parent_proto(cx, CairoSurface::prototype(cx));
+    return JS_NewObjectWithGivenProto(cx, nullptr, parent_proto);
+}
 
-GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_image_surface)
-{
-    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_image_surface)
+cairo_surface_t* CairoImageSurface::constructor_impl(JSContext* context,
+                                                     const JS::CallArgs& argv) {
     int format, width, height;
     cairo_surface_t *surface;
 
-    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_image_surface);
-
     // create_for_data optional parameter
     if (!gjs_parse_call_args(context, "ImageSurface", argv, "iii",
                              "format", &format,
                              "width", &width,
                              "height", &height))
-        return false;
+        return nullptr;
 
     surface = cairo_image_surface_create((cairo_format_t) format, width, height);
 
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface), "surface"))
-        return false;
-
-    gjs_cairo_surface_construct(object, surface);
-    cairo_surface_destroy(surface);
-
-    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_image_surface);
-
-    return true;
-}
+        return nullptr;
 
-static void
-gjs_cairo_image_surface_finalize(JSFreeOp *fop,
-                                 JSObject *obj)
-{
-    gjs_cairo_surface_finalize_surface(fop, obj);
+    return surface;
 }
 
 // clang-format off
-JSPropertySpec gjs_cairo_image_surface_proto_props[] = {
+const JSPropertySpec CairoImageSurface::proto_props[] = {
     JS_STRING_SYM_PS(toStringTag, "ImageSurface", JSPROP_READONLY),
     JS_PS_END};
 // clang-format on
@@ -86,15 +69,10 @@ createFromPNG_func(JSContext *context,
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface), "surface"))
         return false;
 
-    JS::RootedObject proto(context, gjs_cairo_image_surface_get_proto(context));
-    JS::RootedObject surface_wrapper(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_image_surface_class,
-                                   proto));
-    if (!surface_wrapper) {
-        gjs_throw(context, "failed to create surface");
+    JSObject* surface_wrapper = CairoImageSurface::from_c_ptr(context, surface);
+    if (!surface_wrapper)
         return false;
-    }
-    gjs_cairo_surface_construct(surface_wrapper, surface);
+
     cairo_surface_destroy(surface);
 
     argv.rval().setObject(*surface_wrapper);
@@ -115,7 +93,7 @@ getFormat_func(JSContext *context,
         return false;
     }
 
-    cairo_surface_t* surface = gjs_cairo_surface_get_surface(context, obj);
+    cairo_surface_t* surface = CairoSurface::for_js(context, obj);
     if (!surface)
         return false;
 
@@ -142,7 +120,7 @@ getWidth_func(JSContext *context,
         return false;
     }
 
-    cairo_surface_t* surface = gjs_cairo_surface_get_surface(context, obj);
+    cairo_surface_t* surface = CairoSurface::for_js(context, obj);
     if (!surface)
         return false;
 
@@ -169,7 +147,7 @@ getHeight_func(JSContext *context,
         return false;
     }
 
-    cairo_surface_t* surface = gjs_cairo_surface_get_surface(context, obj);
+    cairo_surface_t* surface = CairoSurface::for_js(context, obj);
     if (!surface)
         return false;
 
@@ -196,7 +174,7 @@ getStride_func(JSContext *context,
         return false;
     }
 
-    cairo_surface_t* surface = gjs_cairo_surface_get_surface(context, obj);
+    cairo_surface_t* surface = CairoSurface::for_js(context, obj);
     if (!surface)
         return false;
 
@@ -209,39 +187,14 @@ getStride_func(JSContext *context,
     return true;
 }
 
-JSFunctionSpec gjs_cairo_image_surface_proto_funcs[] = {
+const JSFunctionSpec CairoImageSurface::proto_funcs[] = {
     JS_FN("createFromPNG", createFromPNG_func, 0, 0),
     // getData
     JS_FN("getFormat", getFormat_func, 0, 0),
     JS_FN("getWidth", getWidth_func, 0, 0),
     JS_FN("getHeight", getHeight_func, 0, 0),
-    JS_FN("getStride", getStride_func, 0, 0),
-    JS_FS_END};
+    JS_FN("getStride", getStride_func, 0, 0), JS_FS_END};
 
-JSFunctionSpec gjs_cairo_image_surface_static_funcs[] = {
+const JSFunctionSpec CairoImageSurface::static_funcs[] = {
     JS_FN("createFromPNG", createFromPNG_func, 1, GJS_MODULE_PROP_FLAGS),
     JS_FS_END};
-
-JSObject *
-gjs_cairo_image_surface_from_surface(JSContext       *context,
-                                     cairo_surface_t *surface)
-{
-    g_return_val_if_fail(context, nullptr);
-    g_return_val_if_fail(surface, nullptr);
-    g_return_val_if_fail(
-        cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE, nullptr);
-
-    JS::RootedObject proto(context, gjs_cairo_image_surface_get_proto(context));
-    JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_image_surface_class,
-                                   proto));
-    if (!object) {
-        gjs_throw(context, "failed to create image surface");
-        return nullptr;
-    }
-
-    gjs_cairo_surface_construct(object, surface);
-
-    return object;
-}
-
diff --git a/modules/cairo-pdf-surface.cpp b/modules/cairo-pdf-surface.cpp
index bbcbd196..77c9d71e 100644
--- a/modules/cairo-pdf-surface.cpp
+++ b/modules/cairo-pdf-surface.cpp
@@ -1,6 +1,7 @@
 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2010 litl, LLC.
+// SPDX-FileCopyrightText: 2020 Philip Chimento <philip chimento gmail com>
 
 #include <config.h>
 
@@ -13,57 +14,43 @@
 
 #if CAIRO_HAS_PDF_SURFACE
 #    include <cairo-pdf.h>
-#    include <glib.h>
 
-#    include <js/Class.h>
 #    include <js/PropertyDescriptor.h>  // for JSPROP_READONLY
 #    include <js/PropertySpec.h>
 #    include <js/RootingAPI.h>
 #    include <jsapi.h>  // for JS_NewObjectWithGivenProto
+#    include <jspubtd.h>  // for JSProtoKey
 
-#    include "gjs/jsapi-class.h"
 #    include "gjs/jsapi-util-args.h"
 #    include "modules/cairo-private.h"
 
-[[nodiscard]] static JSObject* gjs_cairo_pdf_surface_get_proto(JSContext*);
+namespace JS {
+class CallArgs;
+}
 
-GJS_DEFINE_PROTO_WITH_PARENT("PDFSurface", cairo_pdf_surface,
-                             cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
+JSObject* CairoPDFSurface::new_proto(JSContext* cx, JSProtoKey) {
+    JS::RootedObject parent_proto(cx, CairoSurface::prototype(cx));
+    return JS_NewObjectWithGivenProto(cx, nullptr, parent_proto);
+}
 
-GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_pdf_surface)
-{
-    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_pdf_surface)
+cairo_surface_t* CairoPDFSurface::constructor_impl(JSContext* context,
+                                                   const JS::CallArgs& argv) {
     GjsAutoChar filename;
     double width, height;
     cairo_surface_t *surface;
-
-    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_pdf_surface);
-
     if (!gjs_parse_call_args(context, "PDFSurface", argv, "Fff",
                              "filename", &filename,
                              "width", &width,
                              "height", &height))
-        return false;
+        return nullptr;
 
     surface = cairo_pdf_surface_create(filename, width, height);
 
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface),
                                 "surface"))
-        return false;
-
-    gjs_cairo_surface_construct(object, surface);
-    cairo_surface_destroy(surface);
-
-    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_pdf_surface);
-
-    return true;
-}
+        return nullptr;
 
-static void
-gjs_cairo_pdf_surface_finalize(JSFreeOp *fop,
-                               JSObject *obj)
-{
-    gjs_cairo_surface_finalize_surface(fop, obj);
+    return surface;
 }
 
 // clang-format off
@@ -71,40 +58,9 @@ JSPropertySpec gjs_cairo_pdf_surface_proto_props[] = {
     JS_STRING_SYM_PS(toStringTag, "PDFSurface", JSPROP_READONLY),
     JS_PS_END};
 // clang-format on
-
-JSFunctionSpec gjs_cairo_pdf_surface_proto_funcs[] = {
-    JS_FS_END
-};
-
-JSFunctionSpec gjs_cairo_pdf_surface_static_funcs[] = { JS_FS_END };
-
-JSObject *
-gjs_cairo_pdf_surface_from_surface(JSContext       *context,
-                                   cairo_surface_t *surface)
-{
-    g_return_val_if_fail(context, nullptr);
-    g_return_val_if_fail(surface, nullptr);
-    g_return_val_if_fail(
-        cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_PDF, nullptr);
-
-    JS::RootedObject proto(context, gjs_cairo_pdf_surface_get_proto(context));
-    JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_pdf_surface_class,
-                                   proto));
-    if (!object) {
-        gjs_throw(context, "failed to create pdf surface");
-        return nullptr;
-    }
-
-    gjs_cairo_surface_construct(object, surface);
-
-    return object;
-}
 #else
-JSObject *
-gjs_cairo_pdf_surface_from_surface(JSContext       *context,
-                                   cairo_surface_t *surface)
-{
+JSObject* CairoPDFSurface::from_c_ptr(JSContext* context,
+                                      cairo_surface_t* surface) {
     gjs_throw(context,
         "could not create PDF surface, recompile cairo and gjs with "
         "PDF support.");
diff --git a/modules/cairo-private.h b/modules/cairo-private.h
index ebe32f75..76dd75d5 100644
--- a/modules/cairo-private.h
+++ b/modules/cairo-private.h
@@ -116,68 +116,229 @@ class CairoPath : public CWrapper<CairoPath, cairo_path_t> {
 };
 
 /* surface */
-[[nodiscard]] JSObject* gjs_cairo_surface_get_proto(JSContext* cx);
 
-GJS_JSAPI_RETURN_CONVENTION
-bool gjs_cairo_surface_define_proto(JSContext              *cx,
-                                    JS::HandleObject        module,
-                                    JS::MutableHandleObject proto);
+class CairoSurface : public CWrapper<CairoSurface, cairo_surface_t> {
+    friend CWrapperPointerOps<CairoSurface, cairo_surface_t>;
+    friend CWrapper<CairoSurface, cairo_surface_t>;
+    friend class CairoImageSurface;  // "inherits" from CairoSurface
+    friend class CairoPSSurface;
+    friend class CairoPDFSurface;
+    friend class CairoSVGSurface;
 
-void gjs_cairo_surface_construct(JSObject* object, cairo_surface_t* surface);
-void             gjs_cairo_surface_finalize_surface     (JSFreeOp        *fop,
-                                                         JSObject        *object);
-GJS_JSAPI_RETURN_CONVENTION
-JSObject *       gjs_cairo_surface_from_surface         (JSContext       *context,
-                                                         cairo_surface_t *surface);
-GJS_JSAPI_RETURN_CONVENTION
-cairo_surface_t* gjs_cairo_surface_get_surface(
-    JSContext* cx, JS::HandleObject surface_wrapper);
+    CairoSurface() = delete;
+    CairoSurface(CairoSurface&) = delete;
+    CairoSurface(CairoSurface&&) = delete;
 
-/* image surface */
-GJS_JSAPI_RETURN_CONVENTION
-bool gjs_cairo_image_surface_define_proto(JSContext              *cx,
-                                          JS::HandleObject        module,
-                                          JS::MutableHandleObject proto);
+    static constexpr GjsGlobalSlot PROTOTYPE_SLOT =
+        GjsGlobalSlot::PROTOTYPE_cairo_surface;
+    static constexpr GjsDebugTopic DEBUG_TOPIC = GJS_DEBUG_CAIRO;
 
-void             gjs_cairo_image_surface_init           (JSContext       *context,
-                                                         JS::HandleObject proto);
+    static GType gtype() { return CAIRO_GOBJECT_TYPE_SURFACE; }
 
-GJS_JSAPI_RETURN_CONVENTION
-JSObject *       gjs_cairo_image_surface_from_surface   (JSContext       *context,
-                                                         cairo_surface_t *surface);
+    static void finalize_impl(JSFreeOp* fop, cairo_surface_t* surface);
+
+    static const JSFunctionSpec proto_funcs[];
+    static const JSPropertySpec proto_props[];
+    static constexpr js::ClassSpec class_spec = {
+        &CairoSurface::create_abstract_constructor,
+        nullptr,  // createPrototype
+        nullptr,  // constructorFunctions
+        nullptr,  // constructorProperties
+        CairoSurface::proto_funcs,
+        CairoSurface::proto_props,
+        &CairoSurface::define_gtype_prop,
+    };
+    static constexpr JSClass klass = {
+        "Surface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+        &CairoSurface::class_ops, &CairoSurface::class_spec};
+
+    static cairo_surface_t* copy_ptr(cairo_surface_t* surface) {
+        return cairo_surface_reference(surface);
+    }
+
+ public:
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* from_c_ptr(JSContext* cx, cairo_surface_t* surface);
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static cairo_surface_t* for_js(JSContext* cx,
+                                   JS::HandleObject surface_wrapper);
+};
+
+class CairoImageSurface : public CWrapper<CairoImageSurface, cairo_surface_t> {
+    friend CWrapperPointerOps<CairoImageSurface, cairo_surface_t>;
+    friend CWrapper<CairoImageSurface, cairo_surface_t>;
+
+    static constexpr GjsGlobalSlot PROTOTYPE_SLOT =
+        GjsGlobalSlot::PROTOTYPE_cairo_image_surface;
+    static constexpr GjsDebugTopic DEBUG_TOPIC = GJS_DEBUG_CAIRO;
+    static constexpr unsigned constructor_nargs = 3;
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* new_proto(JSContext* cx, JSProtoKey);
+
+    static const JSFunctionSpec static_funcs[];
+    static const JSFunctionSpec proto_funcs[];
+    static const JSPropertySpec proto_props[];
+    static constexpr js::ClassSpec class_spec = {
+        nullptr,  // createConstructor,
+        &CairoImageSurface::new_proto,
+        CairoImageSurface::static_funcs,
+        nullptr,  // constructorProperties
+        CairoImageSurface::proto_funcs,
+        CairoImageSurface::proto_props,
+        &CairoSurface::define_gtype_prop,
+    };
+    static constexpr JSClass klass = {
+        "ImageSurface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+        &CairoSurface::class_ops, &CairoImageSurface::class_spec};
+
+    static cairo_surface_t* copy_ptr(cairo_surface_t* surface) {
+        return cairo_surface_reference(surface);
+    }
+
+    static void finalize_impl(JSFreeOp*, cairo_surface_t*) {}
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static cairo_surface_t* constructor_impl(JSContext* cx,
+                                             const JS::CallArgs& args);
+};
 
-/* postscript surface */
 #ifdef CAIRO_HAS_PS_SURFACE
-GJS_JSAPI_RETURN_CONVENTION
-bool gjs_cairo_ps_surface_define_proto(JSContext              *cx,
-                                       JS::HandleObject        module,
-                                       JS::MutableHandleObject proto);
-#endif
-GJS_JSAPI_RETURN_CONVENTION
-JSObject *       gjs_cairo_ps_surface_from_surface       (JSContext       *context,
-                                                          cairo_surface_t *surface);
+class CairoPSSurface : public CWrapper<CairoPSSurface, cairo_surface_t> {
+    friend CWrapperPointerOps<CairoPSSurface, cairo_surface_t>;
+    friend CWrapper<CairoPSSurface, cairo_surface_t>;
+
+    static constexpr GjsGlobalSlot PROTOTYPE_SLOT =
+        GjsGlobalSlot::PROTOTYPE_cairo_ps_surface;
+    static constexpr GjsDebugTopic DEBUG_TOPIC = GJS_DEBUG_CAIRO;
+    static constexpr unsigned constructor_nargs = 3;
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* new_proto(JSContext* cx, JSProtoKey);
+
+    static const JSFunctionSpec proto_funcs[];
+    static const JSPropertySpec proto_props[];
+    static constexpr js::ClassSpec class_spec = {
+        nullptr,  // createConstructor,
+        &CairoPSSurface::new_proto,
+        nullptr,  // constructorFunctions
+        nullptr,  // constructorProperties
+        CairoPSSurface::proto_funcs,
+        CairoPSSurface::proto_props,
+        &CairoSurface::define_gtype_prop,
+    };
+    static constexpr JSClass klass = {
+        "PSSurface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+        &CairoSurface::class_ops, &CairoPSSurface::class_spec};
+
+    static cairo_surface_t* copy_ptr(cairo_surface_t* surface) {
+        return cairo_surface_reference(surface);
+    }
+
+    static void finalize_impl(JSFreeOp*, cairo_surface_t*) {}
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static cairo_surface_t* constructor_impl(JSContext* cx,
+                                             const JS::CallArgs& args);
+};
+#else
+class CairoPSSurface {
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* from_c_ptr(JSContext* cx, cairo_surface_t* surface);
+}
+#endif  // CAIRO_HAS_PS_SURFACE
 
-/* pdf surface */
 #ifdef CAIRO_HAS_PDF_SURFACE
-GJS_JSAPI_RETURN_CONVENTION
-bool gjs_cairo_pdf_surface_define_proto(JSContext              *cx,
-                                        JS::HandleObject        module,
-                                        JS::MutableHandleObject proto);
-#endif
-GJS_JSAPI_RETURN_CONVENTION
-JSObject *       gjs_cairo_pdf_surface_from_surface     (JSContext       *context,
-                                                         cairo_surface_t *surface);
+class CairoPDFSurface : public CWrapper<CairoPDFSurface, cairo_surface_t> {
+    friend CWrapperPointerOps<CairoPDFSurface, cairo_surface_t>;
+    friend CWrapper<CairoPDFSurface, cairo_surface_t>;
+
+    static constexpr GjsGlobalSlot PROTOTYPE_SLOT =
+        GjsGlobalSlot::PROTOTYPE_cairo_pdf_surface;
+    static constexpr GjsDebugTopic DEBUG_TOPIC = GJS_DEBUG_CAIRO;
+    static constexpr unsigned constructor_nargs = 3;
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* new_proto(JSContext* cx, JSProtoKey);
+
+    static const JSFunctionSpec proto_funcs[];
+    static const JSPropertySpec proto_props[];
+    static constexpr js::ClassSpec class_spec = {
+        nullptr,  // createConstructor,
+        &CairoPDFSurface::new_proto,
+        nullptr,  // constructorFunctions
+        nullptr,  // constructorProperties
+        CairoSurface::proto_funcs,
+        CairoSurface::proto_props,
+        &CairoSurface::define_gtype_prop,
+    };
+    static constexpr JSClass klass = {
+        "PDFSurface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+        &CairoSurface::class_ops, &CairoPDFSurface::class_spec};
+
+    static cairo_surface_t* copy_ptr(cairo_surface_t* surface) {
+        return cairo_surface_reference(surface);
+    }
+
+    static void finalize_impl(JSFreeOp*, cairo_surface_t*) {}
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static cairo_surface_t* constructor_impl(JSContext* cx,
+                                             const JS::CallArgs& args);
+};
+#else
+class CairoPDFSurface {
+ public:
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* from_c_ptr(JSContext* cx, cairo_surface_t* surface);
+}
+#endif  // CAIRO_HAS_PDF_SURFACE
 
-/* svg surface */
 #ifdef CAIRO_HAS_SVG_SURFACE
-GJS_JSAPI_RETURN_CONVENTION
-bool gjs_cairo_svg_surface_define_proto(JSContext              *cx,
-                                        JS::HandleObject        module,
-                                        JS::MutableHandleObject proto);
-#endif
-GJS_JSAPI_RETURN_CONVENTION
-JSObject *       gjs_cairo_svg_surface_from_surface     (JSContext       *context,
-                                                         cairo_surface_t *surface);
+class CairoSVGSurface : public CWrapper<CairoSVGSurface, cairo_surface_t> {
+    friend CWrapperPointerOps<CairoSVGSurface, cairo_surface_t>;
+    friend CWrapper<CairoSVGSurface, cairo_surface_t>;
+
+    static constexpr GjsGlobalSlot PROTOTYPE_SLOT =
+        GjsGlobalSlot::PROTOTYPE_cairo_svg_surface;
+    static constexpr GjsDebugTopic DEBUG_TOPIC = GJS_DEBUG_CAIRO;
+    static constexpr unsigned constructor_nargs = 3;
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* new_proto(JSContext* cx, JSProtoKey);
+
+    static const JSPropertySpec proto_props[];
+    static constexpr js::ClassSpec class_spec = {
+        nullptr,  // createConstructor,
+        &CairoSVGSurface::new_proto,
+        nullptr,  // constructorFunctions
+        nullptr,  // constructorProperties
+        nullptr,  // prototypeFunctions
+        CairoSVGSurface::proto_props,
+        &CairoSurface::define_gtype_prop,
+    };
+    static constexpr JSClass klass = {
+        "SVGSurface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
+        &CairoSurface::class_ops, &CairoSVGSurface::class_spec};
+
+    static cairo_surface_t* copy_ptr(cairo_surface_t* surface) {
+        return cairo_surface_reference(surface);
+    }
+
+    static void finalize_impl(JSFreeOp*, cairo_surface_t*) {}
+
+    GJS_JSAPI_RETURN_CONVENTION
+    static cairo_surface_t* constructor_impl(JSContext* cx,
+                                             const JS::CallArgs& args);
+};
+#else
+class CairoSVGSurface {
+ public:
+    GJS_JSAPI_RETURN_CONVENTION
+    static JSObject* from_c_ptr(JSContext* cx, cairo_surface_t* surface);
+}
+#endif  // CAIRO_HAS_SVG_SURFACE
 
 /* pattern */
 
diff --git a/modules/cairo-ps-surface.cpp b/modules/cairo-ps-surface.cpp
index de3d24e8..fc75774f 100644
--- a/modules/cairo-ps-surface.cpp
+++ b/modules/cairo-ps-surface.cpp
@@ -1,6 +1,7 @@
 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2010 litl, LLC.
+// SPDX-FileCopyrightText: 2020 Philip Chimento <philip chimento gmail com>
 
 #include <config.h>
 
@@ -13,66 +14,52 @@
 
 #if CAIRO_HAS_PS_SURFACE
 #    include <cairo-ps.h>
-#    include <glib.h>
 
-#    include <js/Class.h>
 #    include <js/PropertyDescriptor.h>  // for JSPROP_READONLY
 #    include <js/PropertySpec.h>
 #    include <js/RootingAPI.h>
 #    include <jsapi.h>  // for JS_NewObjectWithGivenProto
+#    include <jspubtd.h>  // for JSProtoKey
 
-#    include "gjs/jsapi-class.h"
 #    include "gjs/jsapi-util-args.h"
 #    include "modules/cairo-private.h"
 
-[[nodiscard]] static JSObject* gjs_cairo_ps_surface_get_proto(JSContext*);
+namespace JS {
+class CallArgs;
+}
 
-GJS_DEFINE_PROTO_WITH_PARENT("PSSurface", cairo_ps_surface, cairo_surface,
-                             JSCLASS_BACKGROUND_FINALIZE)
+JSObject* CairoPSSurface::new_proto(JSContext* cx, JSProtoKey) {
+    JS::RootedObject parent_proto(cx, CairoSurface::prototype(cx));
+    return JS_NewObjectWithGivenProto(cx, nullptr, parent_proto);
+}
 
-GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_ps_surface)
-{
-    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_ps_surface)
+cairo_surface_t* CairoPSSurface::constructor_impl(JSContext* context,
+                                                  const JS::CallArgs& argv) {
     GjsAutoChar filename;
     double width, height;
     cairo_surface_t *surface;
-
-    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_ps_surface);
-
     if (!gjs_parse_call_args(context, "PSSurface", argv, "Fff",
                              "filename", &filename,
                              "width", &width,
                              "height", &height))
-        return false;
+        return nullptr;
 
     surface = cairo_ps_surface_create(filename, width, height);
 
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface),
                                 "surface"))
-        return false;
-
-    gjs_cairo_surface_construct(object, surface);
-    cairo_surface_destroy(surface);
-
-    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_ps_surface);
-
-    return true;
-}
+        return nullptr;
 
-static void
-gjs_cairo_ps_surface_finalize(JSFreeOp *fop,
-                              JSObject *obj)
-{
-    gjs_cairo_surface_finalize_surface(fop, obj);
+    return surface;
 }
 
 // clang-format off
-JSPropertySpec gjs_cairo_ps_surface_proto_props[] = {
+const JSPropertySpec CairoPSSurface::proto_props[] = {
     JS_STRING_SYM_PS(toStringTag, "PSSurface", JSPROP_READONLY),
     JS_PS_END};
 // clang-format on
 
-JSFunctionSpec gjs_cairo_ps_surface_proto_funcs[] = {
+const JSFunctionSpec CairoPSSurface::proto_funcs[] = {
     // restrictToLevel
     // getLevels
     // levelToString
@@ -82,37 +69,11 @@ JSFunctionSpec gjs_cairo_ps_surface_proto_funcs[] = {
     // dscBeginSetup
     // dscBeginPageSetup
     // dscComment
-    JS_FS_END
-};
-
-JSFunctionSpec gjs_cairo_ps_surface_static_funcs[] = { JS_FS_END };
-
-JSObject *
-gjs_cairo_ps_surface_from_surface(JSContext       *context,
-                                  cairo_surface_t *surface)
-{
-    g_return_val_if_fail(context, nullptr);
-    g_return_val_if_fail(surface, nullptr);
-    g_return_val_if_fail(
-        cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_PS, nullptr);
-
-    JS::RootedObject proto(context, gjs_cairo_ps_surface_get_proto(context));
-    JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_ps_surface_class, proto));
-    if (!object) {
-        gjs_throw(context, "failed to create ps surface");
-        return nullptr;
-    }
-
-    gjs_cairo_surface_construct(object, surface);
+    JS_FS_END};
 
-    return object;
-}
 #else
-JSObject *
-gjs_cairo_ps_surface_from_surface(JSContext       *context,
-                                  cairo_surface_t *surface)
-{
+JSObject* CairoPSSurface::from_c_ptr(JSContext* context,
+                                     cairo_surface_t* surface) {
     gjs_throw(context,
         "could not create PS surface, recompile cairo and gjs with "
         "PS support.");
diff --git a/modules/cairo-surface-pattern.cpp b/modules/cairo-surface-pattern.cpp
index 2639e422..a4361bbb 100644
--- a/modules/cairo-surface-pattern.cpp
+++ b/modules/cairo-surface-pattern.cpp
@@ -32,8 +32,7 @@ cairo_pattern_t* CairoSurfacePattern::constructor_impl(
                              "surface", &surface_wrapper))
         return nullptr;
 
-    cairo_surface_t* surface =
-        gjs_cairo_surface_get_surface(context, surface_wrapper);
+    cairo_surface_t* surface = CairoSurface::for_js(context, surface_wrapper);
     if (!surface)
         return nullptr;
 
diff --git a/modules/cairo-surface.cpp b/modules/cairo-surface.cpp
index 3d4067fb..2818adf0 100644
--- a/modules/cairo-surface.cpp
+++ b/modules/cairo-surface.cpp
@@ -4,7 +4,6 @@
 
 #include <config.h>
 
-#include <cairo-gobject.h>
 #include <cairo.h>
 #include <girepository.h>
 #include <glib.h>
@@ -20,6 +19,7 @@
 
 #include "gi/arg-inl.h"
 #include "gi/arg.h"
+#include "gi/cwrapper.h"
 #include "gi/foreign.h"
 #include "gjs/enum-utils.h"
 #include "gjs/jsapi-class.h"
@@ -28,25 +28,9 @@
 #include "gjs/macros.h"
 #include "modules/cairo-private.h"
 
-struct GjsCairoSurface
-    : GjsAutoPointer<cairo_surface_t, cairo_surface_t, cairo_surface_destroy,
-                     cairo_surface_reference> {
-    explicit GjsCairoSurface(cairo_surface_t* surface)
-        : GjsAutoPointer(surface, GjsAutoTakeOwnership()) {}
-};
-
-GJS_DEFINE_PROTO_ABSTRACT_WITH_GTYPE("Surface", cairo_surface,
-                                     CAIRO_GOBJECT_TYPE_SURFACE,
-                                     JSCLASS_BACKGROUND_FINALIZE)
-
-static void gjs_cairo_surface_finalize(JSFreeOp*, JSObject* obj) {
-    delete static_cast<GjsCairoSurface*>(JS_GetPrivate(obj));
-    JS_SetPrivate(obj, nullptr);
-}
-
 /* Properties */
 // clang-format off
-JSPropertySpec gjs_cairo_surface_proto_props[] = {
+const JSPropertySpec CairoSurface::proto_props[] = {
     JS_STRING_SYM_PS(toStringTag, "Surface", JSPROP_READONLY),
     JS_PS_END};
 // clang-format on
@@ -65,7 +49,7 @@ writeToPNG_func(JSContext *context,
                              "filename", &filename))
         return false;
 
-    cairo_surface_t* surface = gjs_cairo_surface_get_surface(context, obj);
+    cairo_surface_t* surface = CairoSurface::for_js(context, obj);
     if (!surface)
         return false;
 
@@ -91,7 +75,7 @@ getType_func(JSContext *context,
         return false;
     }
 
-    cairo_surface_t* surface = gjs_cairo_surface_get_surface(context, obj);
+    cairo_surface_t* surface = CairoSurface::for_js(context, obj);
     if (!surface)
         return false;
 
@@ -104,7 +88,7 @@ getType_func(JSContext *context,
     return true;
 }
 
-JSFunctionSpec gjs_cairo_surface_proto_funcs[] = {
+const JSFunctionSpec CairoSurface::proto_funcs[] = {
     // flush
     // getContent
     // getFontOptions
@@ -118,52 +102,27 @@ JSFunctionSpec gjs_cairo_surface_proto_funcs[] = {
     // copyPage
     // showPage
     // hasShowTextGlyphs
-    JS_FN("writeToPNG", writeToPNG_func, 0, 0),
-    JS_FS_END};
-
-JSFunctionSpec gjs_cairo_surface_static_funcs[] = { JS_FS_END };
+    JS_FN("writeToPNG", writeToPNG_func, 0, 0), JS_FS_END};
 
 /* Public API */
 
 /**
- * gjs_cairo_surface_construct:
- * @object: object to construct
- * @surface: cairo_surface to attach to the object
- *
- * Constructs a surface wrapper giving an empty JSObject and a
- * cairo surface. A reference to @surface will be taken.
- *
- * This is mainly used for subclasses where object is already created.
- */
-void gjs_cairo_surface_construct(JSObject* object, cairo_surface_t* surface) {
-    g_return_if_fail(object);
-    g_return_if_fail(surface);
-
-    g_assert(!JS_GetPrivate(object));
-    JS_SetPrivate(object, new GjsCairoSurface(surface));
-}
-
-/**
- * gjs_cairo_surface_finalize:
+ * CairoSurface::finalize_impl:
  * @fop: the free op
- * @object: object to finalize
+ * @surface: the pointer to finalize
  *
  * Destroys the resources associated with a surface wrapper.
  *
  * This is mainly used for subclasses.
  */
-void
-gjs_cairo_surface_finalize_surface(JSFreeOp *fop,
-                                   JSObject *object)
-{
-    g_return_if_fail(fop);
-    g_return_if_fail(object);
-
-    gjs_cairo_surface_finalize(fop, object);
+void CairoSurface::finalize_impl(JSFreeOp*, cairo_surface_t* surface) {
+    if (!surface)
+        return;
+    cairo_surface_destroy(surface);
 }
 
 /**
- * gjs_cairo_surface_from_surface:
+ * CairoSurface::from_c_ptr:
  * @context: the context
  * @surface: cairo_surface to attach to the object
  *
@@ -171,49 +130,38 @@ gjs_cairo_surface_finalize_surface(JSFreeOp *fop,
  * A reference to @surface will be taken.
  *
  */
-JSObject *
-gjs_cairo_surface_from_surface(JSContext       *context,
-                               cairo_surface_t *surface)
-{
+JSObject* CairoSurface::from_c_ptr(JSContext* context,
+                                   cairo_surface_t* surface) {
     g_return_val_if_fail(context, nullptr);
     g_return_val_if_fail(surface, nullptr);
 
     cairo_surface_type_t type = cairo_surface_get_type(surface);
     if (type == CAIRO_SURFACE_TYPE_IMAGE)
-        return gjs_cairo_image_surface_from_surface(context, surface);
+        return CairoImageSurface::from_c_ptr(context, surface);
     if (type == CAIRO_SURFACE_TYPE_PDF)
-        return gjs_cairo_pdf_surface_from_surface(context, surface);
+        return CairoPDFSurface::from_c_ptr(context, surface);
     if (type == CAIRO_SURFACE_TYPE_PS)
-        return gjs_cairo_ps_surface_from_surface(context, surface);
+        return CairoPSSurface::from_c_ptr(context, surface);
     if (type == CAIRO_SURFACE_TYPE_SVG)
-        return gjs_cairo_svg_surface_from_surface(context, surface);
-
-    JS::RootedObject proto(context, gjs_cairo_surface_get_proto(context));
-    JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_surface_class, proto));
-    if (!object) {
-        gjs_throw(context, "failed to create surface");
-        return nullptr;
-    }
-
-    gjs_cairo_surface_construct(object, surface);
-
-    return object;
+        return CairoSVGSurface::from_c_ptr(context, surface);
+    return CairoSurface::CWrapper::from_c_ptr(context, surface);
 }
 
 /**
- * gjs_cairo_surface_get_surface:
+ * CairoSurface::for_js:
  * @cx: the context
  * @surface_wrapper: surface wrapper
  *
+ * Overrides NativeObject::for_js().
+ *
  * Returns: the surface attached to the wrapper.
  */
-cairo_surface_t* gjs_cairo_surface_get_surface(
-    JSContext* cx, JS::HandleObject surface_wrapper) {
+cairo_surface_t* CairoSurface::for_js(JSContext* cx,
+                                      JS::HandleObject surface_wrapper) {
     g_return_val_if_fail(cx, nullptr);
     g_return_val_if_fail(surface_wrapper, nullptr);
 
-    JS::RootedObject proto(cx, gjs_cairo_surface_get_proto(cx));
+    JS::RootedObject proto(cx, CairoSurface::prototype(cx));
 
     bool is_surface_subclass = false;
     if (!gjs_object_in_prototype_chain(cx, proto, surface_wrapper,
@@ -225,8 +173,7 @@ cairo_surface_t* gjs_cairo_surface_get_surface(
         return nullptr;
     }
 
-    auto* priv = static_cast<GjsCairoSurface*>(JS_GetPrivate(surface_wrapper));
-    return priv ? priv->get() : nullptr;
+    return static_cast<cairo_surface_t*>(JS_GetPrivate(surface_wrapper));
 }
 
 [[nodiscard]] static bool surface_to_g_argument(
@@ -253,8 +200,7 @@ cairo_surface_t* gjs_cairo_surface_get_surface(
     }
 
     JS::RootedObject surface_wrapper(context, &value.toObject());
-    cairo_surface_t* s =
-        gjs_cairo_surface_get_surface(context, surface_wrapper);
+    cairo_surface_t* s = CairoSurface::for_js(context, surface_wrapper);
     if (!s)
         return false;
     if (transfer == GI_TRANSFER_EVERYTHING)
@@ -265,13 +211,11 @@ cairo_surface_t* gjs_cairo_surface_get_surface(
 }
 
 GJS_JSAPI_RETURN_CONVENTION
-static bool
-surface_from_g_argument(JSContext             *context,
-                        JS::MutableHandleValue value_p,
-                        GIArgument            *arg)
-{
-    JSObject* obj = gjs_cairo_surface_from_surface(
-        context, gjs_arg_get<cairo_surface_t*>(arg));
+static bool surface_from_g_argument(JSContext* cx,
+                                    JS::MutableHandleValue value_p,
+                                    GIArgument* arg) {
+    JSObject* obj =
+        CairoSurface::from_c_ptr(cx, gjs_arg_get<cairo_surface_t*>(arg));
     if (!obj)
         return false;
 
diff --git a/modules/cairo-svg-surface.cpp b/modules/cairo-svg-surface.cpp
index e5190ac0..cb57707e 100644
--- a/modules/cairo-svg-surface.cpp
+++ b/modules/cairo-svg-surface.cpp
@@ -1,6 +1,7 @@
 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2010 litl, LLC.
+// SPDX-FileCopyrightText: 2020 Philip Chimento <philip chimento gmail com>
 
 #include <config.h>
 
@@ -13,98 +14,54 @@
 
 #if CAIRO_HAS_SVG_SURFACE
 #    include <cairo-svg.h>
-#    include <glib.h>
 
-#    include <js/Class.h>
 #    include <js/PropertyDescriptor.h>  // for JSPROP_READONLY
 #    include <js/PropertySpec.h>
 #    include <js/RootingAPI.h>
 #    include <jsapi.h>  // for JS_NewObjectWithGivenProto
+#    include <jspubtd.h>  // for JSProtoKey
 
-#    include "gjs/jsapi-class.h"
 #    include "gjs/jsapi-util-args.h"
 #    include "modules/cairo-private.h"
 
-[[nodiscard]] static JSObject* gjs_cairo_svg_surface_get_proto(JSContext*);
+namespace JS {
+class CallArgs;
+}
 
-GJS_DEFINE_PROTO_WITH_PARENT("SVGSurface", cairo_svg_surface,
-                             cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
+JSObject* CairoSVGSurface::new_proto(JSContext* cx, JSProtoKey) {
+    JS::RootedObject parent_proto(cx, CairoSurface::prototype(cx));
+    return JS_NewObjectWithGivenProto(cx, nullptr, parent_proto);
+}
 
-GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_svg_surface)
-{
-    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_svg_surface)
+cairo_surface_t* CairoSVGSurface::constructor_impl(JSContext* context,
+                                                   const JS::CallArgs& argv) {
     GjsAutoChar filename;
     double width, height;
     cairo_surface_t *surface;
-
-    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_svg_surface);
-
     if (!gjs_parse_call_args(context, "SVGSurface", argv, "Fff",
                              "filename", &filename,
                              "width", &width,
                              "height", &height))
-        return false;
+        return nullptr;
 
     surface = cairo_svg_surface_create(filename, width, height);
 
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface),
                                 "surface"))
-        return false;
-
-    gjs_cairo_surface_construct(object, surface);
-    cairo_surface_destroy(surface);
-
-    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_svg_surface);
-
-    return true;
-}
+        return nullptr;
 
-static void
-gjs_cairo_svg_surface_finalize(JSFreeOp *fop,
-                               JSObject *obj)
-{
-    gjs_cairo_surface_finalize_surface(fop, obj);
+    return surface;
 }
 
 // clang-format off
-JSPropertySpec gjs_cairo_svg_surface_proto_props[] = {
+const JSPropertySpec CairoSVGSurface::proto_props[] = {
     JS_STRING_SYM_PS(toStringTag, "SVGSurface", JSPROP_READONLY),
     JS_PS_END};
 // clang-format on
 
-JSFunctionSpec gjs_cairo_svg_surface_proto_funcs[] = {
-    JS_FS_END
-};
-
-JSFunctionSpec gjs_cairo_svg_surface_static_funcs[] = { JS_FS_END };
-
-JSObject *
-gjs_cairo_svg_surface_from_surface(JSContext       *context,
-                                   cairo_surface_t *surface)
-{
-    g_return_val_if_fail(context, nullptr);
-    g_return_val_if_fail(surface, nullptr);
-    g_return_val_if_fail(
-        cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_SVG, nullptr);
-
-    JS::RootedObject proto(context, gjs_cairo_svg_surface_get_proto(context));
-    JS::RootedObject object(context,
-        JS_NewObjectWithGivenProto(context, &gjs_cairo_svg_surface_class,
-                                   proto));
-    if (!object) {
-        gjs_throw(context, "failed to create svg surface");
-        return nullptr;
-    }
-
-    gjs_cairo_surface_construct(object, surface);
-
-    return object;
-}
 #else
-JSObject *
-gjs_cairo_svg_surface_from_surface(JSContext       *context,
-                                   cairo_surface_t *surface)
-{
+JSObject* CairoSVGSurface::from_c_ptr(JSContext* context,
+                                      cairo_surface_t* surface) {
     gjs_throw(context,
         "could not create SVG surface, recompile cairo and gjs with "
         "SVG support.");
diff --git a/modules/cairo.cpp b/modules/cairo.cpp
index 2cd7ae5c..652b1b06 100644
--- a/modules/cairo.cpp
+++ b/modules/cairo.cpp
@@ -65,26 +65,25 @@ gjs_js_define_cairo_stuff(JSContext              *context,
         return false;
     gjs_cairo_context_init();
 
-    if (!gjs_cairo_surface_define_proto(context, module, &proto))
+    if (!CairoSurface::create_prototype(context, module))
         return false;
     gjs_cairo_surface_init();
 
-    return
-        gjs_cairo_image_surface_define_proto(context, module, &proto) &&
-        CairoPath::create_prototype(context, module) &&
+    return CairoImageSurface::create_prototype(context, module) &&
+           CairoPath::create_prototype(context, module) &&
 #if CAIRO_HAS_PS_SURFACE
-        gjs_cairo_ps_surface_define_proto(context, module, &proto) &&
+           CairoPSSurface::create_prototype(context, module) &&
 #endif
 #if CAIRO_HAS_PDF_SURFACE
-        gjs_cairo_pdf_surface_define_proto(context, module, &proto) &&
+           CairoPDFSurface::create_prototype(context, module) &&
 #endif
 #if CAIRO_HAS_SVG_SURFACE
-        gjs_cairo_svg_surface_define_proto(context, module, &proto) &&
+           CairoSVGSurface::create_prototype(context, module) &&
 #endif
-        CairoPattern::create_prototype(context, module) &&
-        CairoGradient::create_prototype(context, module) &&
-        CairoLinearGradient::create_prototype(context, module) &&
-        CairoRadialGradient::create_prototype(context, module) &&
-        CairoSurfacePattern::create_prototype(context, module) &&
-        CairoSolidPattern::create_prototype(context, module);
+           CairoPattern::create_prototype(context, module) &&
+           CairoGradient::create_prototype(context, module) &&
+           CairoLinearGradient::create_prototype(context, module) &&
+           CairoRadialGradient::create_prototype(context, module) &&
+           CairoSurfacePattern::create_prototype(context, module) &&
+           CairoSolidPattern::create_prototype(context, module);
 }


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