[gjs: 7/8] Use fast constructors if available



commit 7ae2fa5662e327ccd6bdb624ef66bd8edba6659e
Author: Colin Walters <walters verbum org>
Date:   Wed Oct 20 16:50:41 2010 -0400

    Use fast constructors if available
    
    "slow" natives were removed in the mozjs commit:
    http://hg.mozilla.org/mozilla-central/rev/66c8ad02543b
    
    In order to work with both, add compatibility macros to compat.h,
    and also update the ones in jsapi-util.h to use these.
    
    Port all constructors to use these macros.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=632159

 Makefile.am                     |    2 +-
 gi/boxed.c                      |   42 +++++++++++++-----------
 gi/function.c                   |   67 +++++++++++++++++++++++++++++---------
 gi/keep-alive.c                 |   20 ++++++------
 gi/ns.c                         |   20 ++++++------
 gi/object.c                     |   35 +++++++++-----------
 gi/param.c                      |   25 ++++++--------
 gi/repo.c                       |   20 ++++++------
 gi/union.c                      |   27 +++++++---------
 gjs/byteArray.c                 |   29 ++++++----------
 gjs/compat.h                    |   65 +++++++++++++++++++++++++++++++++++++
 gjs/importer.c                  |   20 ++++++------
 gjs/jsapi-util.c                |   16 ++-------
 gjs/jsapi-util.h                |   45 ++++++++++++--------------
 modules/cairo-context.c         |   17 ++++------
 modules/cairo-gradient.c        |    2 +-
 modules/cairo-image-surface.c   |   17 ++++------
 modules/cairo-linear-gradient.c |   19 +++++------
 modules/cairo-path.c            |    2 +-
 modules/cairo-pattern.c         |    3 +-
 modules/cairo-pdf-surface.c     |   17 ++++------
 modules/cairo-ps-surface.c      |   17 ++++------
 modules/cairo-radial-gradient.c |   19 +++++------
 modules/cairo-solid-pattern.c   |    2 +-
 modules/cairo-surface-pattern.c |   17 ++++------
 modules/cairo-surface.c         |    3 +-
 modules/cairo-svg-surface.c     |   17 ++++------
 modules/dbus-exports.c          |   22 ++++++------
 28 files changed, 327 insertions(+), 280 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index c9978cb..aecbdbe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -25,6 +25,7 @@ nobase_gjs_public_include_HEADERS =	\
 
 nobase_gjs_module_include_HEADERS =	\
 	gjs/gjs-module.h	\
+	gjs/compat.h		\
 	gjs/byteArray.h		\
 	gjs/importer.h		\
 	gjs/jsapi-util.h	\
@@ -32,7 +33,6 @@ nobase_gjs_module_include_HEADERS =	\
 	gjs/native.h
 
 noinst_HEADERS +=		\
-	gjs/compat.h		\
 	gjs/jsapi-private.h	\
 	gjs/profiler.h		\
 	gjs/unit-test-utils.h	\
diff --git a/gi/boxed.c b/gi/boxed.c
index a5e1560..f27a899 100644
--- a/gi/boxed.c
+++ b/gi/boxed.c
@@ -405,13 +405,9 @@ boxed_init(JSContext   *context,
  * identify the prototype as an object of our class with NULL private
  * data.
  */
-static JSBool
-boxed_constructor(JSContext *context,
-                  JSObject  *obj,
-                  uintN      argc,
-                  jsval     *argv,
-                  jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(boxed)
     Boxed *priv;
     Boxed *proto_priv;
     JSClass *obj_class;
@@ -419,28 +415,27 @@ boxed_constructor(JSContext *context,
     JSObject *proto;
     gboolean is_proto;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(boxed);
 
     priv = g_slice_new0(Boxed);
 
     GJS_INC_COUNTER(boxed);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
                         "boxed constructor, obj %p priv %p",
-                        obj, priv);
+                        object, priv);
 
-    proto = JS_GetPrototype(context, obj);
+    proto = JS_GetPrototype(context, object);
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED, "boxed instance __proto__ is %p", proto);
 
     /* If we're constructing the prototype, its __proto__ is not the same
      * class as us, but if we're constructing an instance, the prototype
      * has the same class.
      */
-    obj_class = JS_GET_CLASS(context, obj);
+    obj_class = JS_GET_CLASS(context, object);
     proto_class = JS_GET_CLASS(context, proto);
 
     is_proto = (obj_class != proto_class);
@@ -486,14 +481,15 @@ boxed_constructor(JSContext *context,
                 GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
                 if (gtype != G_TYPE_NONE) {
                     priv->gboxed = g_boxed_copy(gtype, source_priv->gboxed);
+                    GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
                     return JS_TRUE;
                 }
             }
 
-            if (!boxed_new(context, obj, priv))
+            if (!boxed_new(context, object, priv))
                 return JS_FALSE;
 
