[gjs/wip/ptomato/mozjs31prep: 5/7] js: Root gjs_object_get_property_const()



commit 5826de6ba314541033eca5e7e7fd654b4876fe36
Author: Philip Chimento <philip endlessm com>
Date:   Tue Oct 18 15:54:07 2016 -0700

    js: Root gjs_object_get_property_const()
    
    Starting with gjs_object_get_property_const() and working backwards, we
    cause another cascade of GC rooting changes.
    
    One disadvantage of JS::MutableHandle is that it's not so easy to make an
    optional out parameter for a function. Previously, for example, a
    JSObject** parameter could be NULL to indicate the caller wasn't
    interested in the return value. e.g.,
    
        if (out_obj != NULL) { do_some_op(); *out_obj = something; }
    
    Now we have a few options. For those optional parameters that eventually
    get passed as the "constructor" out parameter of gjs_init_class_dynamic(),
    the constructor is going to need to be created anyhow. So there it's best
    to pass an ignored handle in.
    
    In gjs_context_get_frame_info(), where we can avoid doing some work by
    indicating that we don't need the particular out parameters, we use
    mozilla::Maybe. This has an unwieldy API in mozjs24 but is improved to be
    much more convenient in later releases. (If this were C++17, we could use
    std::optional instead.)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=742249

 gi/boxed.cpp                |    2 +-
 gi/fundamental.cpp          |   21 +++++++---------
 gi/fundamental.h            |   11 ++++----
 gi/gerror.cpp               |   16 +++++++-----
 gi/interface.cpp            |   16 ++++-------
 gi/interface.h              |   10 ++++----
 gi/object.cpp               |   36 ++++++++++++---------------
 gi/object.h                 |   10 ++++----
 gi/param.cpp                |    9 +++----
 gi/repo.cpp                 |   24 +++++++++++-------
 gi/union.cpp                |    2 +-
 gjs/context.cpp             |   13 ++++-----
 gjs/jsapi-dynamic-class.cpp |   34 +++++++++++--------------
 gjs/jsapi-util.cpp          |   25 ++++++++++---------
 gjs/jsapi-util.h            |   46 ++++++++++++++++++----------------
 gjs/stack.cpp               |   57 +++++++++++++++++++-----------------------
 modules/cairo-region.cpp    |    8 ++++--
 17 files changed, 166 insertions(+), 174 deletions(-)