-            if (!boxed_init(context, obj, priv, argc, argv))
+            if (!boxed_init(context, object, priv, argc, argv))
                 return JS_FALSE;
 
         } else if (!JSVAL_IS_NULL(unthreadsafe_template_for_constructor.parent_jsval)) {
@@ -505,7 +501,7 @@ boxed_constructor(JSContext *context,
             /* We never actually read the reserved slot, but we put the parent object
              * into it to hold onto the parent object.
              */
-            JS_SetReservedSlot(context, obj, 0,
+            JS_SetReservedSlot(context, object, 0,
                                unthreadsafe_template_for_constructor.parent_jsval);
 
             unthreadsafe_template_for_constructor.parent_jsval = JSVAL_NULL;
@@ -520,12 +516,13 @@ boxed_constructor(JSContext *context,
             unthreadsafe_template_for_constructor.gboxed = NULL;
         } else {
             GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
-
+            JSBool retval;
+            
             if (gtype != G_TYPE_NONE) {
                 priv->gboxed = g_boxed_copy(gtype,
                                             unthreadsafe_template_for_constructor.gboxed);
             } else if (priv->can_allocate_directly) {
-                if (!boxed_new_direct(context, obj, priv))
+                if (!boxed_new_direct(context, object, priv))
                     return JS_FALSE;
 
                 memcpy(priv->gboxed,
@@ -539,10 +536,15 @@ boxed_constructor(JSContext *context,
 
             unthreadsafe_template_for_constructor.gboxed = NULL;
 
-            return priv->gboxed != NULL;
+            retval = priv->gboxed != NULL;
+            if (retval)
+                GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
+            return retval;
         }
     }
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
+
     return JS_TRUE;
 }
 
@@ -1159,7 +1161,7 @@ gjs_define_boxed_class(JSContext    *context,
                                            * none - just name the prototype like
                                            * Math - rarely correct)
                                            */
-                                          boxed_constructor,
+                                          gjs_boxed_constructor,
                                           /* number of constructor args (less can be passed) */
                                           1,
                                           /* props of prototype */
diff --git a/gi/function.c b/gi/function.c
index 4a4d247..0404bdf 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -755,32 +755,49 @@ release:
     }
 }
 
-/* this macro was introduced with JSFastNative in 2007 */
-#ifndef JS_ARGV_CALLEE
-#define JS_ARGV_CALLEE(argv)    ((argv)[-2])
-#endif
-
+#ifdef JSFUN_CONSTRUCTOR
+static JSBool
+function_call(JSContext *context,
+              uintN      js_argc,
+              jsval     *vp)
+{
+    jsval *js_argv = JS_ARGV(context, vp);
+    JSObject *object = JS_THIS_OBJECT(context, vp);
+    JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(context, vp));
+    jsval retval;
+#else
 static JSBool
 function_call(JSContext *context,
-              JSObject  *obj, /* "this" object, not the function object */
+              JSObject  *object, /* "this" object, not the function object */
               uintN      js_argc,
               jsval     *js_argv,
-              jsval     *rval)
+              jsval     *retval)
 {
+    JSObject *callee = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(js_argv));
+#endif
+    JSBool success;
     Function *priv;
-    JSObject *callee;
-
-    callee = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(js_argv)); /* Callee is the Function object being called */
 
     priv = priv_from_js(context, callee);
     gjs_debug_marshal(GJS_DEBUG_GFUNCTION, "Call callee %p priv %p this obj %p %s", callee, priv,
                       obj, JS_GetTypeName(context,
-                                          JS_TypeOfValue(context, OBJECT_TO_JSVAL(obj))));
+                                          JS_TypeOfValue(context, OBJECT_TO_JSVAL(object))));
 
     if (priv == NULL)
         return JS_TRUE; /* we are the prototype, or have the wrong class */
 
-    return gjs_invoke_c_function(context, priv, obj, js_argc, js_argv, rval);
+
+#ifdef JSFUN_CONSTRUCTOR
+    {
+        jsval retval;
+        success = gjs_invoke_c_function(context, priv, object, js_argc, js_argv, &retval);
+        if (success)
+            JS_SET_RVAL(context, vp, retval);
+    }
+#else
+    success = gjs_invoke_c_function(context, priv, object, js_argc, js_argv, retval);
+#endif
+    return success;
 }
 
 /* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
@@ -791,24 +808,42 @@ function_call(JSContext *context,
  * identify the prototype as an object of our class with NULL private
  * data.
  */
+#ifdef JSFUN_CONSTRUCTOR
 static JSBool
 function_constructor(JSContext *context,
-                     JSObject  *obj,
+                     uintN      argc,
+                     jsval     *vp)
+{
+    JSObject *object;
+    if (!JS_IsConstructing_PossiblyWithGivenThisObject(context, vp, &object)) {
+        gjs_throw_constructor_error(context);
+        return JS_FALSE;
+    }
+    if (object == NULL)
+        object = JS_NewObjectForConstructor(context, vp);
+#else
+static JSBool
+function_constructor(JSContext *context,
+                     JSObject  *object,
                      uintN      argc,
                      jsval     *argv,
                      jsval     *retval)
 {
+#endif
     Function *priv;
 
     priv = g_slice_new0(Function);
 
     GJS_INC_COUNTER(function);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GFUNCTION,
-                        "function constructor, obj %p priv %p", obj, priv);
+                        "function constructor, obj %p priv %p", object, priv);
+#ifdef JSFUN_CONSTRUCTOR
+    JS_SET_RVAL(context, vp, OBJECT_TO_JSVAL(object));
+#endif
 
     return JS_TRUE;
 }
diff --git a/gi/keep-alive.c b/gi/keep-alive.c
index b20a5f6..87fb2f0 100644
--- a/gi/keep-alive.c
+++ b/gi/keep-alive.c
@@ -88,23 +88,23 @@ child_free(void *data)
  * identify the prototype as an object of our class with NULL private
  * data.
  */
-static JSBool
-keep_alive_constructor(JSContext *context,
-                       JSObject  *obj,
-                       uintN      argc,
-                       jsval     *argv,
-                       jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(keep_alive)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(keep_alive)
     KeepAlive *priv;
 
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(keep_alive);
+
     priv = g_slice_new0(KeepAlive);
     priv->children = g_hash_table_new_full(child_hash, child_equal, NULL, child_free);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_KEEP_ALIVE,
-                        "keep_alive constructor, obj %p priv %p", obj, priv);
+                        "keep_alive constructor, obj %p priv %p", object, priv);
+
+    GJS_NATIVE_CONSTRUCTOR_FINISH(keep_alive);
 
     return JS_TRUE;
 }
@@ -248,7 +248,7 @@ gjs_keep_alive_new(JSContext *context)
                                   * none - just name the prototype like
                                   * Math - rarely correct)
                                   */
-                                 keep_alive_constructor,
+                                 gjs_keep_alive_constructor,
                                  /* number of constructor args */
                                  0,
                                  /* props of prototype */
diff --git a/gi/ns.c b/gi/ns.c
index 1fe1720..0eb474a 100644
--- a/gi/ns.c
+++ b/gi/ns.c
@@ -147,23 +147,23 @@ ns_new_resolve(JSContext *context,
  * identify the prototype as an object of our class with NULL private
  * data.
  */
-static JSBool
-ns_constructor(JSContext *context,
-               JSObject  *obj,
-               uintN      argc,
-               jsval     *argv,
-               jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(ns)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(ns)
     Ns *priv;
 
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(ns);
+
     priv = g_slice_new0(Ns);
 
     GJS_INC_COUNTER(ns);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
+
+    gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE, "ns constructor, obj %p priv %p", object, priv);
 
-    gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE, "ns constructor, obj %p priv %p", obj, priv);
+    GJS_NATIVE_CONSTRUCTOR_FINISH(ns);
 
     return JS_TRUE;
 }