---
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index fb83128..ac83e8e 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -1110,7 +1110,7 @@ gjs_define_boxed_class(JSContext    *context,
 {
     const char *constructor_name;
     JSObject *prototype;
-    JSObject *constructor;
+    JS::RootedObject constructor(context);
     JS::Value value;
     Boxed *priv;
 
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 22c7454..10bf86b 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -565,9 +565,7 @@ gjs_lookup_fundamental_prototype(JSContext    *context,
                                  GType         gtype)
 {
     JSObject *in_object;
-    JSObject *constructor;
     const char *constructor_name;
-    JS::Value value;
 
     if (info) {
         in_object = gjs_lookup_namespace_object(context, (GIBaseInfo*) info);
@@ -580,9 +578,11 @@ gjs_lookup_fundamental_prototype(JSContext    *context,
     if (G_UNLIKELY (!in_object))
         return NULL;
 
-    if (!JS_GetProperty(context, in_object, constructor_name, &value))
+    JS::RootedValue value(context);
+    if (!JS_GetProperty(context, in_object, constructor_name, value.address()))
         return NULL;
 
+    JS::RootedObject constructor(context);
     if (value.isUndefined()) {
         /* In case we're looking for a private type, and we don't find it,
            we need to define it first.
@@ -624,11 +624,11 @@ gjs_lookup_fundamental_prototype_from_gtype(JSContext *context,
 }
 
 bool
-gjs_define_fundamental_class(JSContext     *context,
-                             JSObject      *in_object,
-                             GIObjectInfo  *info,
-                             JSObject     **constructor_p,
-                             JSObject     **prototype_p)
+gjs_define_fundamental_class(JSContext              *context,
+                             JSObject               *in_object,
+                             GIObjectInfo           *info,
+                             JS::MutableHandleObject constructor,
+                             JSObject              **prototype_p)
 {
     const char *constructor_name;
     JSObject *prototype;
@@ -636,7 +636,6 @@ gjs_define_fundamental_class(JSContext     *context,
     jsid js_constructor_name = JSID_VOID;
     JSObject *parent_proto;
     Fundamental *priv;
-    JSObject *constructor;
     GType parent_gtype;
     GType gtype;
     GIFunctionInfo *constructor_info;
@@ -677,7 +676,7 @@ gjs_define_fundamental_class(JSContext     *context,
                                 /* funcs of constructor, MyConstructor.myfunc() */
                                 NULL,
                                 &prototype,
-                                &constructor)) {
+                                constructor)) {
         gjs_log_exception(context);
         g_error("Can't init class %s", constructor_name);
     }
@@ -722,8 +721,6 @@ gjs_define_fundamental_class(JSContext     *context,
     JS_DefineProperty(context, constructor, "$gtype", value,
                       NULL, NULL, JSPROP_PERMANENT);
 
-    if (constructor_p)
-        *constructor_p = constructor;
     if (prototype_p)
         *prototype_p = prototype;
 
diff --git a/gi/fundamental.h b/gi/fundamental.h
index d67750c..b631005 100644
--- a/gi/fundamental.h
+++ b/gi/fundamental.h
@@ -32,11 +32,12 @@
 
 G_BEGIN_DECLS
 
-bool      gjs_define_fundamental_class       (JSContext     *context,
-                                              JSObject      *in_object,
-                                              GIObjectInfo  *info,
-                                              JSObject     **constructor_p,
-                                              JSObject     **prototype_p);
+bool gjs_define_fundamental_class(JSContext              *context,
+                                  JSObject               *in_object,
+                                  GIObjectInfo           *info,
+                                  JS::MutableHandleObject constructor,
+                                  JSObject              **prototype_p);
+
 JSObject* gjs_object_from_g_fundamental      (JSContext     *context,
                                               GIObjectInfo  *info,
                                               void          *fobj);
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index b1c0136..73df0a6 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -317,7 +317,7 @@ gjs_define_error_class(JSContext    *context,
     const char *constructor_name;
     GIBoxedInfo *glib_error_info;
     JSObject *prototype, *parent_proto;
-    JSObject *constructor;
+    JS::RootedObject constructor(context);
     Error *priv;
 
     /* See the comment in gjs_define_boxed_class() for an
@@ -401,12 +401,14 @@ define_error_properties(JSContext *context,
                         JSObject  *obj)
 {
     jsid stack_name, filename_name, linenumber_name;
-    JS::Value stack, fileName, lineNumber;
-
-    if (!gjs_context_get_frame_info (context,
-                                     &stack,
-                                     &fileName,
-                                     &lineNumber))
+    JS::RootedValue stack(context), fileName(context), lineNumber(context);
+    /* COMPAT: mozilla::Maybe gains a much more usable API in future versions */
+    mozilla::Maybe<JS::MutableHandleValue> m_stack, m_file, m_line;
+    m_stack.construct(&stack);
+    m_file.construct(&fileName);
+    m_line.construct(&lineNumber);
+
+    if (!gjs_context_get_frame_info(context, m_stack, m_file, m_line))
         return;
 
     stack_name = gjs_context_get_const_string(context, GJS_STRING_STACK);
diff --git a/gi/interface.cpp b/gi/interface.cpp
index d06199a..476cc18 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -181,16 +181,15 @@ JSFunctionSpec gjs_interface_proto_funcs[] = {
 };
 
 bool
-gjs_define_interface_class(JSContext       *context,
-                           JSObject        *in_object,
-                           GIInterfaceInfo *info,
-                           GType            gtype,
-                           JSObject       **constructor_p)
+gjs_define_interface_class(JSContext              *context,
+                           JSObject               *in_object,
+                           GIInterfaceInfo        *info,
+                           GType                   gtype,
+                           JS::MutableHandleObject constructor)
 {
     Interface *priv;
     const char *constructor_name;
     const char *ns;
-    JSObject *constructor;
     JSObject *prototype;
     JS::Value value;
 
@@ -212,7 +211,7 @@ gjs_define_interface_class(JSContext       *context,
                                 /* funcs of constructor, MyConstructor.myfunc() */
                                 NULL,
                                 &prototype,
-                                &constructor)) {
+                                constructor)) {
         g_error("Can't init class %s", constructor_name);
     }
 
@@ -232,9 +231,6 @@ gjs_define_interface_class(JSContext       *context,
     JS_DefineProperty(context, constructor, "$gtype", value,
                       NULL, NULL, JSPROP_PERMANENT);
 
-    if (constructor_p)
-        *constructor_p = constructor;
-
     return true;
 }
 
diff --git a/gi/interface.h b/gi/interface.h
index 0dc5e56..ba5a6f1 100644
--- a/gi/interface.h
+++ b/gi/interface.h
@@ -32,11 +32,11 @@
 
 G_BEGIN_DECLS
 
-bool gjs_define_interface_class (JSContext       *context,
-                                 JSObject        *in_object,
-                                 GIInterfaceInfo *info,
-                                 GType            gtype,
-                                 JSObject       **constructor_p);
+bool gjs_define_interface_class(JSContext              *context,
+                                JSObject               *in_object,
+                                GIInterfaceInfo        *info,
+                                GType                   gtype,
+                                JS::MutableHandleObject constructor);
 
 bool gjs_lookup_interface_constructor(JSContext             *context,
                                       GType                  gtype,
diff --git a/gi/object.cpp b/gi/object.cpp
index f43cc0b..b977b78 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1477,7 +1477,6 @@ gjs_lookup_object_constructor_from_info(JSContext    *context,
                                         GType         gtype)
 {
     JSObject *in_object;
-    JSObject *constructor;
     const char *constructor_name;
     JS::Value value;
 
@@ -1495,6 +1494,7 @@ gjs_lookup_object_constructor_from_info(JSContext    *context,
     if (!JS_GetProperty(context, in_object, constructor_name, &value))
         return NULL;
 
+    JS::RootedObject constructor(context);
     if (value.isUndefined()) {
         /* In case we're looking for a private type, and we don't find it,
            we need to define it first.
@@ -1517,14 +1517,13 @@ gjs_lookup_object_prototype_from_info(JSContext    *context,
                                       GIObjectInfo *info,
                                       GType         gtype)
 {
-    JSObject *constructor;
-    JS::Value value;
-
-    constructor = gjs_lookup_object_constructor_from_info(context, info, gtype);
+    JS::RootedObject constructor(context,
+        gjs_lookup_object_constructor_from_info(context, info, gtype));
 
     if (G_UNLIKELY (constructor == NULL))
         return NULL;
 
+    JS::RootedValue value(context);
     if (!gjs_object_get_property_const(context, constructor,
                                        GJS_STRING_PROTOTYPE, &value))
         return NULL;
@@ -1893,15 +1892,14 @@ gjs_object_define_static_methods(JSContext    *context,
 }
 
 void
-gjs_define_object_class(JSContext      *context,
-                        JSObject       *in_object,
-                        GIObjectInfo   *info,
-                        GType           gtype,
-                        JSObject      **constructor_p)
+gjs_define_object_class(JSContext              *context,
+                        JSObject               *in_object,
+                        GIObjectInfo           *info,
+                        GType                   gtype,
+                        JS::MutableHandleObject constructor)
 {
     const char *constructor_name;
     JSObject *prototype;
-    JSObject *constructor;
     JSObject *parent_proto;
     JSObject *global;
 
@@ -1975,7 +1973,7 @@ gjs_define_object_class(JSContext      *context,
                                 /* funcs of constructor, MyConstructor.myfunc() */
                                 NULL,
                                 &prototype,
-                                &constructor)) {
+                                constructor)) {
         g_error("Can't init class %s", constructor_name);
     }
 
@@ -1997,9 +1995,6 @@ gjs_define_object_class(JSContext      *context,
     value = JS::ObjectValue(*gjs_gtype_create_gtype_wrapper(context, gtype));
     JS_DefineProperty(context, constructor, "$gtype", value,
                       NULL, NULL, JSPROP_PERMANENT);
-
-    if (constructor_p)
-        *constructor_p = constructor;
 }
 
 static JSObject*
@@ -2587,7 +2582,7 @@ gjs_object_custom_init(GTypeInstance *instance,
     GjsContext *gjs_context;
     JSContext *context;
     ObjectInstance *priv;
-    JS::Value v, r;
+    JS::Value r;
 
     if (!object_init_list)
       return;
@@ -2611,6 +2606,7 @@ gjs_object_custom_init(GTypeInstance *instance,
 
     associate_js_gobject(context, object, G_OBJECT (instance));
 
+    JS::RootedValue v(context);
     if (!gjs_object_get_property_const(context, object,
                                        GJS_STRING_INSTANCE_INIT, &v)) {
         gjs_log_exception(context);
@@ -2746,8 +2742,8 @@ gjs_register_interface(JSContext *cx,
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     char *name = NULL;
-    JS::RootedObject interfaces(cx), properties(cx);
-    JSObject *constructor, *module;
+    JS::RootedObject interfaces(cx), properties(cx), constructor(cx);
+    JSObject *module;
     guint32 i, n_interfaces, n_properties;
     GType *iface_types;
     GType interface_type;
@@ -2826,8 +2822,8 @@ gjs_register_type(JSContext *cx,
 {
     JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
     gchar *name;
-    JS::RootedObject parent(cx), interfaces(cx), properties(cx);
-    JSObject *constructor, *module;
+    JS::RootedObject parent(cx), interfaces(cx), properties(cx), constructor(cx);
+    JSObject *module;
     GType instance_type, parent_type;
     GTypeQuery query;
     GTypeModule *type_module;
diff --git a/gi/object.h b/gi/object.h
index f09d473..2906a96 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -31,11 +31,11 @@
 
 G_BEGIN_DECLS
 
-void      gjs_define_object_class       (JSContext     *context,
-                                         JSObject      *in_object,
-                                         GIObjectInfo  *info,
-                                         GType          gtype,
-                                         JSObject     **constructor_p);
+void gjs_define_object_class(JSContext              *context,
+                             JSObject               *in_object,
+                             GIObjectInfo           *info,
+                             GType                   gtype,
+                             JS::MutableHandleObject constructor);
 
 bool gjs_lookup_object_constructor(JSContext             *context,
                                    GType                  gtype,
diff --git a/gi/param.cpp b/gi/param.cpp
index a35c5f5..ad40abd 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -183,9 +183,7 @@ static JSObject*
 gjs_lookup_param_prototype(JSContext    *context)
 {
     JSObject *in_object;
-    JSObject *constructor;
     jsid gobject_name;
-    JS::Value value;
 
     gobject_name = gjs_intern_string_to_id(context, "GObject");
     in_object = gjs_lookup_namespace_object_by_name(context, gobject_name);
@@ -193,13 +191,14 @@ gjs_lookup_param_prototype(JSContext    *context)
     if (G_UNLIKELY (!in_object))
         return NULL;
 
-    if (!JS_GetProperty(context, in_object, "ParamSpec", &value))
+    JS::RootedValue value(context);
+    if (!JS_GetProperty(context, in_object, "ParamSpec", value.address()))
         return NULL;
 
     if (G_UNLIKELY (!value.isObject()))
         return NULL;
 
-    constructor = &value.toObject();
+    JS::RootedObject constructor(context, &value.toObject());
     g_assert(constructor != NULL);
 
     if (!gjs_object_get_property_const(context, constructor,
@@ -219,7 +218,7 @@ gjs_define_param_class(JSContext    *context,
     const char *constructor_name;
     JSObject *prototype;
     JS::Value value;
-    JSObject *constructor;
+    JS::RootedObject constructor(context);
     GIObjectInfo *info;
 
     constructor_name = "ParamSpec";
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 1b60039..2c8ade5 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -471,9 +471,12 @@ gjs_define_info(JSContext  *context,
             if (g_type_is_a (gtype, G_TYPE_PARAM)) {
                 gjs_define_param_class(context, in_object);
             } else if (g_type_is_a (gtype, G_TYPE_OBJECT)) {
-                gjs_define_object_class(context, in_object, (GIObjectInfo*) info, gtype, NULL);
+                JS::RootedObject ignored(context);
+                gjs_define_object_class(context, in_object,
+                                        (GIObjectInfo *) info, gtype, &ignored);
             } else if (G_TYPE_IS_INSTANTIATABLE(gtype)) {
-                if (!gjs_define_fundamental_class(context, in_object, (GIObjectInfo*)info, NULL, NULL)) {
+                JS::RootedObject ignored(context);
+                if (!gjs_define_fundamental_class(context, in_object, (GIObjectInfo*)info, &ignored, NULL)) {
                     gjs_throw (context,
                                "Unsupported fundamental class creation for type %s",
                                g_type_name(gtype));
@@ -522,9 +525,13 @@ gjs_define_info(JSContext  *context,
             return false;
         break;
     case GI_INFO_TYPE_INTERFACE:
-        gjs_define_interface_class(context, in_object, (GIInterfaceInfo *) info,
-                                   g_registered_type_info_get_g_type((GIRegisteredTypeInfo *) info),
-                                   NULL);
+        {
+            JS::RootedObject ignored(context);
+            gjs_define_interface_class(context, in_object,
+                                       (GIInterfaceInfo *) info,
+                                       g_registered_type_info_get_g_type((GIRegisteredTypeInfo *) info),
+                                       &ignored);
+        }
         break;
     default:
         gjs_throw(context, "API of type %s not implemented, cannot define %s.%s",
@@ -784,13 +791,12 @@ JSObject *
 gjs_lookup_generic_prototype(JSContext  *context,
                              GIBaseInfo *info)
 {
-    JSObject *constructor;
-    JS::Value value;
-
-    constructor = gjs_lookup_generic_constructor(context, info);
+    JS::RootedObject constructor(context,
+                                 gjs_lookup_generic_constructor(context, info));
     if (G_UNLIKELY (constructor == NULL))
         return NULL;
 
+    JS::RootedValue value(context);
     if (!gjs_object_get_property_const(context, constructor,
                                        GJS_STRING_PROTOTYPE, &value))
         return NULL;
diff --git a/gi/union.cpp b/gi/union.cpp
index a494622..2890b47 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -331,7 +331,7 @@ gjs_define_union_class(JSContext    *context,
     JS::Value value;
     Union *priv;
     GType gtype;
-    JSObject *constructor;
+    JS::RootedObject constructor(context);
 
     /* For certain unions, we may be able to relax this in the future by
      * directly allocating union memory, as we do for structures in boxed.c
diff --git a/gjs/context.cpp b/gjs/context.cpp
index ff39cd1..7596345 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -750,14 +750,13 @@ gjs_context_get_const_string(JSContext      *context,
 }
 
 bool
-gjs_object_get_property_const(JSContext      *context,
-                              JSObject       *obj,
-                              GjsConstString  property_name,
-                              JS::Value      *value_p)
+gjs_object_get_property_const(JSContext             *cx,
+                              JS::HandleObject       obj,
+                              GjsConstString         property_name,
+                              JS::MutableHandleValue value_p)
 {
-    jsid pname;
-    pname = gjs_context_get_const_string(context, property_name);
-    return JS_GetPropertyById(context, obj, pname, value_p);
+    JS::RootedId pname(cx, gjs_context_get_const_string(cx, property_name));
+    return JS_GetPropertyById(cx, obj, pname, value_p.address());
 }
 
 /**
diff --git a/gjs/jsapi-dynamic-class.cpp b/gjs/jsapi-dynamic-class.cpp
index 2581b2a..84b09e8 100644
--- a/gjs/jsapi-dynamic-class.cpp
+++ b/gjs/jsapi-dynamic-class.cpp
@@ -36,26 +36,25 @@
 #include <math.h>
 
 bool
-gjs_init_class_dynamic(JSContext       *context,
-                       JSObject        *in_object,
-                       JSObject        *parent_proto,
-                       const char      *ns_name,
-                       const char      *class_name,
-                       JSClass         *clasp,
-                       JSNative         constructor_native,
-                       unsigned         nargs,
-                       JSPropertySpec  *proto_ps,
-                       JSFunctionSpec  *proto_fs,
-                       JSPropertySpec  *static_ps,
-                       JSFunctionSpec  *static_fs,
-                       JSObject       **prototype_p,
-                       JSObject       **constructor_p)
+gjs_init_class_dynamic(JSContext              *context,
+                       JSObject               *in_object,
+                       JSObject               *parent_proto,
+                       const char             *ns_name,
+                       const char             *class_name,
+                       JSClass                *clasp,
+                       JSNative                constructor_native,
+                       unsigned                nargs,
+                       JSPropertySpec         *proto_ps,
+                       JSFunctionSpec         *proto_fs,
+                       JSPropertySpec         *static_ps,
+                       JSFunctionSpec         *static_fs,
+                       JSObject              **prototype_p,
+                       JS::MutableHandleObject constructor)
 {
     JSObject *global;
     /* Force these variables on the stack, so the conservative GC will
        find them */
     JSObject * volatile prototype;
-    JSObject * volatile constructor;
     JSFunction * volatile constructor_fun;
     char *full_function_name = NULL;
     bool res = false;
@@ -102,7 +101,7 @@ gjs_init_class_dynamic(JSContext       *context,
     if (!constructor_fun)
         goto out;
 
-    constructor = JS_GetFunctionObject(constructor_fun);
+    constructor.set(JS_GetFunctionObject(constructor_fun));
 
     if (static_ps && !JS_DefineProperties(context, constructor, static_ps))
         goto out;
@@ -122,8 +121,6 @@ gjs_init_class_dynamic(JSContext       *context,
                            JS_PropertyStub, JS_StrictPropertyStub, GJS_MODULE_PROP_FLAGS))
         goto out;
 
-    if (constructor_p)
-        *constructor_p = constructor;
     if (prototype_p)
         *prototype_p = prototype;
 
@@ -131,7 +128,6 @@ gjs_init_class_dynamic(JSContext       *context,
 
     prototype = NULL;
     constructor_fun = NULL;
-    constructor = NULL;
 
  out:
     JS_EndRequest(context);
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 8f39ea7..cd30847 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -193,14 +193,15 @@ gjs_throw_abstract_constructor_error(JSContext *context,
                                      JS::Value *vp)
 {
     JS::Value callee;
-    JS::Value prototype;
     JSClass *proto_class;
     const char *name = "anonymous";
 
     callee = JS_CALLEE(context, vp);
 
     if (callee.isObject()) {
-        if (gjs_object_get_property_const(context, &callee.toObject(),
+        JS::RootedObject callee_obj(context, &callee.toObject());
+        JS::RootedValue prototype(context);
+        if (gjs_object_get_property_const(context, callee_obj,
                                           GJS_STRING_PROTOTYPE, &prototype)) {
             proto_class = JS_GetClass(&prototype.toObject());
             name = proto_class->name;
@@ -424,25 +425,25 @@ gjs_log_exception_full(JSContext *context,
                        JS::Value  exc,
                        JSString  *message)
 {
-    JS::Value stack;
     char *utf8_exception, *utf8_message;
     bool is_syntax;
 
     JS_BeginRequest(context);
+    JS::RootedObject exc_obj(context);
 
     is_syntax = false;
 
     if (!exc.isObject()) {
         utf8_exception = utf8_exception_from_non_gerror_value(context, exc);
     } else {
-        JS::RootedObject exc_obj(context, &exc.toObject());
+        exc_obj = &exc.toObject();
         if (gjs_typecheck_boxed(context, exc_obj, NULL, G_TYPE_ERROR, false)) {
             GError *gerror = (GError *) gjs_c_struct_from_boxed(context, exc_obj);
             utf8_exception = g_strdup_printf("GLib.Error %s: %s",
                                              g_quark_to_string(gerror->domain),
                                              gerror->message);
         } else {
-            JS::Value js_name;
+            JS::RootedValue js_name(context);
             char *utf8_name;
 
             if (gjs_object_get_property_const(context, exc_obj,
@@ -467,14 +468,14 @@ gjs_log_exception_full(JSContext *context,
     */
 
     if (is_syntax) {
-        JS::Value js_lineNumber, js_fileName;
+        JS::RootedValue js_lineNumber(context), js_fileName(context);
         unsigned lineNumber;
         char *utf8_fileName;
 
-        gjs_object_get_property_const(context, &exc.toObject(),
-                                      GJS_STRING_LINE_NUMBER, &js_lineNumber);
-        gjs_object_get_property_const(context, &exc.toObject(),
-                                      GJS_STRING_FILENAME, &js_fileName);
+        gjs_object_get_property_const(context, exc_obj, GJS_STRING_LINE_NUMBER,
+                                      &js_lineNumber);
+        gjs_object_get_property_const(context, exc_obj, GJS_STRING_FILENAME,
+                                      &js_fileName);
 
         if (js_fileName.isString())
             gjs_string_to_utf8(context, js_fileName, &utf8_fileName);
@@ -494,10 +495,10 @@ gjs_log_exception_full(JSContext *context,
         g_free(utf8_fileName);
     } else {
         char *utf8_stack;
+        JS::RootedValue stack(context);
 
         if (exc.isObject() &&
-            gjs_object_get_property_const(context, &exc.toObject(),
-                                          GJS_STRING_STACK, &stack) &&
+            gjs_object_get_property_const(context, exc_obj, GJS_STRING_STACK, &stack) &&
             stack.isString())
             gjs_string_to_utf8(context, stack, &utf8_stack);
         else
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 5e24093..dc633ac 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -307,20 +307,21 @@ bool        gjs_object_require_property      (JSContext       *context,
                                               jsid             property_name,
                                               JS::Value       *value_p);
 
-bool        gjs_init_class_dynamic           (JSContext       *context,
-                                              JSObject        *in_object,
-                                              JSObject        *parent_proto,
-                                              const char      *ns_name,
-                                              const char      *class_name,
-                                              JSClass         *clasp,
-                                              JSNative         constructor,
-                                              unsigned         nargs,
-                                              JSPropertySpec  *ps,
-                                              JSFunctionSpec  *fs,
-                                              JSPropertySpec  *static_ps,
-                                              JSFunctionSpec  *static_fs,
-                                              JSObject       **constructor_p,
-                                              JSObject       **prototype_p);
+bool gjs_init_class_dynamic(JSContext              *context,
+                            JSObject               *in_object,
+                            JSObject               *parent_proto,
+                            const char             *ns_name,
+                            const char             *class_name,
+                            JSClass                *clasp,
+                            JSNative                constructor_native,
+                            unsigned                nargs,
+                            JSPropertySpec         *ps,
+                            JSFunctionSpec         *fs,
+                            JSPropertySpec         *static_ps,
+                            JSFunctionSpec         *static_fs,
+                            JSObject              **prototype_p,
+                            JS::MutableHandleObject constructor);
+
 void gjs_throw_constructor_error             (JSContext       *context);
 void gjs_throw_abstract_constructor_error    (JSContext       *context,
                                               JS::Value       *vp);
@@ -423,10 +424,10 @@ const char* gjs_get_type_name                (JS::Value        value);
 
 void gjs_maybe_gc (JSContext *context);
 
-bool              gjs_context_get_frame_info (JSContext  *context,
-                                              JS::Value  *stack,
-                                              JS::Value  *fileName,
-                                              JS::Value  *lineNumber);
+bool gjs_context_get_frame_info(JSContext                              *context,
+                                mozilla::Maybe<JS::MutableHandleValue>& stack,
+                                mozilla::Maybe<JS::MutableHandleValue>& fileName,
+                                mozilla::Maybe<JS::MutableHandleValue>& lineNumber);
 
 bool              gjs_eval_with_scope        (JSContext    *context,
                                               JSObject     *object,
@@ -467,10 +468,11 @@ typedef enum {
 
 jsid              gjs_context_get_const_string  (JSContext       *context,
                                                  GjsConstString   string);
-bool              gjs_object_get_property_const (JSContext       *context,
-                                                 JSObject        *obj,
-                                                 GjsConstString   property_name,
-                                                 JS::Value       *value_p);
+
+bool gjs_object_get_property_const(JSContext             *cx,
+                                   JS::HandleObject       obj,
+                                   GjsConstString         property_name,
+                                   JS::MutableHandleValue value_p);
 
 const char * gjs_strip_unix_shebang(const char *script,
                                     gssize     *script_len,
diff --git a/gjs/stack.cpp b/gjs/stack.cpp
index 9f2b3f5..f23e614 100644
--- a/gjs/stack.cpp
+++ b/gjs/stack.cpp
@@ -48,64 +48,59 @@
 #include "jsapi-util.h"
 
 bool
-gjs_context_get_frame_info (JSContext  *context,
-                            JS::Value  *stack,
-                            JS::Value  *fileName,
-                            JS::Value  *lineNumber)
+gjs_context_get_frame_info(JSContext                              *context,
+                           mozilla::Maybe<JS::MutableHandleValue>& stack,
+                           mozilla::Maybe<JS::MutableHandleValue>& fileName,
+                           mozilla::Maybe<JS::MutableHandleValue>& lineNumber)
 {
     JS::Value v_constructor;
-    JSObject *err_obj;
     JSObject *global;
-    bool ret = false;
 
-    JS_BeginRequest(context);
+    JSAutoRequest ar(context);
     global = JS_GetGlobalForScopeChain(context);
     JSAutoCompartment ac(context, global);
 
     if (!JS_GetProperty(context, global, "Error", &v_constructor) ||
         !v_constructor.isObject()) {
         g_error("??? Missing Error constructor in global object?");
-        goto out;
+        return false;
     }
 
-    err_obj = JS_New(context, &v_constructor.toObject(), 0, NULL);
+    JS::RootedObject err_obj(context,
+                             JS_New(context, &v_constructor.toObject(), 0, NULL));
 
-    if (stack != NULL) {
-        if (!gjs_object_get_property_const(context, err_obj,
-                                           GJS_STRING_STACK, stack))
-            goto out;
-    }
-
-    if (fileName != NULL) {
-        if (!gjs_object_get_property_const(context, err_obj,
-                                           GJS_STRING_FILENAME, fileName))
-            goto out;
-    }
+    if (!stack.empty() &&
+        !gjs_object_get_property_const(context, err_obj, GJS_STRING_STACK,
+                                       stack.ref()))
+        return false;
 
-    if (lineNumber != NULL) {
-        if (!gjs_object_get_property_const(context, err_obj,
-                                           GJS_STRING_LINE_NUMBER, lineNumber))
-            goto out;
-    }
+    if (!fileName.empty() &&
+        !gjs_object_get_property_const(context, err_obj, GJS_STRING_FILENAME,
+                                       fileName.ref()))
+        return false;
 
-    ret = true;
+    if (!lineNumber.empty() &&
+        !gjs_object_get_property_const(context, err_obj, GJS_STRING_LINE_NUMBER,
+                                       lineNumber.ref()))
+        return false;
 
- out:
-    JS_EndRequest(context);
-    return ret;
+    return true;
 }
 
 void
 gjs_context_print_stack_stderr(GjsContext *context)
 {
     JSContext *cx = (JSContext*) gjs_context_get_native_context(context);
-    JS::Value v_stack;
+    JS::RootedValue v_stack(cx);
     char *stack;
 
     g_printerr("== Stack trace for context %p ==\n", context);
 
     /* Stderr is locale encoding, so we use string_to_filename here */
-    if (!gjs_context_get_frame_info(cx, &v_stack, NULL, NULL) ||
+    /* COMPAT: mozilla::Maybe gains a much more usable API in future versions */
+    mozilla::Maybe<JS::MutableHandleValue> m_stack, m_file, m_line;
+    m_stack.construct(&v_stack);
+    if (!gjs_context_get_frame_info(cx, m_stack, m_file, m_line) ||
         !gjs_string_to_filename(cx, v_stack, &stack)) {
         g_printerr("No stack trace available\n");
         return;
diff --git a/modules/cairo-region.cpp b/modules/cairo-region.cpp
index ecee331..f941374 100644
--- a/modules/cairo-region.cpp
+++ b/modules/cairo-region.cpp
@@ -51,7 +51,8 @@ get_region(JSContext       *context,
 }
 
 static bool
-fill_rectangle(JSContext *context, JSObject *obj,
+fill_rectangle(JSContext             *context,
+               JS::HandleObject       obj,
                cairo_rectangle_int_t *rect);
 
 #define PRELUDE                                                       \
@@ -113,10 +114,11 @@ REGION_DEFINE_RECT_FUNC(intersect)
 REGION_DEFINE_RECT_FUNC(xor)
 
 static bool
-fill_rectangle(JSContext *context, JSObject *obj,
+fill_rectangle(JSContext             *context,
+               JS::HandleObject       obj,
                cairo_rectangle_int_t *rect)
 {
-    JS::Value val;
+    JS::RootedValue val(context);
 
     if (!gjs_object_get_property_const(context, obj, GJS_STRING_X, &val))
         return false;


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