@@ -247,7 +247,7 @@ ns_new(JSContext    *context,
                                   * none - just name the prototype like
                                   * Math - rarely correct)
                                   */
-                                 ns_constructor,
+                                 gjs_ns_constructor,
                                  /* number of constructor args */
                                  0,
                                  /* props of prototype */
diff --git a/gi/object.c b/gi/object.c
index 3bbf0b6..a2284fd 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -615,13 +615,9 @@ wrapped_gobj_toggle_notify(gpointer      data,
  * also, but can be replaced with another object to use instead as the
  * prototype.
  */
-static JSBool
-object_instance_constructor(JSContext *context,
-                            JSObject  *obj,
-                            uintN      argc,
-                            jsval     *argv,
-                            jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(object_instance)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(object_instance)
     ObjectInstance *priv;
     ObjectInstance *proto_priv;
     JSObject *proto;
@@ -629,29 +625,26 @@ object_instance_constructor(JSContext *context,
     JSClass *obj_class;
     JSClass *proto_class;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(object_instance);
 
     priv = g_slice_new0(ObjectInstance);
 
     GJS_INC_COUNTER(object);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GOBJECT,
-                        "obj instance constructor, obj %p priv %p retval %p", obj, priv,
-                        JSVAL_IS_OBJECT(*retval) ?
-                        JSVAL_TO_OBJECT(*retval) : NULL);
+                        "obj instance constructor, obj %p priv %p", object, priv);
 
-    proto = JS_GetPrototype(context, obj);
+    proto = JS_GetPrototype(context, object);
     gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "obj instance __proto__ is %p", proto);
 
     /* If we're constructing the prototype, its __proto__ is not the same
      * class as us, but if we're constructing an instance, the prototype
      * has the same class.
      */
-    obj_class = JS_GET_CLASS(context, obj);
+    obj_class = JS_GET_CLASS(context, object);
     proto_class = JS_GET_CLASS(context, proto);
 
     is_proto = (obj_class != proto_class);
@@ -700,7 +693,7 @@ object_instance_constructor(JSContext *context,
                 return JS_FALSE;
             }
 
-            if (!object_instance_props_to_g_parameters(context, obj, argc, argv,
+            if (!object_instance_props_to_g_parameters(context, object, argc, argv,
                                                        gtype,
                                                        &params, &n_params)) {
                 return JS_FALSE;
@@ -731,10 +724,10 @@ object_instance_constructor(JSContext *context,
         }
 
         g_assert(peek_js_obj(context, priv->gobj) == NULL);
-        set_js_obj(context, priv->gobj, obj);
+        set_js_obj(context, priv->gobj, object);
 
 #if DEBUG_DISPOSE
-        g_object_weak_ref(priv->gobj, wrapped_gobj_dispose_notify, obj);
+        g_object_weak_ref(priv->gobj, wrapped_gobj_dispose_notify, object);
 #endif
 
         /* OK, here is where things get complicated. We want the
@@ -752,7 +745,7 @@ object_instance_constructor(JSContext *context,
         gjs_keep_alive_add_child(context,
                                  priv->keep_alive,
                                  gobj_no_longer_kept_alive_func,
-                                 obj,
+                                 object,
                                  priv);
 
         g_object_add_toggle_ref(priv->gobj,
@@ -773,6 +766,8 @@ object_instance_constructor(JSContext *context,
                                     g_base_info_get_name ( (GIBaseInfo*) priv->info) ));
     }
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(object_instance);
+
     return JS_TRUE;
 }
 
@@ -1375,7 +1370,7 @@ gjs_define_object_class(JSContext     *context,
                                         * none - just name the prototype like
                                         * Math - rarely correct)
                                         */
-                                       object_instance_constructor,
+                                       gjs_object_instance_constructor,
                                        /* number of constructor args */
                                        0,
                                        /* props of prototype */
diff --git a/gi/param.c b/gi/param.c
index ae41367..5c4c669 100644
--- a/gi/param.c
+++ b/gi/param.c
@@ -142,13 +142,9 @@ param_new_resolve(JSContext *context,
  * identify the prototype as an object of our class with NULL private
  * data.
  */
-static JSBool
-param_constructor(JSContext *context,
-                  JSObject  *obj,
-                  uintN      argc,
-                  jsval     *argv,
-                  jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(param)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(param)
     Param *priv;
     Param *proto_priv;
     JSClass *obj_class;
@@ -156,27 +152,26 @@ param_constructor(JSContext *context,
     JSObject *proto;
     gboolean is_proto;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(param);
 
     priv = g_slice_new0(Param);
 
     GJS_INC_COUNTER(param);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GPARAM,
-                        "param constructor, obj %p priv %p", obj, priv);
+                        "param constructor, obj %p priv %p", object, priv);
 
-    proto = JS_GetPrototype(context, obj);
+    proto = JS_GetPrototype(context, object);
     gjs_debug_lifecycle(GJS_DEBUG_GPARAM, "param instance __proto__ is %p", proto);
 
     /* If we're constructing the prototype, its __proto__ is not the same
      * class as us, but if we're constructing an instance, the prototype
      * has the same class.
      */
-    obj_class = JS_GET_CLASS(context, obj);
+    obj_class = JS_GET_CLASS(context, object);
     proto_class = JS_GET_CLASS(context, proto);
 
     is_proto = (obj_class != proto_class);
@@ -214,6 +209,8 @@ param_constructor(JSContext *context,
                   priv->gparam, g_type_name(G_TYPE_FROM_INSTANCE((GTypeInstance*) priv->gparam)));
     }
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(param);
+
     return JS_TRUE;
 }
 
@@ -345,7 +342,7 @@ gjs_define_param_class(JSContext    *context,
                                            * none - just name the prototype like
                                            * Math - rarely correct)
                                            */
-                                          param_constructor,
+                                          gjs_param_constructor,
                                           /* number of constructor args */
                                           0,
                                           /* props of prototype */
diff --git a/gi/repo.c b/gi/repo.c
index 9ce76bc..7d3bbbc 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -161,24 +161,24 @@ repo_new_resolve(JSContext *context,
  * identify the prototype as an object of our class with NULL private
  * data.
  */
-static JSBool
-repo_constructor(JSContext *context,
-                 JSObject  *obj,
-                 uintN      argc,
-                 jsval     *argv,
-                 jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(repo)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(repo)
     Repo *priv;
 
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(repo);
+
     priv = g_slice_new0(Repo);
 
     GJS_INC_COUNTER(repo);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GREPO,
-                        "repo constructor, obj %p priv %p", obj, priv);
+                        "repo constructor, obj %p priv %p", object, priv);
+
+    GJS_NATIVE_CONSTRUCTOR_FINISH(repo);
 
     return JS_TRUE;
 }
@@ -254,7 +254,7 @@ repo_new(JSContext *context)
                                   * none - just name the prototype like
                                   * Math - rarely correct)
                                   */
-                                 repo_constructor,
+                                 gjs_repo_constructor,
                                  /* number of constructor args */
                                  0,
                                  /* props of prototype */
diff --git a/gi/union.c b/gi/union.c
index 13442ba..118cc88 100644
--- a/gi/union.c
+++ b/gi/union.c
@@ -201,13 +201,9 @@ union_new(JSContext   *context,
  * identify the prototype as an object of our class with NULL private
  * data.
  */
-static JSBool
-union_constructor(JSContext *context,
-                  JSObject  *obj,
-                  uintN      argc,
-                  jsval     *argv,
-                  jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(union)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(union)
     Union *priv;
     Union *proto_priv;
     JSClass *obj_class;
@@ -215,28 +211,27 @@ union_constructor(JSContext *context,
     JSObject *proto;
     gboolean is_proto;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(union);
 
     priv = g_slice_new0(Union);
 
     GJS_INC_COUNTER(boxed);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
                         "union constructor, obj %p priv %p",
-                        obj, priv);
+                        object, priv);
 
-    proto = JS_GetPrototype(context, obj);
+    proto = JS_GetPrototype(context, object);
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED, "union instance __proto__ is %p", proto);
 
     /* If we're constructing the prototype, its __proto__ is not the same
      * class as us, but if we're constructing an instance, the prototype
      * has the same class.
      */
-    obj_class = JS_GET_CLASS(context, obj);
+    obj_class = JS_GET_CLASS(context, object);
     proto_class = JS_GET_CLASS(context, proto);
 
     is_proto = (obj_class != proto_class);
@@ -283,7 +278,7 @@ union_constructor(JSContext *context,
              * The returned "gboxed" here is owned by that jsval,
              * not by us.
              */
-            gboxed = union_new(context, obj, priv->info);
+            gboxed = union_new(context, object, priv->info);
 
             if (gboxed == NULL) {
                 return JS_FALSE;
@@ -304,6 +299,8 @@ union_constructor(JSContext *context,
                             priv->gboxed, g_type_name(gtype));
     }
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(union);
+
     return JS_TRUE;
 }
 
@@ -488,7 +485,7 @@ gjs_define_union_class(JSContext    *context,
                                         * none - just name the prototype like
                                         * Math - rarely correct)
                                         */
-                                       union_constructor,
+                                       gjs_union_constructor,
                                        /* number of constructor args */
                                        0,
                                        /* props of prototype */
diff --git a/gjs/byteArray.c b/gjs/byteArray.c
index 107e94f..e4b47af 100644
--- a/gjs/byteArray.c
+++ b/gjs/byteArray.c
@@ -51,11 +51,7 @@ static JSBool byte_array_new_resolve   (JSContext    *context,
                                         jsid          id,
                                         uintN         flags,
                                         JSObject    **objp);
-static JSBool byte_array_constructor   (JSContext    *context,
-                                        JSObject     *obj,
-                                        uintN         argc,
-                                        jsval        *argv,
-                                        jsval        *retval);
+GJS_NATIVE_CONSTRUCTOR_DECLARE(byte_array);
 static void   byte_array_finalize      (JSContext    *context,
                                         JSObject     *obj);
 
@@ -432,13 +428,9 @@ gjs_g_byte_array_new(int preallocated_length)
  * also, but can be replaced with another object to use instead as the
  * prototype.
  */
-static JSBool
-byte_array_constructor(JSContext *context,
-                       JSObject  *obj,
-                       uintN      argc,
-                       jsval     *argv,
-                       jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(byte_array)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(byte_array)
     ByteArrayInstance *priv;
     JSObject *proto;
     gboolean is_proto;
@@ -446,8 +438,7 @@ byte_array_constructor(JSContext *context,
     JSClass *proto_class;
     gsize preallocated_length;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(byte_array);
 
     preallocated_length = 0;
     if (argc >= 1) {
@@ -460,17 +451,17 @@ byte_array_constructor(JSContext *context,
 
     priv = g_slice_new0(ByteArrayInstance);
 
-    g_assert(priv_from_js(context, obj) == NULL);
+    g_assert(priv_from_js(context, object) == NULL);
 
-    JS_SetPrivate(context, obj, priv);
+    JS_SetPrivate(context, object, priv);
 
-    proto = JS_GetPrototype(context, obj);
+    proto = JS_GetPrototype(context, object);
 
     /* If we're constructing the prototype, its __proto__ is not the same
      * class as us, but if we're constructing an instance, the prototype
      * has the same class.
      */
-    obj_class = JS_GetClass(context, obj);
+    obj_class = JS_GetClass(context, object);
     proto_class = JS_GetClass(context, proto);
 
     is_proto = (obj_class != proto_class);
@@ -479,6 +470,8 @@ byte_array_constructor(JSContext *context,
         priv->array = gjs_g_byte_array_new(preallocated_length);
     }
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(byte_array);
+
     return JS_TRUE;
 }
 
@@ -862,7 +855,7 @@ gjs_define_byte_array_stuff(JSContext      *context,
     gjs_byte_array_prototype = JS_InitClass(context, global,
                              NULL,
                              &gjs_byte_array_class,
-                             byte_array_constructor,
+                             gjs_byte_array_constructor,
                              0,
                              &gjs_byte_array_proto_props[0],
                              &gjs_byte_array_proto_funcs[0],
diff --git a/gjs/compat.h b/gjs/compat.h
index 03daf6c..d418a22 100644
--- a/gjs/compat.h
+++ b/gjs/compat.h
@@ -30,6 +30,7 @@
 #define __GJS_COMPAT_H__
 
 #include <jsapi.h>
+#include <glib.h>
 
 G_BEGIN_DECLS
 
@@ -68,6 +69,70 @@ G_BEGIN_DECLS
 #ifdef JSFUN_CONSTRUCTOR
 /* All functions are "fast", so define this to a no-op */
 #define JSFUN_FAST_NATIVE 0
+
+/**
+ * GJS_NATIVE_CONSTRUCTOR_DECLARE:
+ * Prototype a constructor.
+ */
+#define GJS_NATIVE_CONSTRUCTOR_DECLARE(name)            \
+static JSBool                                           \
+gjs_##name##_constructor(JSContext  *context,           \
+                         uintN       argc,              \
+                         jsval      *vp)
+
+/**
+ * GJS_NATIVE_CONSTRUCTOR_VARIABLES:
+ * Declare variables necessary for the constructor; should
+ * be at the very top.
+ */
+#define GJS_NATIVE_CONSTRUCTOR_VARIABLES(name)          \
+    JSObject *object = NULL;                            \
+    jsval *argv = JS_ARGV(context, vp);
+
+/**
+ * GJS_NATIVE_CONSTRUCTOR_PRELUDE:
+ * Call after the initial variable declaration.
+ */
+#define GJS_NATIVE_CONSTRUCTOR_PRELUDE(name)                                         \
+    {                                                                                \
+        if (!JS_IsConstructing_PossiblyWithGivenThisObject(context, vp, &object)) {  \
+            gjs_throw_constructor_error(context);                                    \
+            return JS_FALSE;                                                         \
+        }                                                                            \
+        if (object == NULL)                                                          \
+            object = JS_NewObjectForConstructor(context, vp);                        \
+        if (object == NULL)                                                          \
+            return JS_FALSE;                                                         \
+    }
+
+
+/**
+ * GJS_NATIVE_CONSTRUCTOR_FINISH:
+ * Call this at the end of a constructor when it's completed
+ * successfully.
+ */
+#define GJS_NATIVE_CONSTRUCTOR_FINISH(name)             \
+    JS_SET_RVAL(context, vp, OBJECT_TO_JSVAL(object));
+#else
+
+#define GJS_NATIVE_CONSTRUCTOR_DECLARE(name)            \
+static JSBool                                           \
+gjs_##name##_constructor(JSContext *context,            \
+                         JSObject  *object,             \
+                         uintN      argc,               \
+                         jsval     *argv,               \
+                         jsval     *retval)
+
+#define GJS_NATIVE_CONSTRUCTOR_VARIABLES(name)
+
+#define GJS_NATIVE_CONSTRUCTOR_PRELUDE(name)            \
+    if (!JS_IsConstructing(context)) {                  \
+        gjs_throw_constructor_error(context);           \
+        return JS_FALSE;                                \
+    }
+
+#define GJS_NATIVE_CONSTRUCTOR_FINISH(name)
+
 #endif
 
 G_END_DECLS
diff --git a/gjs/importer.c b/gjs/importer.c
index b5c8fb6..9986b9b 100644
--- a/gjs/importer.c
+++ b/gjs/importer.c
@@ -956,24 +956,24 @@ importer_new_resolve(JSContext *context,
  * identify the prototype as an object of our class with NULL private
  * data.
  */
-static JSBool
-importer_constructor(JSContext *context,
-                     JSObject  *obj,
-                     uintN      argc,
-                     jsval     *argv,
-                     jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(importer)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(importer)
     Importer *priv;
 
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(importer);
+
     priv = g_slice_new0(Importer);
 
     GJS_INC_COUNTER(importer);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_IMPORTER,
-                        "importer constructor, obj %p priv %p", obj, priv);
+                        "importer constructor, obj %p priv %p", object, priv);
+
+    GJS_NATIVE_CONSTRUCTOR_FINISH(importer);
 
     return JS_TRUE;
 }
@@ -1050,7 +1050,7 @@ importer_new(JSContext    *context)
                                   * none - just name the prototype like
                                   * Math - rarely correct)
                                   */
-                                 importer_constructor,
+                                 gjs_importer_constructor,
                                  /* number of constructor args */
                                  0,
                                  /* props of prototype */
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index bf7cc6f..4695ec0 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -566,19 +566,11 @@ gjs_init_class_dynamic(JSContext      *context,
     return NULL;
 }
 
-gboolean
-gjs_check_constructing(JSContext *context)
+void
+gjs_throw_constructor_error(JSContext *context)
 {
-    JS_BeginRequest(context);
-    if (!JS_IsConstructing(context)) {
-        JS_EndRequest(context);
-        gjs_throw(context,
-                  "Constructor called as normal method. Use 'new SomeObject()' not 'SomeObject()'");
-        return FALSE;
-    }
-
-    JS_EndRequest(context);
-    return TRUE;
+    gjs_throw(context,
+              "Constructor called as normal method. Use 'new SomeObject()' not 'SomeObject()'");
 }
 
 void*
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 9cd507a..cdaa6d5 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -29,6 +29,7 @@
 #endif
 
 #include <jsapi.h>
+#include <gjs/compat.h>
 #include <glib-object.h>
 
 G_BEGIN_DECLS
@@ -112,12 +113,8 @@ typedef struct GjsRootedArray GjsRootedArray;
  * A convenience macro for prototype implementations.
  */
 #define GJS_DEFINE_PROTO(tn, cn) \
-static JSBool cn##_constructor(JSContext *context, \
-                               JSObject  *obj, \
-                               uintN      argc, \
-                               jsval     *argv, \
-                               jsval     *retval); \
-_GJS_DEFINE_PROTO_FULL(tn, cn, cn##_constructor)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cn); \
+_GJS_DEFINE_PROTO_FULL(tn, cn, gjs_##cn##_constructor)
 
 /**
  * GJS_DEFINE_PROTO_ABSTRACT:
@@ -132,18 +129,18 @@ _GJS_DEFINE_PROTO_FULL(tn, cn, cn##_constructor)
 _GJS_DEFINE_PROTO_FULL(tn, cn, NULL)
 
 #define _GJS_DEFINE_PROTO_FULL(type_name, cname, ctor) \
-static JSPropertySpec cname##_proto_props[]; \
-static JSFunctionSpec cname##_proto_funcs[]; \
-static void cname##_finalize(JSContext *context, JSObject *obj); \
-static JSBool cname##_new_resolve(JSContext *context, \
-                                  JSObject  *obj, \
-                                  jsval      id, \
-                                  uintN      flags, \
-                                  JSObject **objp) \
+static JSPropertySpec gjs_##cname##_proto_props[]; \
+static JSFunctionSpec gjs_##cname##_proto_funcs[]; \
+static void gjs_##cname##_finalize(JSContext *context, JSObject *obj); \
+static JSBool gjs_##cname##_new_resolve(JSContext *context, \
+                                        JSObject  *obj, \
+                                        jsval      id, \
+                                        uintN      flags, \
+                                        JSObject **objp) \
 { \
     return JS_TRUE; \
 } \
-static struct JSClass cname##_class = { \
+static struct JSClass gjs_##cname##_class = { \
     type_name, \
     JSCLASS_HAS_PRIVATE | \
     JSCLASS_NEW_RESOLVE | \
@@ -153,27 +150,27 @@ static struct JSClass cname##_class = { \
     JS_PropertyStub, \
     JS_PropertyStub,\
     JS_EnumerateStub,\
-    (JSResolveOp) cname##_new_resolve, \
+    (JSResolveOp) gjs_##cname##_new_resolve, \
     JS_ConvertStub, \
-    cname##_finalize, \
+    gjs_##cname##_finalize, \
     NULL, \
     NULL, \
     NULL, \
     NULL, NULL, NULL, NULL, NULL \
 }; \
-jsval cname##_create_proto(JSContext *context, JSObject *module, const char *proto_name, JSObject *parent) \
+jsval gjs_##cname##_create_proto(JSContext *context, JSObject *module, const char *proto_name, JSObject *parent) \
 { \
     jsval rval; \
     JSObject *global = gjs_get_import_global(context); \
     if (!gjs_object_has_property(context, global, \
-                                 cname##_class.name)) { \
+                                 gjs_##cname##_class.name)) { \
         JSObject *prototype = JS_InitClass(context, global, \
                                  parent, \
-                                 &cname##_class, \
+                                 &gjs_##cname##_class, \
                                  ctor, \
                                  0, \
-                                 &cname##_proto_props[0], \
-                                 &cname##_proto_funcs[0], \
+                                 &gjs_##cname##_proto_props[0], \
+                                 &gjs_##cname##_proto_funcs[0], \
                                  NULL, \
                                  NULL); \
         if (prototype == NULL) { \
@@ -181,7 +178,7 @@ jsval cname##_create_proto(JSContext *context, JSObject *module, const char *pro
         } \
         if (!gjs_object_require_property( \
                 context, global, NULL, \
-                cname##_class.name, &rval)) { \
+                gjs_##cname##_class.name, &rval)) { \
             return JSVAL_NULL; \
         } \
     } \
@@ -228,7 +225,7 @@ JSObject *  gjs_init_class_dynamic           (JSContext       *context,
                                               JSFunctionSpec  *fs,
                                               JSPropertySpec  *static_ps,
                                               JSFunctionSpec  *static_fs);
-gboolean    gjs_check_constructing           (JSContext       *context);
+void gjs_throw_constructor_error             (JSContext       *context);
 
 void* gjs_get_instance_private_dynamic                (JSContext  *context,
                                                        JSObject   *obj,
diff --git a/modules/cairo-context.c b/modules/cairo-context.c
index 175777e..bc104ac 100644
--- a/modules/cairo-context.c
+++ b/modules/cairo-context.c
@@ -231,7 +231,7 @@ typedef struct {
     cairo_t * cr;
 } GjsCairoContext;
 
-GJS_DEFINE_PROTO("CairoContext", gjs_cairo_context)
+GJS_DEFINE_PROTO("CairoContext", cairo_context)
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoContext, gjs_cairo_context_class);
 
 static void
@@ -251,19 +251,14 @@ _gjs_cairo_context_construct_internal(JSContext *context,
     priv->cr = cairo_reference(cr);
 }
 
-static JSBool
-gjs_cairo_context_constructor(JSContext *context,
-                              JSObject  *obj,
-                              uintN      argc,
-                              jsval     *argv,
-                              jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_context)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_context)
     JSObject *surface_wrapper;
     cairo_surface_t *surface;
     cairo_t *cr;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_context);
 
     if (!gjs_parse_args(context, "Context", "o", argc, argv,
                         "surface", &surface_wrapper))
@@ -280,9 +275,11 @@ gjs_cairo_context_constructor(JSContext *context,
     if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
         return JS_FALSE;
 
-    _gjs_cairo_context_construct_internal(context, obj, cr);
+    _gjs_cairo_context_construct_internal(context, object, cr);
     cairo_destroy(cr);
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_context);
+
     return JS_TRUE;
 }
 
diff --git a/modules/cairo-gradient.c b/modules/cairo-gradient.c
index 36148dc..fead174 100644
--- a/modules/cairo-gradient.c
+++ b/modules/cairo-gradient.c
@@ -27,7 +27,7 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO_ABSTRACT("CairoGradient", gjs_cairo_gradient)
+GJS_DEFINE_PROTO_ABSTRACT("CairoGradient", cairo_gradient)
 
 static void
 gjs_cairo_gradient_finalize(JSContext *context,
diff --git a/modules/cairo-image-surface.c b/modules/cairo-image-surface.c
index d65b9f5..c2e587f 100644
--- a/modules/cairo-image-surface.c
+++ b/modules/cairo-image-surface.c
@@ -27,20 +27,15 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO("CairoImageSurface", gjs_cairo_image_surface)
+GJS_DEFINE_PROTO("CairoImageSurface", cairo_image_surface)
 
-static JSBool
-gjs_cairo_image_surface_constructor(JSContext *context,
-                                    JSObject  *obj,
-                                    uintN      argc,
-                                    jsval     *argv,
-                                    jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_image_surface)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_image_surface)
     int format, width, height;
     cairo_surface_t *surface;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_image_surface);
 
     // create_for_data optional parameter
     if (!gjs_parse_args(context, "ImageSurface", "iii", argc, argv,
@@ -54,9 +49,11 @@ gjs_cairo_image_surface_constructor(JSContext *context,
     if (!gjs_cairo_check_status(context, cairo_surface_status(surface), "surface"))
         return JS_FALSE;
 
-    gjs_cairo_surface_construct(context, obj, surface);
+    gjs_cairo_surface_construct(context, object, surface);
     cairo_surface_destroy(surface);
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_image_surface);
+
     return JS_TRUE;
 }
 
diff --git a/modules/cairo-linear-gradient.c b/modules/cairo-linear-gradient.c
index 5b7b4ee..74efc90 100644
--- a/modules/cairo-linear-gradient.c
+++ b/modules/cairo-linear-gradient.c
@@ -27,20 +27,15 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO("CairoLinearGradient", gjs_cairo_linear_gradient)
-
-static JSBool
-gjs_cairo_linear_gradient_constructor(JSContext *context,
-                                      JSObject  *obj,
-                                      uintN      argc,
-                                      jsval     *argv,
-                                      jsval     *retval)
+GJS_DEFINE_PROTO("CairoLinearGradient", cairo_linear_gradient)
+
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_linear_gradient)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_linear_gradient)
     double x0, y0, x1, y1;
     cairo_pattern_t *pattern;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_linear_gradient);
 
     if (!gjs_parse_args(context, "LinearGradient", "ffff", argc, argv,
                         "x0", &x0,
@@ -54,9 +49,11 @@ gjs_cairo_linear_gradient_constructor(JSContext *context,
     if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
         return JS_FALSE;
 
-    gjs_cairo_pattern_construct(context, obj, pattern);
+    gjs_cairo_pattern_construct(context, object, pattern);
     cairo_pattern_destroy(pattern);
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_linear_gradient);
+
     return JS_TRUE;
 }
 
diff --git a/modules/cairo-path.c b/modules/cairo-path.c
index b08f518..86a50dc 100644
--- a/modules/cairo-path.c
+++ b/modules/cairo-path.c
@@ -33,7 +33,7 @@ typedef struct {
     cairo_path_t    *path;
 } GjsCairoPath;
 
-GJS_DEFINE_PROTO_ABSTRACT("CairoPath", gjs_cairo_path)
+GJS_DEFINE_PROTO_ABSTRACT("CairoPath", cairo_path)
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoPath, gjs_cairo_path_class)
 
 static void
diff --git a/modules/cairo-pattern.c b/modules/cairo-pattern.c
index 730eccc..d1b9730 100644
--- a/modules/cairo-pattern.c
+++ b/modules/cairo-pattern.c
@@ -34,8 +34,7 @@ typedef struct {
     cairo_pattern_t *pattern;
 } GjsCairoPattern;
 
-GJS_DEFINE_PROTO_ABSTRACT("CairoPattern", gjs_cairo_pattern)
-
+GJS_DEFINE_PROTO_ABSTRACT("CairoPattern", cairo_pattern)
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoPattern, gjs_cairo_pattern_class)
 
 static void
diff --git a/modules/cairo-pdf-surface.c b/modules/cairo-pdf-surface.c
index fc54b7c..6aca613 100644
--- a/modules/cairo-pdf-surface.c
+++ b/modules/cairo-pdf-surface.c
@@ -30,21 +30,16 @@
 #if CAIRO_HAS_PDF_SURFACE
 #include <cairo-pdf.h>
 
-GJS_DEFINE_PROTO("CairoPDFSurface", gjs_cairo_pdf_surface)
-
-static JSBool
-gjs_cairo_pdf_surface_constructor(JSContext *context,
-                                  JSObject  *obj,
-                                  uintN      argc,
-                                  jsval     *argv,
-                                  jsval     *retval)
+GJS_DEFINE_PROTO("CairoPDFSurface", cairo_pdf_surface)
+
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_pdf_surface)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_pdf_surface)
     char *filename;
     double width, height;
     cairo_surface_t *surface;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_pdf_surface);
 
     if (!gjs_parse_args(context, "PDFSurface", "sff", argc, argv,
                         "filename", &filename,
@@ -60,10 +55,12 @@ gjs_cairo_pdf_surface_constructor(JSContext *context,
         return JS_FALSE;
     }
 
-    gjs_cairo_surface_construct(context, obj, surface);
+    gjs_cairo_surface_construct(context, object, surface);
     cairo_surface_destroy(surface);
     g_free(filename);
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_pdf_surface);
+
     return JS_TRUE;
 }
 
diff --git a/modules/cairo-ps-surface.c b/modules/cairo-ps-surface.c
index 70b389c..ca0fad4 100644
--- a/modules/cairo-ps-surface.c
+++ b/modules/cairo-ps-surface.c
@@ -30,21 +30,16 @@
 #if CAIRO_HAS_PS_SURFACE
 #include <cairo-ps.h>
 
-GJS_DEFINE_PROTO("CairoPSSurface", gjs_cairo_ps_surface)
-
-static JSBool
-gjs_cairo_ps_surface_constructor(JSContext *context,
-                                 JSObject  *obj,
-                                 uintN      argc,
-                                 jsval     *argv,
-                                 jsval     *retval)
+GJS_DEFINE_PROTO("CairoPSSurface", cairo_ps_surface)
+
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_ps_surface)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_ps_surface)
     char *filename;
     double width, height;
     cairo_surface_t *surface;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_ps_surface);
 
     if (!gjs_parse_args(context, "PSSurface", "sff", argc, argv,
                         "filename", &filename,
@@ -60,10 +55,12 @@ gjs_cairo_ps_surface_constructor(JSContext *context,
         return JS_FALSE;
     }
 
-    gjs_cairo_surface_construct(context, obj, surface);
+    gjs_cairo_surface_construct(context, object, surface);
     cairo_surface_destroy(surface);
     g_free(filename);
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_ps_surface);
+
     return JS_TRUE;
 }
 
diff --git a/modules/cairo-radial-gradient.c b/modules/cairo-radial-gradient.c
index d20973d..48f8b0b 100644
--- a/modules/cairo-radial-gradient.c
+++ b/modules/cairo-radial-gradient.c
@@ -27,20 +27,15 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO("CairoRadialGradient", gjs_cairo_radial_gradient)
-
-static JSBool
-gjs_cairo_radial_gradient_constructor(JSContext *context,
-                                      JSObject  *obj,
-                                      uintN      argc,
-                                      jsval     *argv,
-                                      jsval     *retval)
+GJS_DEFINE_PROTO("CairoRadialGradient", cairo_radial_gradient)
+
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_radial_gradient)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_radial_gradient)
     double cx0, cy0, radius0, cx1, cy1, radius1;
     cairo_pattern_t *pattern;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_radial_gradient);
 
     if (!gjs_parse_args(context, "RadialGradient", "ffffff", argc, argv,
                         "cx0", &cx0,
@@ -56,9 +51,11 @@ gjs_cairo_radial_gradient_constructor(JSContext *context,
     if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
         return JS_FALSE;
 
-    gjs_cairo_pattern_construct(context, obj, pattern);
+    gjs_cairo_pattern_construct(context, object, pattern);
     cairo_pattern_destroy(pattern);
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_radial_gradient);
+
     return JS_TRUE;
 }
 
diff --git a/modules/cairo-solid-pattern.c b/modules/cairo-solid-pattern.c
index 47c68cb..936a765 100644
--- a/modules/cairo-solid-pattern.c
+++ b/modules/cairo-solid-pattern.c
@@ -27,7 +27,7 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO_ABSTRACT("CairoSolidPattern", gjs_cairo_solid_pattern)
+GJS_DEFINE_PROTO_ABSTRACT("CairoSolidPattern", cairo_solid_pattern)
 
 static void
 gjs_cairo_solid_pattern_finalize(JSContext *context,
diff --git a/modules/cairo-surface-pattern.c b/modules/cairo-surface-pattern.c
index 11c6ee6..8791e32 100644
--- a/modules/cairo-surface-pattern.c
+++ b/modules/cairo-surface-pattern.c
@@ -27,21 +27,16 @@
 #include <cairo.h>
 #include "cairo-private.h"
 
-GJS_DEFINE_PROTO("CairoSurfacePattern", gjs_cairo_surface_pattern)
+GJS_DEFINE_PROTO("CairoSurfacePattern", cairo_surface_pattern)
 
-static JSBool
-gjs_cairo_surface_pattern_constructor(JSContext *context,
-                                      JSObject  *obj,
-                                      uintN      argc,
-                                      jsval     *argv,
-                                      jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_surface_pattern)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_surface_pattern)
     JSObject *surface_wrapper;
     cairo_surface_t *surface;
     cairo_pattern_t *pattern;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_surface_pattern);
 
     if (!gjs_parse_args(context, "SurfacePattern", "o", argc, argv,
                         "surface", &surface_wrapper))
@@ -58,9 +53,11 @@ gjs_cairo_surface_pattern_constructor(JSContext *context,
     if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern"))
         return JS_FALSE;
 
-    gjs_cairo_pattern_construct(context, obj, pattern);
+    gjs_cairo_pattern_construct(context, object, pattern);
     cairo_pattern_destroy(pattern);
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_surface_pattern);
+
     return JS_TRUE;
 }
 
diff --git a/modules/cairo-surface.c b/modules/cairo-surface.c
index f086af8..a511817 100644
--- a/modules/cairo-surface.c
+++ b/modules/cairo-surface.c
@@ -34,8 +34,7 @@ typedef struct {
     cairo_surface_t *surface;
 } GjsCairoSurface;
 
-GJS_DEFINE_PROTO_ABSTRACT("CairoSurface", gjs_cairo_surface)
-
+GJS_DEFINE_PROTO_ABSTRACT("CairoSurface", cairo_surface)
 GJS_DEFINE_PRIV_FROM_JS(GjsCairoSurface, gjs_cairo_surface_class)
 
 static void
diff --git a/modules/cairo-svg-surface.c b/modules/cairo-svg-surface.c
index 81fa67c..6acc26c 100644
--- a/modules/cairo-svg-surface.c
+++ b/modules/cairo-svg-surface.c
@@ -30,21 +30,16 @@
 #if CAIRO_HAS_SVG_SURFACE
 #include <cairo-svg.h>
 
-GJS_DEFINE_PROTO("CairoSVGSurface", gjs_cairo_svg_surface)
-
-static JSBool
-gjs_cairo_svg_surface_constructor(JSContext *context,
-                                  JSObject  *obj,
-                                  uintN      argc,
-                                  jsval     *argv,
-                                  jsval     *retval)
+GJS_DEFINE_PROTO("CairoSVGSurface", cairo_svg_surface)
+
+GJS_NATIVE_CONSTRUCTOR_DECLARE(cairo_svg_surface)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(cairo_svg_surface)
     char *filename;
     double width, height;
     cairo_surface_t *surface;
 
-    if (!gjs_check_constructing(context))
-        return JS_FALSE;
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(cairo_svg_surface);
 
     if (!gjs_parse_args(context, "SVGSurface", "sff", argc, argv,
                         "filename", &filename,
@@ -60,10 +55,12 @@ gjs_cairo_svg_surface_constructor(JSContext *context,
         return JS_FALSE;
     }
 
-    gjs_cairo_surface_construct(context, obj, surface);
+    gjs_cairo_surface_construct(context, object, surface);
     cairo_surface_destroy(surface);
     g_free(filename);
 
+    GJS_NATIVE_CONSTRUCTOR_FINISH(cairo_svg_surface);
+
     return JS_TRUE;
 }
 
diff --git a/modules/dbus-exports.c b/modules/dbus-exports.c
index 025fafc..bd86ac8 100644
--- a/modules/dbus-exports.c
+++ b/modules/dbus-exports.c
@@ -1685,27 +1685,27 @@ exports_new_resolve(JSContext *context,
  * identify the prototype as an object of our class with NULL private
  * data.
  */
-static JSBool
-exports_constructor(JSContext *context,
-                    JSObject  *obj,
-                    uintN      argc,
-                    jsval     *argv,
-                    jsval     *retval)
+GJS_NATIVE_CONSTRUCTOR_DECLARE(js_exports)
 {
+    GJS_NATIVE_CONSTRUCTOR_VARIABLES(js_exports)
     Exports *priv;
 
+    GJS_NATIVE_CONSTRUCTOR_PRELUDE(js_exports);
+
     priv = g_slice_new0(Exports);
 
     GJS_INC_COUNTER(dbus_exports);
 
-    g_assert(priv_from_js(context, obj) == NULL);
-    JS_SetPrivate(context, obj, priv);
+    g_assert(priv_from_js(context, object) == NULL);
+    JS_SetPrivate(context, object, priv);
 
     gjs_debug_lifecycle(GJS_DEBUG_DBUS,
-                        "exports constructor, obj %p priv %p", obj, priv);
+                        "exports constructor, obj %p priv %p", object, priv);
 
     priv->runtime = JS_GetRuntime(context);
-    priv->object = obj;
+    priv->object = object;
+
+    GJS_NATIVE_CONSTRUCTOR_FINISH(js_exports);
 
     return JS_TRUE;
 }
@@ -1825,7 +1825,7 @@ exports_new(JSContext  *context,
                                   * none - just name the prototype like
                                   * Math - rarely correct)
                                   */
-                                 exports_constructor,
+                                 gjs_js_exports_constructor,
                                  /* number of constructor args */
                                  0,
                                  /* props of prototype */



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