diff -pruN 1.72.0-4/build/flatpak/org.gnome.GjsConsole.json 1.73.1-1/build/flatpak/org.gnome.GjsConsole.json
--- 1.72.0-4/build/flatpak/org.gnome.GjsConsole.json	2022-03-19 18:04:36.057217400 +0000
+++ 1.73.1-1/build/flatpak/org.gnome.GjsConsole.json	2022-07-10 19:35:20.000000000 +0000
@@ -11,10 +11,16 @@
   "sdk": "org.gnome.Sdk",
   "command": "gjs-console",
   "finish-args": [
-    "--socket=x11",
+    "--share=ipc",
+    "--socket=fallback-x11",
     "--socket=wayland",
+    "--device=dri",
     "--share=network",
-    "--filesystem=host"
+    "--filesystem=host",
+    "--filesystem=home",
+    "--socket=session-bus",
+    "--socket=system-bus",
+    "--socket=pulseaudio"
   ],
   "modules": [
     {
diff -pruN 1.72.0-4/debian/changelog 1.73.1-1/debian/changelog
--- 1.72.0-4/debian/changelog	2022-06-29 12:40:12.000000000 +0000
+++ 1.73.1-1/debian/changelog	2022-08-03 15:51:35.000000000 +0000
@@ -1,3 +1,10 @@
+gjs (1.73.1-1) unstable; urgency=medium
+
+  * New upstream release
+  * debian/control.in: Bump minimum meson to 0.54.0
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Wed, 03 Aug 2022 11:51:35 -0400
+
 gjs (1.72.0-4) unstable; urgency=medium
 
   [ Simon McVittie ]
diff -pruN 1.72.0-4/debian/control 1.73.1-1/debian/control
--- 1.72.0-4/debian/control	2022-06-29 12:40:12.000000000 +0000
+++ 1.73.1-1/debian/control	2022-08-03 15:51:35.000000000 +0000
@@ -19,7 +19,7 @@ Build-Depends: debhelper-compat (= 13),
                gobject-introspection (>= 1.64),
                libmozjs-91-dev (>= 91.3.0),
                libreadline-dev,
-               meson (>= 0.50.0),
+               meson (>= 0.54.0),
                dbus <!nocheck>,
                dbus-x11 <!nocheck>,
                at-spi2-core <!nocheck>,
diff -pruN 1.72.0-4/debian/control.in 1.73.1-1/debian/control.in
--- 1.72.0-4/debian/control.in	2022-06-29 12:40:12.000000000 +0000
+++ 1.73.1-1/debian/control.in	2022-08-03 15:51:35.000000000 +0000
@@ -15,7 +15,7 @@ Build-Depends: debhelper-compat (= 13),
                gobject-introspection (>= 1.64),
                libmozjs-91-dev (>= 91.3.0),
                libreadline-dev,
-               meson (>= 0.50.0),
+               meson (>= 0.54.0),
                dbus <!nocheck>,
                dbus-x11 <!nocheck>,
                at-spi2-core <!nocheck>,
diff -pruN 1.72.0-4/debian/patches/arg-cache-Use-BoxedInTransferNone-release-for-GBytesInTra.patch 1.73.1-1/debian/patches/arg-cache-Use-BoxedInTransferNone-release-for-GBytesInTra.patch
--- 1.72.0-4/debian/patches/arg-cache-Use-BoxedInTransferNone-release-for-GBytesInTra.patch	2022-06-29 12:40:12.000000000 +0000
+++ 1.73.1-1/debian/patches/arg-cache-Use-BoxedInTransferNone-release-for-GBytesInTra.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,31 +0,0 @@
-From: msizanoen1 <msizanoen@qtmlabs.xyz>
-Date: Tue, 24 May 2022 16:51:15 +0700
-Subject: arg-cache: Use BoxedInTransferNone::release for
- GBytesInTransferNone::release
-
-GBytes parameters in "transfer none" mode needs to be released after the
-function returns, otherwise its reference count will be incremented even
-if the callee doesn't own the reference, causing a memory leak. Fix this
-by using BoxedInTransferNone::release instead of BoxedIn::release which is
-a no-op.
-
-Fixes #483
-
-(cherry picked from commit f43d9d16445967498cd8652f87f5450b81b5bf6a)
----
- gi/arg-cache.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
-index 83c4ad4..bf08e53 100644
---- a/gi/arg-cache.cpp
-+++ b/gi/arg-cache.cpp
-@@ -596,7 +596,7 @@ struct GBytesInTransferNone : GBytesIn {
-     using GBytesIn::GBytesIn;
-     bool release(JSContext* cx, GjsFunctionCallState* state, GIArgument* in_arg,
-                  GIArgument* out_arg) override {
--        return BoxedIn::release(cx, state, in_arg, out_arg);
-+        return BoxedInTransferNone::release(cx, state, in_arg, out_arg);
-     }
- };
- 
diff -pruN 1.72.0-4/debian/patches/jsapi-util-strings-Ignore-locale-to-compute-the-upper-cas.patch 1.73.1-1/debian/patches/jsapi-util-strings-Ignore-locale-to-compute-the-upper-cas.patch
--- 1.72.0-4/debian/patches/jsapi-util-strings-Ignore-locale-to-compute-the-upper-cas.patch	2022-06-29 12:40:12.000000000 +0000
+++ 1.73.1-1/debian/patches/jsapi-util-strings-Ignore-locale-to-compute-the-upper-cas.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,58 +0,0 @@
-From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
-Date: Thu, 28 Apr 2022 19:53:59 +0200
-Subject: jsapi-util-strings: Ignore locale to compute the upper case of a
- char
-MIME-Version: 1.0
-Content-Type: text/plain; charset="utf-8"
-Content-Transfer-Encoding: 8bit
-
-We used to compute camel-case name of properties using toupper(),
-however this is locale-dependent, while in this case we want to be sure
-that we're only using ASCII values.
-
-This is particularly problematic in Turkish (and maybe other locales)
-because there 'i'.toLocaleUpperCase() is 'İ', that is definitely not an
-ASCII char, causing problems to with our generated properties.
-
-See: https://github.com/micheleg/dash-to-dock/issues/1687
-
-Origin: https://gitlab.gnome.org/GNOME/gjs/-/merge_requests/742
-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gjs/+bug/1969838
----
- gjs/gjs_pch.hh            | 1 -
- gjs/jsapi-util-string.cpp | 3 +--
- 2 files changed, 1 insertion(+), 3 deletions(-)
-
-diff --git a/gjs/gjs_pch.hh b/gjs/gjs_pch.hh
-index 46bea8a..6f1b0b4 100644
---- a/gjs/gjs_pch.hh
-+++ b/gjs/gjs_pch.hh
-@@ -28,7 +28,6 @@
- #include <vector>
- 
- #include <assert.h>
--#include <ctype.h>
- #include <errno.h>
- #include <ffi.h>
- #include <gio/gio.h>
-diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
-index c78069a..a39a0c0 100644
---- a/gjs/jsapi-util-string.cpp
-+++ b/gjs/jsapi-util-string.cpp
-@@ -4,7 +4,6 @@
- 
- #include <config.h>
- 
--#include <ctype.h>  // for toupper
- #include <stdint.h>
- #include <string.h>     // for size_t, strlen
- #include <sys/types.h>  // for ssize_t
-@@ -59,7 +58,7 @@ GjsAutoChar gjs_hyphen_to_camel(const char* str) {
-         if (*input_iter == '-') {
-             uppercase_next = true;
-         } else if (uppercase_next) {
--            *output_iter++ = toupper(*input_iter);
-+            *output_iter++ = g_ascii_toupper(*input_iter);
-             uppercase_next = false;
-         } else {
-             *output_iter++ = *input_iter;
diff -pruN 1.72.0-4/debian/patches/series 1.73.1-1/debian/patches/series
--- 1.72.0-4/debian/patches/series	2022-06-29 12:40:12.000000000 +0000
+++ 1.73.1-1/debian/patches/series	2022-08-03 15:51:35.000000000 +0000
@@ -1,2 +0,0 @@
-jsapi-util-strings-Ignore-locale-to-compute-the-upper-cas.patch
-arg-cache-Use-BoxedInTransferNone-release-for-GBytesInTra.patch
diff -pruN 1.72.0-4/doc/Logging.md 1.73.1-1/doc/Logging.md
--- 1.72.0-4/doc/Logging.md	2022-03-19 18:04:36.058217300 +0000
+++ 1.73.1-1/doc/Logging.md	2022-07-10 19:35:20.000000000 +0000
@@ -1,7 +1,14 @@
 GJS includes a number of built-in functions for logging and aiding debugging, in
 addition to those available as a part of the GNOME APIs.
 
-# Built-in Functions
+## `console` Functions
+
+As of GJS 1.70 (GNOME 41), the `console` collection of functions are available
+as described in the WHATWG [Console Standard][console-standard]. The `console`
+object is available globally (i.e. without import) and the implementation source
+is found in [console.js][console-js].
+
+## Built-in Functions
 
 GJS includes four built-in logging functions: `log()`, `logError()`, `print()`
 and `printerr()`. These functions are available globally (ie. without import)
@@ -110,6 +117,8 @@ if (GLib.log_writer_is_journald(2))
     GLib.setenv('G_MESSAGES_DEBUG', LOG_DOMAIN, false);
 ```
 
+[console-js]: https://gitlab.gnome.org/GNOME/gjs/-/blob/HEAD/modules/esm/console.js
+[console-standard]: https://console.spec.whatwg.org/
 [global-cpp]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/gjs/global.cpp
 [polari]: https://gitlab.gnome.org/GNOME/polari/blob/HEAD/src/main.js
 
diff -pruN 1.72.0-4/gi/arg-cache.cpp 1.73.1-1/gi/arg-cache.cpp
--- 1.72.0-4/gi/arg-cache.cpp	2022-03-19 18:04:36.062217500 +0000
+++ 1.73.1-1/gi/arg-cache.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -6,6 +6,7 @@
 #include <config.h>
 
 #include <inttypes.h>
+#include <stddef.h>  // for size_t
 #include <stdint.h>
 #include <string.h>
 
@@ -61,34 +62,9 @@ static const char* expected_type_names[]
 static_assert(G_N_ELEMENTS(expected_type_names) == ExpectedType::LAST,
               "Names must match the values in ExpectedType");
 
-// A helper function to retrieve array lengths from a GIArgument (letting the
-// compiler generate good instructions in case of big endian machines)
-[[nodiscard]] size_t gjs_g_argument_get_array_length(GITypeTag tag,
-                                                     GIArgument* arg) {
-    switch (tag) {
-        case GI_TYPE_TAG_INT8:
-            return gjs_arg_get<int8_t>(arg);
-        case GI_TYPE_TAG_UINT8:
-            return gjs_arg_get<uint8_t>(arg);
-        case GI_TYPE_TAG_INT16:
-            return gjs_arg_get<int16_t>(arg);
-        case GI_TYPE_TAG_UINT16:
-            return gjs_arg_get<uint16_t>(arg);
-        case GI_TYPE_TAG_INT32:
-            return gjs_arg_get<int32_t>(arg);
-        case GI_TYPE_TAG_UINT32:
-            return gjs_arg_get<uint32_t>(arg);
-        case GI_TYPE_TAG_INT64:
-            return gjs_arg_get<int64_t>(arg);
-        case GI_TYPE_TAG_UINT64:
-            return gjs_arg_get<uint64_t>(arg);
-        default:
-            g_assert_not_reached();
-    }
-}
-
-static void gjs_g_argument_set_array_length(GITypeTag tag, GIArgument* arg,
-                                            size_t value) {
+static constexpr void gjs_g_argument_set_array_length(GITypeTag tag,
+                                                      GIArgument* arg,
+                                                      size_t value) {
     switch (tag) {
         case GI_TYPE_TAG_INT8:
             gjs_arg_set<int8_t>(arg, value);
@@ -166,7 +142,10 @@ struct String {
 };
 
 struct TypeInfo {
-    constexpr const GITypeInfo* type_info() const { return &m_type_info; }
+    constexpr GITypeInfo* type_info() const {
+        // Should be const GITypeInfo*, but G-I APIs won't accept that
+        return const_cast<GITypeInfo*>(&m_type_info);
+    }
 
     GITypeInfo m_type_info;
 };
@@ -205,7 +184,8 @@ struct Positioned {
         m_arg_pos = pos;
     }
 
-    bool set_out_parameter(GjsFunctionCallState* state, GIArgument* arg) {
+    constexpr bool set_out_parameter(GjsFunctionCallState* state,
+                                     GIArgument* arg) {
         gjs_arg_unset<void*>(&state->out_cvalue(m_arg_pos));
         gjs_arg_set(arg, &gjs_arg_member<void*>(&state->out_cvalue(m_arg_pos)));
         return true;
@@ -226,8 +206,10 @@ struct Array : BasicType {
 };
 
 struct BaseInfo {
-    explicit BaseInfo(GIBaseInfo* info)
-        : m_info(info ? g_base_info_ref(info) : nullptr) {}
+    constexpr explicit BaseInfo(GIBaseInfo* info,
+                                const GjsAutoTakeOwnership& add_ref)
+        : m_info(info, add_ref) {}
+    constexpr explicit BaseInfo(GIBaseInfo* info) : m_info(info) {}
 
     GjsAutoBaseInfo m_info;
 };
@@ -251,7 +233,8 @@ struct RegisteredType {
 
 struct RegisteredInterface : BaseInfo {
     explicit RegisteredInterface(GIBaseInfo* info)
-        : BaseInfo(info), m_gtype(g_registered_type_info_get_g_type(m_info)) {}
+        : BaseInfo(info, GjsAutoTakeOwnership{}),
+          m_gtype(g_registered_type_info_get_g_type(m_info)) {}
 
     constexpr GType gtype() const { return m_gtype; }
 
@@ -259,8 +242,8 @@ struct RegisteredInterface : BaseInfo {
 };
 
 struct Callback : Nullable, BaseInfo {
-    explicit Callback(GITypeInfo* type_info)
-        : BaseInfo(g_type_info_get_interface(type_info)),
+    constexpr explicit Callback(GIInterfaceInfo* info)
+        : BaseInfo(info, GjsAutoTakeOwnership{}),
           m_scope(GI_SCOPE_TYPE_INVALID) {}
 
     inline void set_callback_destroy_pos(int pos) {
@@ -555,7 +538,7 @@ struct UnregisteredBoxedIn : BoxedIn, Ba
     explicit UnregisteredBoxedIn(GIInterfaceInfo* info)
         : BoxedIn(g_registered_type_info_get_g_type(info),
                   g_base_info_get_type(info)),
-          BaseInfo(info) {}
+          BaseInfo(info, GjsAutoTakeOwnership{}) {}
     // This is a smart argument, no release needed
     GIBaseInfo* info() const override { return m_info; }
 };
@@ -596,7 +579,7 @@ struct GBytesInTransferNone : GBytesIn {
     using GBytesIn::GBytesIn;
     bool release(JSContext* cx, GjsFunctionCallState* state, GIArgument* in_arg,
                  GIArgument* out_arg) override {
-        return BoxedIn::release(cx, state, in_arg, out_arg);
+        return BoxedInTransferNone::release(cx, state, in_arg, out_arg);
     }
 };
 
@@ -708,6 +691,8 @@ struct CallbackIn : SkipAll, Callback {
 
     bool release(JSContext*, GjsFunctionCallState*, GIArgument*,
                  GIArgument*) override;
+ private:
+    ffi_closure *m_ffi_closure;
 };
 
 using CArrayIn = ExplicitArrayIn;
@@ -730,26 +715,44 @@ struct CallerAllocatesOut : GenericOut,
 GJS_JSAPI_RETURN_CONVENTION
 bool NotIntrospectable::in(JSContext* cx, GjsFunctionCallState* state,
                            GIArgument*, JS::HandleValue) {
-    static const char* reason_strings[] = {
-        "callback out-argument",
-        "DestroyNotify argument with no callback",
-        "DestroyNotify argument with no user data",
-        "type not supported for (transfer container)",
-        "type not supported for (out caller-allocates)",
-        "boxed type with transfer not registered as a GType",
-        "union type not registered as a GType",
-        "type not supported by introspection",
-    };
-    static_assert(
-        G_N_ELEMENTS(reason_strings) == NotIntrospectableReason::LAST_REASON,
-        "Explanations must match the values in NotIntrospectableReason");
+    const char* reason_string = "invalid introspection";
+
+    switch (m_reason) {
+        case CALLBACK_OUT:
+            reason_string = "callback out-argument";
+            break;
+        case DESTROY_NOTIFY_NO_CALLBACK:
+            reason_string = "DestroyNotify argument with no callback";
+            break;
+        case DESTROY_NOTIFY_NO_USER_DATA:
+            reason_string = "DestroyNotify argument with no user data";
+            break;
+        case INTERFACE_TRANSFER_CONTAINER:
+            reason_string = "type not supported for (transfer container)";
+            break;
+        case OUT_CALLER_ALLOCATES_NON_STRUCT:
+            reason_string = "type not supported for (out caller-allocates)";
+            break;
+        case UNREGISTERED_BOXED_WITH_TRANSFER:
+            reason_string =
+                "boxed type with transfer not registered as a GType";
+            break;
+        case UNREGISTERED_UNION:
+            reason_string = "union type not registered as a GType";
+            break;
+        case UNSUPPORTED_TYPE:
+            reason_string = "type not supported by introspection";
+            break;
+        case LAST_REASON:
+            g_assert_not_reached();
+    }
 
     gjs_throw(cx,
               "Function %s() cannot be called: argument '%s' with type %s is "
               "not introspectable because it has a %s",
               state->display_name().get(), m_arg_name,
               g_type_tag_to_string(g_type_info_get_tag(&m_type_info)),
-              reason_strings[m_reason]);
+              reason_string);
     return false;
 }
 
@@ -826,11 +829,12 @@ GJS_JSAPI_RETURN_CONVENTION
 bool CallbackIn::in(JSContext* cx, GjsFunctionCallState* state, GIArgument* arg,
                     JS::HandleValue value) {
     GjsCallbackTrampoline* trampoline;
-    ffi_closure* closure;
+    void* closure;
 
     if (value.isNull() && m_nullable) {
         closure = nullptr;
         trampoline = nullptr;
+        m_ffi_closure = nullptr;
     } else {
         if (JS_TypeOfValue(cx, value) != JSTYPE_FUNCTION) {
             gjs_throw(cx, "Expected function for callback argument %s, got %s",
@@ -855,6 +859,7 @@ bool CallbackIn::in(JSContext* cx, GjsFu
                 return false;
         }
         closure = trampoline->closure();
+        m_ffi_closure = trampoline->get_ffi_closure();
     }
 
     if (has_callback_destroy()) {
@@ -879,10 +884,11 @@ bool CallbackIn::in(JSContext* cx, GjsFu
     }
 
     bool keep_forever =
+        !has_callback_destroy() && (
 #if GI_CHECK_VERSION(1, 72, 0)
-        m_scope == GI_SCOPE_TYPE_FOREVER ||
+                                       m_scope == GI_SCOPE_TYPE_FOREVER ||
 #endif
-        m_scope == GI_SCOPE_TYPE_NOTIFIED && !has_callback_destroy();
+                                       m_scope == GI_SCOPE_TYPE_NOTIFIED);
 
     if (trampoline && keep_forever) {
         trampoline->mark_forever();
@@ -1411,7 +1417,7 @@ bool CallerAllocatesOut::release(JSConte
 GJS_JSAPI_RETURN_CONVENTION
 bool CallbackIn::release(JSContext*, GjsFunctionCallState*, GIArgument* in_arg,
                          GIArgument* out_arg [[maybe_unused]]) {
-    auto* closure = gjs_arg_get<ffi_closure*>(in_arg);
+    ffi_closure *closure = m_ffi_closure;
     if (!closure)
         return true;
 
@@ -2171,8 +2177,8 @@ void ArgsCache::build_arg(uint8_t gi_ind
                     common_args, DESTROY_NOTIFY_NO_CALLBACK);
                 *inc_counter_out = false;
             } else {
-                auto* gjs_arg =
-                    set_argument_auto<Arg::CallbackIn>(common_args, &type_info);
+                auto* gjs_arg = set_argument_auto<Arg::CallbackIn>(
+                    common_args, interface_info);
 
                 int destroy_pos = g_arg_info_get_destroy(arg);
                 int closure_pos = g_arg_info_get_closure(arg);
diff -pruN 1.72.0-4/gi/arg-cache.h 1.73.1-1/gi/arg-cache.h
--- 1.72.0-4/gi/arg-cache.h	2022-03-19 18:04:36.062217500 +0000
+++ 1.73.1-1/gi/arg-cache.h	2022-07-10 19:35:20.000000000 +0000
@@ -8,7 +8,6 @@
 
 #include <config.h>
 
-#include <stddef.h>
 #include <stdint.h>
 
 #include <limits>
@@ -231,7 +230,4 @@ struct ArgsCache {
 
 }  // namespace Gjs
 
-[[nodiscard]] size_t gjs_g_argument_get_array_length(GITypeTag tag,
-                                                     GIArgument* arg);
-
 #endif  // GI_ARG_CACHE_H_
diff -pruN 1.72.0-4/gi/arg.cpp 1.73.1-1/gi/arg.cpp
--- 1.72.0-4/gi/arg.cpp	2022-03-19 18:04:36.063217400 +0000
+++ 1.73.1-1/gi/arg.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -209,6 +209,10 @@ static bool _gjs_enum_value_is_valid(JSC
     }
 }
 
+[[nodiscard]] static inline bool is_string_type(GITypeTag tag) {
+    return tag == GI_TYPE_TAG_FILENAME || tag == GI_TYPE_TAG_UTF8;
+}
+
 /* Check if an argument of the given needs to be released if we obtained it
  * from out argument (or the return value), and we're transferring ownership
  */
@@ -340,7 +344,7 @@ GJS_JSAPI_RETURN_CONVENTION static bool
     /* Don't use key/value destructor functions here, because we can't
      * construct correct ones in general if the value type is complex.
      * Rely on the type-aware g_argument_release functions. */
-    if (key_type == GI_TYPE_TAG_UTF8 || key_type == GI_TYPE_TAG_FILENAME)
+    if (is_string_type(key_type))
         return g_hash_table_new(g_str_hash, g_str_equal);
     return g_hash_table_new(NULL, NULL);
 }
@@ -967,16 +971,11 @@ static bool gjs_array_to_array(JSContext
     }
 }
 
-GJS_JSAPI_RETURN_CONVENTION
-static GArray*
-gjs_g_array_new_for_type(JSContext    *context,
-                         unsigned int  length,
-                         GITypeInfo   *param_info)
-{
+static GArray* garray_new_for_storage_type(unsigned length,
+                                           GITypeTag storage_type) {
     guint element_size;
-    GITypeTag element_type = g_type_info_get_storage_type(param_info);
 
-    switch (element_type) {
+    switch (storage_type) {
     case GI_TYPE_TAG_BOOLEAN:
         element_size = sizeof(gboolean);
         break;
@@ -1020,9 +1019,7 @@ gjs_g_array_new_for_type(JSContext    *c
         break;
     case GI_TYPE_TAG_VOID:
     default:
-        gjs_throw(context,
-                  "Unhandled GArray element-type %d", element_type);
-        return NULL;
+        g_assert_not_reached();
     }
 
     return g_array_sized_new(true, false, element_size, length);
@@ -1720,10 +1717,8 @@ bool gjs_value_to_g_argument(JSContext*
         if (array_type == GI_ARRAY_TYPE_C) {
             gjs_arg_set(arg, data.release());
         } else if (array_type == GI_ARRAY_TYPE_ARRAY) {
-            GArray *array = gjs_g_array_new_for_type(context, length, param_info);
-
-            if (!array)
-                return false;
+            GITypeTag storage_type = g_type_info_get_storage_type(param_info);
+            GArray* array = garray_new_for_storage_type(length, storage_type);
 
             if (data)
                 g_array_append_vals(array, data, length);
diff -pruN 1.72.0-4/gi/arg-inl.h 1.73.1-1/gi/arg-inl.h
--- 1.72.0-4/gi/arg-inl.h	2022-03-19 18:04:36.062217500 +0000
+++ 1.73.1-1/gi/arg-inl.h	2022-07-10 19:35:20.000000000 +0000
@@ -39,7 +39,7 @@
 //   appropriate union member for type T and returns the replaced value.
 
 template <auto GIArgument::*member>
-[[nodiscard]] inline decltype(auto) gjs_arg_member(GIArgument* arg) {
+[[nodiscard]] constexpr inline decltype(auto) gjs_arg_member(GIArgument* arg) {
     return (arg->*member);
 }
 
@@ -47,7 +47,7 @@ template <auto GIArgument::*member>
  * which are in fact typedef's of other generic types.
  * Setting a tag for a type allows to perform proper specialization. */
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-[[nodiscard]] inline decltype(auto) gjs_arg_member(GIArgument* arg) {
+[[nodiscard]] constexpr inline decltype(auto) gjs_arg_member(GIArgument* arg) {
     if constexpr (TAG == GI_TYPE_TAG_VOID) {
         if constexpr (std::is_same_v<T, bool>)
             return gjs_arg_member<&GIArgument::v_boolean>(arg);
@@ -115,7 +115,7 @@ template <typename T, GITypeTag TAG = GI
 }
 
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-inline void gjs_arg_set(GIArgument* arg, T v) {
+constexpr inline void gjs_arg_set(GIArgument* arg, T v) {
     if constexpr (std::is_pointer_v<T>) {
         using NonconstPtrT =
             std::add_pointer_t<std::remove_const_t<std::remove_pointer_t<T>>>;
@@ -132,18 +132,18 @@ inline void gjs_arg_set(GIArgument* arg,
 // Store function pointers as void*. It is a requirement of GLib that your
 // compiler can do this
 template <typename ReturnT, typename... Args>
-inline void gjs_arg_set(GIArgument* arg, ReturnT (*v)(Args...)) {
+constexpr inline void gjs_arg_set(GIArgument* arg, ReturnT (*v)(Args...)) {
     gjs_arg_member<void*>(arg) = reinterpret_cast<void*>(v);
 }
 
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-inline std::enable_if_t<std::is_integral_v<T>> gjs_arg_set(GIArgument* arg,
-                                                           void *v) {
+constexpr inline std::enable_if_t<std::is_integral_v<T>> gjs_arg_set(
+    GIArgument* arg, void* v) {
     gjs_arg_set<T, TAG>(arg, gjs_pointer_to_int<T>(v));
 }
 
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-[[nodiscard]] inline T gjs_arg_get(GIArgument* arg) {
+[[nodiscard]] constexpr inline T gjs_arg_get(GIArgument* arg) {
     if constexpr (std::is_same_v<T, bool> ||
                   (std::is_same_v<T, gboolean> && TAG == GI_TYPE_TAG_BOOLEAN))
         return T(!!gjs_arg_member<T, TAG>(arg));
@@ -152,12 +152,12 @@ template <typename T, GITypeTag TAG = GI
 }
 
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-[[nodiscard]] inline void* gjs_arg_get_as_pointer(GIArgument* arg) {
+[[nodiscard]] constexpr inline void* gjs_arg_get_as_pointer(GIArgument* arg) {
     return gjs_int_to_pointer(gjs_arg_get<T, TAG>(arg));
 }
 
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-inline void gjs_arg_unset(GIArgument* arg) {
+constexpr inline void gjs_arg_unset(GIArgument* arg) {
     if constexpr (std::is_pointer_v<T>)
         gjs_arg_set<T, TAG>(arg, nullptr);
     else
@@ -165,7 +165,7 @@ inline void gjs_arg_unset(GIArgument* ar
 }
 
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-[[nodiscard]] inline T gjs_arg_steal(GIArgument* arg) {
+[[nodiscard]] constexpr inline T gjs_arg_steal(GIArgument* arg) {
     auto val = gjs_arg_get<T, TAG>(arg);
     gjs_arg_unset<T, TAG>(arg);
     return val;
@@ -174,10 +174,10 @@ template <typename T, GITypeTag TAG = GI
 // Implementation to store rounded (u)int64_t numbers into double
 
 template <typename BigT>
-[[nodiscard]] inline std::enable_if_t<std::is_integral_v<BigT> &&
-                                          (std::numeric_limits<BigT>::max() >
-                                           std::numeric_limits<int32_t>::max()),
-                                      double>
+[[nodiscard]] inline constexpr std::enable_if_t<
+    std::is_integral_v<BigT> && (std::numeric_limits<BigT>::max() >
+                                 std::numeric_limits<int32_t>::max()),
+    double>
 gjs_arg_get_maybe_rounded(GIArgument* arg) {
     BigT val = gjs_arg_get<BigT>(arg);
 
@@ -211,3 +211,29 @@ GJS_JSAPI_RETURN_CONVENTION inline bool
 
     return true;
 }
+
+// A helper function to retrieve array lengths from a GIArgument (letting the
+// compiler generate good instructions in case of big endian machines)
+[[nodiscard]] constexpr size_t gjs_g_argument_get_array_length(
+    GITypeTag tag, GIArgument* arg) {
+    switch (tag) {
+        case GI_TYPE_TAG_INT8:
+            return gjs_arg_get<int8_t>(arg);
+        case GI_TYPE_TAG_UINT8:
+            return gjs_arg_get<uint8_t>(arg);
+        case GI_TYPE_TAG_INT16:
+            return gjs_arg_get<int16_t>(arg);
+        case GI_TYPE_TAG_UINT16:
+            return gjs_arg_get<uint16_t>(arg);
+        case GI_TYPE_TAG_INT32:
+            return gjs_arg_get<int32_t>(arg);
+        case GI_TYPE_TAG_UINT32:
+            return gjs_arg_get<uint32_t>(arg);
+        case GI_TYPE_TAG_INT64:
+            return gjs_arg_get<int64_t>(arg);
+        case GI_TYPE_TAG_UINT64:
+            return gjs_arg_get<uint64_t>(arg);
+        default:
+            g_assert_not_reached();
+    }
+}
diff -pruN 1.72.0-4/gi/function.cpp 1.73.1-1/gi/function.cpp
--- 1.72.0-4/gi/function.cpp	2022-03-19 18:04:36.065217300 +0000
+++ 1.73.1-1/gi/function.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -640,8 +640,13 @@ GjsCallbackTrampoline::GjsCallbackTrampo
 }
 
 GjsCallbackTrampoline::~GjsCallbackTrampoline() {
-    if (m_info && m_closure)
+    if (m_info && m_closure) {
+#if GI_CHECK_VERSION(1, 71, 0)
+        g_callable_info_destroy_closure(m_info, m_closure);
+#else
         g_callable_info_free_closure(m_info, m_closure);
+#endif
+    }
 }
 
 void GjsCallbackTrampoline::mark_forever() {
@@ -652,6 +657,23 @@ void GjsCallbackTrampoline::prepare_shut
     s_forever_closure_list.clear();
 }
 
+ffi_closure* GjsCallbackTrampoline::create_closure() {
+    auto callback = [](ffi_cif*, void* result, void** ffi_args, void* data) {
+        auto** args = reinterpret_cast<GIArgument**>(ffi_args);
+        g_assert(data && "Trampoline data is not set");
+        Gjs::Closure::Ptr trampoline(static_cast<GjsCallbackTrampoline*>(data),
+                                     GjsAutoTakeOwnership());
+
+        trampoline.as<GjsCallbackTrampoline>()->callback_closure(args, result);
+    };
+
+#if GI_CHECK_VERSION(1, 71, 0)
+    return g_callable_info_create_closure(m_info, &m_cif, callback, this);
+#else
+    return g_callable_info_prepare_closure(m_info, &m_cif, callback, this);
+#endif
+}
+
 bool GjsCallbackTrampoline::initialize() {
     g_assert(is_valid());
     g_assert(!m_closure);
@@ -720,20 +742,7 @@ bool GjsCallbackTrampoline::initialize()
         }
     }
 
-    m_closure = g_callable_info_prepare_closure(
-        m_info, &m_cif,
-        [](ffi_cif*, void* result, void** ffi_args, void* data) {
-            auto** args = reinterpret_cast<GIArgument**>(ffi_args);
-            g_assert(data && "Trampoline data is not set");
-            Gjs::Closure::Ptr trampoline(
-                static_cast<GjsCallbackTrampoline*>(data),
-                GjsAutoTakeOwnership());
-
-            trampoline.as<GjsCallbackTrampoline>()->callback_closure(args,
-                                                                     result);
-        },
-        this);
-
+    m_closure = create_closure();
     return true;
 }
 
diff -pruN 1.72.0-4/gi/function.h 1.73.1-1/gi/function.h
--- 1.72.0-4/gi/function.h	2022-03-19 18:04:36.065217300 +0000
+++ 1.73.1-1/gi/function.h	2022-07-10 19:35:20.000000000 +0000
@@ -49,13 +49,24 @@ struct GjsCallbackTrampoline : public Gj
 
     ~GjsCallbackTrampoline();
 
-    constexpr ffi_closure* closure() const { return m_closure; }
+    void* closure() const {
+#if GI_CHECK_VERSION(1, 71, 0)
+        return g_callable_info_get_closure_native_address(m_info, m_closure);
+#else
+        return m_closure;
+#endif
+    }
+
+    ffi_closure* get_ffi_closure() const {
+        return m_closure;
+    }
 
     void mark_forever();
 
     static void prepare_shutdown();
 
  private:
+    ffi_closure* create_closure();
     GJS_JSAPI_RETURN_CONVENTION bool initialize();
     GjsCallbackTrampoline(JSContext* cx, JS::HandleFunction function,
                           GICallableInfo* callable_info, GIScopeType scope,
diff -pruN 1.72.0-4/gi/object.cpp 1.73.1-1/gi/object.cpp
--- 1.72.0-4/gi/object.cpp	2022-03-19 18:04:36.067217400 +0000
+++ 1.73.1-1/gi/object.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -18,7 +18,6 @@
 #include <utility>      // for move
 #include <vector>
 
-#include <ffi.h>
 #include <girepository.h>
 #include <glib-object.h>
 #include <glib.h>
@@ -3004,7 +3003,7 @@ bool ObjectPrototype::hook_up_vfunc_impl
 
     if (field_info) {
         gint offset;
-        gpointer method_ptr;
+        void* method_ptr;
         GjsCallbackTrampoline *trampoline;
 
         offset = g_field_info_get_offset(field_info);
@@ -3032,7 +3031,7 @@ bool ObjectPrototype::hook_up_vfunc_impl
             trampoline, nullptr,
             [](void*, GClosure* closure) { g_closure_unref(closure); });
 
-        *reinterpret_cast<ffi_closure**>(method_ptr) = trampoline->closure();
+        *reinterpret_cast<void**>(method_ptr) = trampoline->closure();
     }
 
     return true;
diff -pruN 1.72.0-4/gi/value.cpp 1.73.1-1/gi/value.cpp
--- 1.72.0-4/gi/value.cpp	2022-03-19 18:04:36.068217300 +0000
+++ 1.73.1-1/gi/value.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -479,7 +479,7 @@ gjs_value_to_g_value_internal(JSContext
             return throw_expect_type(context, value, "integer");
         }
     } else if (gtype == G_TYPE_INT64) {
-        gint64 i;
+        int64_t i;
         if (Gjs::js_value_to_c_checked<int64_t>(context, value, &i,
                                                 &out_of_range) &&
             !out_of_range) {
@@ -512,7 +512,7 @@ gjs_value_to_g_value_internal(JSContext
             return throw_expect_type(context, value, "unsigned integer");
         }
     } else if (gtype == G_TYPE_UINT64) {
-        guint64 i;
+        uint64_t i;
         if (Gjs::js_value_to_c_checked<uint64_t>(context, value, &i,
                                                  &out_of_range) &&
             !out_of_range) {
diff -pruN 1.72.0-4/.gitignore 1.73.1-1/.gitignore
--- 1.72.0-4/.gitignore	1970-01-01 00:00:00.000000000 +0000
+++ 1.73.1-1/.gitignore	2022-07-10 19:35:20.000000000 +0000
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+# SPDX-FileCopyrightText: 2020 Philip Chimento <philip.chimento@gmail.com>
+/tools/node_modules
diff -pruN 1.72.0-4/.gitlab-ci.yml 1.73.1-1/.gitlab-ci.yml
--- 1.72.0-4/.gitlab-ci.yml	2022-03-19 18:04:36.053217400 +0000
+++ 1.73.1-1/.gitlab-ci.yml	2022-07-10 19:35:20.000000000 +0000
@@ -71,7 +71,7 @@ build_recommended:
   stage: source_check
   image: registry.gitlab.gnome.org/gnome/gjs:job-1740076_fedora.mozjs91-debug  # pinned on purpose
   variables:
-    TEST_OPTS: --verbose --no-stdsplit --print-errorlogs
+    TEST_OPTS: --verbose --no-stdsplit --print-errorlogs --setup=verbose
   except:
     - schedules
 
@@ -83,7 +83,7 @@ sanitizer_gcc:
   image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug
   variables:
     CONFIG_OPTS: -Db_sanitize=address,undefined
-    TEST_OPTS: --timeout-multiplier=3
+    TEST_OPTS: --timeout-multiplier=3 --setup=verbose
   except:
     - schedules
 
@@ -97,7 +97,7 @@ sanitizer_thread_gcc:
   image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug
   variables:
     CONFIG_OPTS: -Db_sanitize=thread
-    TEST_OPTS: --timeout-multiplier=3
+    TEST_OPTS: --timeout-multiplier=3 --setup=verbose
   except:
     - schedules
 
@@ -128,6 +128,7 @@ build_minimal:
     CONFIG_OPTS: >-
       -Dbuildtype=release
       -Dcairo=disabled -Dreadline=disabled -Dprofiler=disabled
+    TEST_OPTS: --setup=verbose
   except:
     - schedules
 
@@ -142,6 +143,7 @@ build_unity:
     CONFIG_OPTS: >-
       -Dprofiler=disabled
       --unity on --unity-size=10000
+    TEST_OPTS: --setup=verbose
   except:
     - schedules
 
@@ -313,7 +315,7 @@ sanitizer_clang:
     CC: clang
     CXX: clang++
     CONFIG_OPTS: -Db_sanitize=address,undefined -Db_lundef=false
-    TEST_OPTS: --timeout-multiplier=3
+    TEST_OPTS: --timeout-multiplier=3 --setup=verbose
   when: manual
   except:
     - schedules
diff -pruN 1.72.0-4/gjs/gjs_pch.hh 1.73.1-1/gjs/gjs_pch.hh
--- 1.72.0-4/gjs/gjs_pch.hh	2022-03-19 18:04:36.070217400 +0000
+++ 1.73.1-1/gjs/gjs_pch.hh	2022-07-10 19:35:20.000000000 +0000
@@ -28,7 +28,6 @@
 #include <vector>
 
 #include <assert.h>
-#include <ctype.h>
 #include <errno.h>
 #include <ffi.h>
 #include <gio/gio.h>
diff -pruN 1.72.0-4/gjs/global.h 1.73.1-1/gjs/global.h
--- 1.72.0-4/gjs/global.h	2022-03-19 18:04:36.070217400 +0000
+++ 1.73.1-1/gjs/global.h	2022-07-10 19:35:20.000000000 +0000
@@ -42,6 +42,8 @@ enum class GjsGlobalSlot : uint32_t {
     // Stores the module registry (a Map object)
     MODULE_REGISTRY,
     NATIVE_REGISTRY,
+    // prettyPrint() function defined in JS but used internally in C++
+    PRETTY_PRINT_FUNC,
     PROTOTYPE_gtype,
     PROTOTYPE_importer,
     PROTOTYPE_function,
diff -pruN 1.72.0-4/gjs/jsapi-util.cpp 1.73.1-1/gjs/jsapi-util.cpp
--- 1.72.0-4/gjs/jsapi-util.cpp	2022-03-19 18:04:36.072217500 +0000
+++ 1.73.1-1/gjs/jsapi-util.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -243,121 +243,6 @@ JSObject* gjs_define_string_array(JSCont
     return array;
 }
 
-/**
- * gjs_string_readable:
- *
- * Return a string that can be read back by gjs-console; for
- * JS strings that contain valid Unicode, we return a UTF-8 formatted
- * string.  Otherwise, we return one where non-ASCII-printable bytes
- * are \x escaped.
- *
- */
-[[nodiscard]] static std::string gjs_string_readable(JSContext* context,
-                                                     JS::HandleString string) {
-    std::string buf(1, '"');
-
-    JS::UniqueChars chars(JS_EncodeStringToUTF8(context, string));
-    if (!chars) {
-        /* I'm not sure this code will actually ever be reached except in the
-         * case of OOM, since JS_EncodeStringToUTF8() seems to happily output
-         * non-valid UTF-8 bytes. However, let's leave this in, since
-         * SpiderMonkey may decide to do validation in the future. */
-
-        /* Find out size of buffer to allocate, not counting 0-terminator */
-        size_t len = JS_PutEscapedString(context, NULL, 0, string, '"');
-        char *escaped = g_new(char, len + 1);
-
-        JS_PutEscapedString(context, escaped, len, string, '"');
-        buf += escaped;
-        g_free(escaped);
-    } else {
-        buf += chars.get();
-    }
-
-    return buf + '"';
-}
-
-[[nodiscard]] static std::string _gjs_g_utf8_make_valid(const char* name) {
-    const char *remainder, *invalid;
-    int remaining_bytes, valid_bytes;
-
-    g_return_val_if_fail (name != NULL, "");
-
-    remainder = name;
-    remaining_bytes = strlen (name);
-
-    if (remaining_bytes == 0)
-        return std::string(name);
-
-    std::string buf;
-    buf.reserve(remaining_bytes);
-    while (remaining_bytes != 0) {
-        if (g_utf8_validate (remainder, remaining_bytes, &invalid))
-            break;
-        valid_bytes = invalid - remainder;
-
-        buf.append(remainder, valid_bytes);
-        /* append U+FFFD REPLACEMENT CHARACTER */
-        buf += "\357\277\275";
-
-        remaining_bytes -= valid_bytes + 1;
-        remainder = invalid + 1;
-    }
-
-    buf += remainder;
-
-    g_assert(g_utf8_validate(buf.c_str(), -1, nullptr));
-
-    return buf;
-}
-
-/**
- * gjs_value_debug_string:
- * @context:
- * @value: Any JavaScript value
- *
- * Returns: A UTF-8 encoded string describing @value
- */
-std::string gjs_value_debug_string(JSContext* context, JS::HandleValue value) {
-    /* Special case debug strings for strings */
-    if (value.isString()) {
-        JS::RootedString str(context, value.toString());
-        return gjs_string_readable(context, str);
-    }
-
-    JS::RootedString str(context, JS::ToString(context, value));
-
-    if (!str) {
-        JS_ClearPendingException(context);
-        str = JS_ValueToSource(context, value);
-    }
-
-    if (!str) {
-        if (value.isObject()) {
-            /* Specifically the Call object (see jsfun.c in spidermonkey)
-             * does not have a toString; there may be others also.
-             */
-            const JSClass* klass = JS::GetClass(&value.toObject());
-            if (klass != NULL) {
-                str = JS_NewStringCopyZ(context, klass->name);
-                JS_ClearPendingException(context);
-                if (!str)
-                    return "[out of memory copying class name]";
-            } else {
-                gjs_log_exception(context);
-                return "[unknown object]";
-            }
-        } else {
-            return "[unknown non-object]";
-        }
-    }
-
-    g_assert(str);
-
-    JS::UniqueChars bytes = JS_EncodeStringToUTF8(context, str);
-    return _gjs_g_utf8_make_valid(bytes.get());
-}
-
 // Helper function: perform ToString on an exception (which may not even be an
 // object), except if it is an InternalError, which would throw in ToString.
 GJS_JSAPI_RETURN_CONVENTION
diff -pruN 1.72.0-4/gjs/jsapi-util.h 1.73.1-1/gjs/jsapi-util.h
--- 1.72.0-4/gjs/jsapi-util.h	2022-03-19 18:04:36.072217500 +0000
+++ 1.73.1-1/gjs/jsapi-util.h	2022-07-10 19:35:20.000000000 +0000
@@ -450,9 +450,6 @@ bool gjs_log_exception_uncaught(JSContex
 void gjs_log_exception_full(JSContext* cx, JS::HandleValue exc,
                             JS::HandleString message, GLogLevelFlags level);
 
-[[nodiscard]] std::string gjs_value_debug_string(JSContext* cx,
-                                                 JS::HandleValue value);
-
 void gjs_warning_reporter(JSContext*, JSErrorReport* report);
 
 GJS_JSAPI_RETURN_CONVENTION
diff -pruN 1.72.0-4/gjs/jsapi-util-string.cpp 1.73.1-1/gjs/jsapi-util-string.cpp
--- 1.72.0-4/gjs/jsapi-util-string.cpp	2022-03-19 18:04:36.071217300 +0000
+++ 1.73.1-1/gjs/jsapi-util-string.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -4,7 +4,6 @@
 
 #include <config.h>
 
-#include <ctype.h>  // for toupper
 #include <stdint.h>
 #include <string.h>     // for size_t, strlen
 #include <sys/types.h>  // for ssize_t
@@ -59,7 +58,7 @@ GjsAutoChar gjs_hyphen_to_camel(const ch
         if (*input_iter == '-') {
             uppercase_next = true;
         } else if (uppercase_next) {
-            *output_iter++ = toupper(*input_iter);
+            *output_iter++ = g_ascii_toupper(*input_iter);
             uppercase_next = false;
         } else {
             *output_iter++ = *input_iter;
diff -pruN 1.72.0-4/gjs/profiler.cpp 1.73.1-1/gjs/profiler.cpp
--- 1.72.0-4/gjs/profiler.cpp	2022-03-19 18:04:36.073217400 +0000
+++ 1.73.1-1/gjs/profiler.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -786,8 +786,8 @@ gjs_profiler_set_filename(GjsProfiler *s
     self->filename = g_strdup(filename);
 }
 
-void _gjs_profiler_add_mark(GjsProfiler* self, gint64 time_nsec,
-                            gint64 duration_nsec, const char* group,
+void _gjs_profiler_add_mark(GjsProfiler* self, int64_t time_nsec,
+                            int64_t duration_nsec, const char* group,
                             const char* name, const char* message) {
     g_return_if_fail(self);
     g_return_if_fail(group);
diff -pruN 1.72.0-4/installed-tests/js/minijasmine.js 1.73.1-1/installed-tests/js/minijasmine.js
--- 1.72.0-4/installed-tests/js/minijasmine.js	2022-03-19 18:04:36.078217300 +0000
+++ 1.73.1-1/installed-tests/js/minijasmine.js	2022-07-10 19:35:20.000000000 +0000
@@ -4,11 +4,6 @@
 
 const GLib = imports.gi.GLib;
 
-function _removeNewlines(str) {
-    let allNewlines = /\n/g;
-    return str.replace(allNewlines, '\\n');
-}
-
 function _filterStack(stack) {
     if (!stack)
         return 'No stack';
@@ -27,6 +22,7 @@ globalThis._jasmineEnv.configure({
 });
 globalThis._jasmineMain = GLib.MainLoop.new(null, false);
 globalThis._jasmineRetval = 0;
+globalThis._jasmineErrorsOutput = [];
 
 // Install Jasmine API on the global object
 let jasmineInterface = jasmineRequire.interface(jasmineCore, globalThis._jasmineEnv);
@@ -78,7 +74,8 @@ class TapReporter {
             tapReport = 'ok';
         }
         tapReport += ` ${this._specCount} ${result.fullName}`;
-        if (result.status === 'pending' || result.status === 'disabled') {
+        if (result.status === 'pending' || result.status === 'disabled' ||
+            result.status === 'excluded') {
             let reason = result.pendingReason || result.status;
             tapReport += ` # SKIP ${reason}`;
         }
@@ -87,10 +84,22 @@ class TapReporter {
         // Print additional diagnostic info on failure
         if (result.status === 'failed' && result.failedExpectations) {
             result.failedExpectations.forEach(failedExpectation => {
-                print('# Message:', _removeNewlines(failedExpectation.message));
-                print('# Stack:');
+                const output = [];
+                const messageLines = failedExpectation.message.split('\n');
+                output.push(`Message: ${messageLines.shift()}`);
+                output.push(...messageLines.map(str => `  ${str}`));
+                output.push('Stack:');
                 let stackTrace = _filterStack(failedExpectation.stack).trim();
-                print(stackTrace.split('\n').map(str => `#   ${str}`).join('\n'));
+                output.push(...stackTrace.split('\n').map(str => `  ${str}`));
+
+                if (globalThis._jasmineErrorsOutput.length) {
+                    globalThis._jasmineErrorsOutput.push(
+                        Array(GLib.getenv('COLUMNS') || 80).fill('―').join(''));
+                }
+
+                globalThis._jasmineErrorsOutput.push(`Test: ${result.fullName}`);
+                globalThis._jasmineErrorsOutput.push(...output);
+                print(output.map(l => `# ${l}`).join('\n'));
             });
         }
     }
diff -pruN 1.72.0-4/installed-tests/js/testGDBus.js 1.73.1-1/installed-tests/js/testGDBus.js
--- 1.72.0-4/installed-tests/js/testGDBus.js	2022-03-19 18:04:36.080217400 +0000
+++ 1.73.1-1/installed-tests/js/testGDBus.js	2022-07-10 19:35:20.000000000 +0000
@@ -330,6 +330,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can call a method with async/await', async function () {
+        const [{hello}] = await proxy.frobateStuffAsync({});
+        expect(hello.deepUnpack()).toEqual('world');
+    });
+
     it('can call a remote method when not using makeProxyWrapper', function () {
         let info = Gio.DBusNodeInfo.new_for_xml(TestIface);
         let iface = info.interfaces[0];
@@ -368,6 +373,13 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can handle an exception thrown by a method with async/await', async function () {
+        GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+            'JS ERROR: Exception in method call: alwaysThrowException: *');
+
+        await expectAsync(proxy.alwaysThrowExceptionAsync({})).toBeRejected();
+    });
+
     it('can still destructure the return value when an exception is thrown', function () {
         GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
             'JS ERROR: Exception in method call: alwaysThrowException: *');
@@ -398,6 +410,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('throws an exception when trying to call an async method that does not exist', async function () {
+        delete Test.prototype.thisDoesNotExist;
+        await expectAsync(proxy.thisDoesNotExistAsync()).toBeRejected();
+    });
+
     it('can pass a parameter to a remote method that is not a JSON object', function () {
         proxy.nonJsonFrobateStuffRemote(42, ([result], excp) => {
             expect(result).toEqual('42 it is!');
@@ -407,6 +424,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can pass a parameter to a method with async/await that is not a JSON object', async function () {
+        const [result] = await proxy.nonJsonFrobateStuffAsync(1);
+        expect(result).toEqual('Oops');
+    });
+
     it('can call a remote method with no in parameter', function () {
         proxy.noInParameterRemote(([result], excp) => {
             expect(result).toEqual('Yes!');
@@ -416,6 +438,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can call an async/await method with no in parameter', async function () {
+        const [result] = await proxy.noInParameterAsync();
+        expect(result).toEqual('Yes!');
+    });
+
     it('can call a remote method with multiple in parameters', function () {
         proxy.multipleInArgsRemote(1, 2, 3, 4, 5, ([result], excp) => {
             expect(result).toEqual('1 2 3 4 5');
@@ -425,6 +452,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can call an async/await method with multiple in parameters', async function () {
+        const [result] = await proxy.multipleInArgsAsync(1, 2, 3, 4, 5);
+        expect(result).toEqual('1 2 3 4 5');
+    });
+
     it('can call a remote method with no return value', function () {
         proxy.noReturnValueRemote(([result], excp) => {
             expect(result).not.toBeDefined();
@@ -434,6 +466,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can call an async/await method with no return value', async function () {
+        const [result] = await proxy.noReturnValueAsync();
+        expect(result).not.toBeDefined();
+    });
+
     it('can emit a DBus signal', function () {
         let handler = jasmine.createSpy('signalFoo');
         let id = proxy.connectSignal('signalFoo', handler);
@@ -450,6 +487,18 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can emit a DBus signal with async/await', async function () {
+        const handler = jasmine.createSpy('signalFoo');
+        const id = proxy.connectSignal('signalFoo', handler);
+        handler.and.callFake(() => proxy.disconnectSignal(id));
+
+        const [result] = await proxy.emitSignalAsync();
+        expect(result).not.toBeDefined();
+        expect(handler).toHaveBeenCalledTimes(1);
+        expect(handler).toHaveBeenCalledWith(jasmine.anything(),
+            jasmine.anything(), ['foobar']);
+    });
+
     it('can call a remote method with multiple return values', function () {
         proxy.multipleOutValuesRemote(function (result, excp) {
             expect(result).toEqual(['Hello', 'World', '!']);
@@ -459,6 +508,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can call an async/await method with multiple return values', async function () {
+        const results = await proxy.multipleOutValuesAsync();
+        expect(results).toEqual(['Hello', 'World', '!']);
+    });
+
     it('does not coalesce one array into the array of return values', function () {
         proxy.oneArrayOutRemote(([result], excp) => {
             expect(result).toEqual(['Hello', 'World', '!']);
@@ -468,6 +522,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('does not coalesce one array into the array of return values with async/await', async function () {
+        const [result] = await proxy.oneArrayOutAsync();
+        expect(result).toEqual(['Hello', 'World', '!']);
+    });
+
     it('does not coalesce an array of arrays into the array of return values', function () {
         proxy.arrayOfArrayOutRemote(([[a1, a2]], excp) => {
             expect(a1).toEqual(['Hello', 'World']);
@@ -478,6 +537,12 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('does not coalesce an array of arrays into the array of return values with async/await', async function () {
+        const [[a1, a2]] = await proxy.arrayOfArrayOutAsync();
+        expect(a1).toEqual(['Hello', 'World']);
+        expect(a2).toEqual(['World', 'Hello']);
+    });
+
     it('can return multiple arrays from a remote method', function () {
         proxy.multipleArrayOutRemote(([a1, a2], excp) => {
             expect(a1).toEqual(['Hello', 'World']);
@@ -488,6 +553,12 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can return multiple arrays from an async/await method', async function () {
+        const [a1, a2] = await proxy.multipleArrayOutAsync();
+        expect(a1).toEqual(['Hello', 'World']);
+        expect(a2).toEqual(['World', 'Hello']);
+    });
+
     it('handles a bad signature by throwing an exception', function () {
         proxy.arrayOutBadSigRemote(function (result, excp) {
             expect(excp).not.toBeNull();
@@ -496,6 +567,10 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('handles a bad signature in async/await by rejecting the promise', async function () {
+        await expectAsync(proxy.arrayOutBadSigAsync()).toBeRejected();
+    });
+
     it('can call a remote method that is implemented asynchronously', function () {
         let someString = 'Hello world!';
         let someInt = 42;
@@ -509,6 +584,14 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can call an async/await method that is implemented asynchronously', async function () {
+        const someString = 'Hello world!';
+        const someInt = 42;
+
+        const results = await proxy.echoAsync(someString, someInt);
+        expect(results).toEqual([someString, someInt]);
+    });
+
     it('can send and receive bytes from a remote method', function () {
         let someBytes = [0, 63, 234];
         someBytes.forEach(b => {
@@ -522,6 +605,14 @@ describe('Exported DBus object', functio
         });
     });
 
+    it('can send and receive bytes from an async/await method', async function () {
+        let someBytes = [0, 63, 234];
+        await Promise.allSettled(someBytes.map(async b => {
+            const [byte] = await proxy.byteEchoAsync(b);
+            expect(byte).toEqual(b);
+        }));
+    });
+
     it('can call a remote method that returns an array of structs', function () {
         proxy.structArrayRemote(([result], excp) => {
             expect(excp).toBeNull();
@@ -531,6 +622,11 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can call an async/await method that returns an array of structs', async function () {
+        const [result] = await proxy.structArrayAsync();
+        expect(result).toEqual([[128, 123456], [42, 654321]]);
+    });
+
     it('can send and receive dicts from a remote method', function () {
         let someDict = {
             aDouble: new GLib.Variant('d', 10),
@@ -558,6 +654,19 @@ describe('Exported DBus object', functio
         loop.run();
     });
 
+    it('can send and receive dicts from an async/await method', async function () {
+        // See notes in test above
+        const [result] = await proxy.dictEchoAsync({
+            aDouble: new GLib.Variant('d', 10),
+            anInteger: new GLib.Variant('i', 10.5),
+            aDoubleBeforeAndAfter: new GLib.Variant('d', 10.5),
+        });
+        expect(result).not.toBeNull();
+        expect(result['anInteger'].deepUnpack()).toEqual(10);
+        expect(result['aDoubleBeforeAndAfter'].deepUnpack()).toEqual(10.5);
+        expect(result['aDouble'].deepUnpack()).toBe(10.0);
+    });
+
     it('can call a remote method with a Unix FD', function (done) {
         const expectedBytes = ByteArray.fromString('some bytes');
         const fd = GjsTestTools.open_bytes(expectedBytes);
@@ -570,6 +679,16 @@ describe('Exported DBus object', functio
         });
     });
 
+    it('can call an async/await method with a Unix FD', async function () {
+        const encoder = new TextEncoder();
+        const expectedBytes = encoder.encode('some bytes');
+        const fd = GjsTestTools.open_bytes(expectedBytes);
+        const fdList = Gio.UnixFDList.new_from_array([fd]);
+        const [bytes, outFdList] = await proxy.fdInAsync(0, fdList);
+        expect(outFdList).not.toBeDefined();
+        expect(bytes).toEqual(expectedBytes);
+    });
+
     it('can call an asynchronously implemented remote method with a Unix FD', function (done) {
         const expectedBytes = ByteArray.fromString('some bytes');
         const fd = GjsTestTools.open_bytes(expectedBytes);
@@ -582,6 +701,16 @@ describe('Exported DBus object', functio
         });
     });
 
+    it('can call an asynchronously implemented async/await method with a Unix FD', async function () {
+        const encoder = new TextEncoder();
+        const expectedBytes = encoder.encode('some bytes');
+        const fd = GjsTestTools.open_bytes(expectedBytes);
+        const fdList = Gio.UnixFDList.new_from_array([fd]);
+        const [bytes, outFdList] = await proxy.fdIn2Async(0, fdList);
+        expect(outFdList).not.toBeDefined();
+        expect(bytes).toEqual(expectedBytes);
+    });
+
     function readBytesFromFdSync(fd) {
         const stream = new Gio.UnixInputStream({fd, closeFd: true});
         const bytes = stream.read_bytes(4096, null);
@@ -598,6 +727,14 @@ describe('Exported DBus object', functio
         });
     });
 
+    it('can call an async/await method that returns a Unix FD', async function () {
+        const encoder = new TextEncoder();
+        const expectedBytes = encoder.encode('some bytes');
+        const [fdIndex, outFdList] = await proxy.fdOutAsync(expectedBytes);
+        const bytes = readBytesFromFdSync(outFdList.get(fdIndex));
+        expect(bytes).toEqual(expectedBytes);
+    });
+
     it('can call an asynchronously implemented remote method that returns a Unix FD', function (done) {
         const expectedBytes = ByteArray.fromString('some bytes');
         proxy.fdOut2Remote(expectedBytes, ([fdIndex], exc, outFdList) => {
@@ -608,15 +745,32 @@ describe('Exported DBus object', functio
         });
     });
 
+    it('can call an asynchronously implemented asyc/await method that returns a Unix FD', async function () {
+        const encoder = new TextEncoder();
+        const expectedBytes = encoder.encode('some bytes');
+        const [fdIndex, outFdList] = await proxy.fdOut2Async(expectedBytes);
+        const bytes = readBytesFromFdSync(outFdList.get(fdIndex));
+        expect(bytes).toEqual(expectedBytes);
+    });
+
     it('throws an exception when not passing a Gio.UnixFDList to a method that requires one', function () {
         expect(() => proxy.fdInRemote(0, () => {})).toThrow();
     });
 
+    it('rejects the promise when not passing a Gio.UnixFDList to an async method that requires one', async function () {
+        await expectAsync(proxy.fdInAsync(0)).toBeRejected();
+    });
+
     it('throws an exception when passing a handle out of range of a Gio.UnixFDList', function () {
         const fdList = new Gio.UnixFDList();
         expect(() => proxy.fdInRemote(0, fdList, () => {})).toThrow();
     });
 
+    it('rejects the promise when async passing a handle out of range of a Gio.UnixFDList', async function () {
+        const fdList = new Gio.UnixFDList();
+        await expectAsync(proxy.fdInAsync(0, fdList)).toBeRejected();
+    });
+
     it('Has defined properties', function () {
         expect(proxy.hasOwnProperty('PropReadWrite')).toBeTruthy();
         expect(proxy.hasOwnProperty('PropReadOnly')).toBeTruthy();
diff -pruN 1.72.0-4/installed-tests/js/testGio.js 1.73.1-1/installed-tests/js/testGio.js
--- 1.72.0-4/installed-tests/js/testGio.js	2022-03-19 18:04:36.081217300 +0000
+++ 1.73.1-1/installed-tests/js/testGio.js	2022-07-10 19:35:20.000000000 +0000
@@ -197,3 +197,96 @@ describe('Gio.Settings overrides', funct
         });
     });
 });
+
+describe('Gio.add_action_entries override', function () {
+    it('registers each entry as an action', function ()  {
+        const app = new Gio.Application();
+
+        const entries = [
+            {
+                name: 'foo',
+                parameter_type: 's',
+            },
+            {
+                name: 'bar',
+                state: 'false',
+            },
+        ];
+
+        app.add_action_entries(entries);
+
+        expect(app.lookup_action('foo').name).toEqual(entries[0].name);
+        expect(app.lookup_action('foo').parameter_type.dup_string()).toEqual(entries[0].parameter_type);
+
+        expect(app.lookup_action('bar').name).toEqual(entries[1].name);
+        expect(app.lookup_action('bar').state.print(true)).toEqual(entries[1].state);
+    });
+
+    it('connects and binds the activate handler', function (done) {
+        const app = new Gio.Application();
+        let action;
+
+        const entries = [
+            {
+                name: 'foo',
+                parameter_type: 's',
+                activate() {
+                    expect(this).toBe(action);
+                    done();
+                },
+            },
+        ];
+
+        app.add_action_entries(entries);
+        action = app.lookup_action('foo');
+
+        action.activate(new GLib.Variant('s', 'hello'));
+    });
+
+    it('connects and binds the change_state handler', function (done) {
+        const app = new Gio.Application();
+        let action;
+
+        const entries = [
+            {
+                name: 'bar',
+                state: 'false',
+                change_state() {
+                    expect(this).toBe(action);
+                    done();
+                },
+            },
+        ];
+
+        app.add_action_entries(entries);
+        action = app.lookup_action('bar');
+
+        action.change_state(new GLib.Variant('b', 'true'));
+    });
+
+    it('throw an error if the parameter_type is invalid', function () {
+        const app = new Gio.Application();
+
+        const entries = [
+            {
+                name: 'foo',
+                parameter_type: '(((',
+            },
+        ];
+
+        expect(() => app.add_action_entries(entries)).toThrow();
+    });
+
+    it('throw an error if the state is invalid', function () {
+        const app = new Gio.Application();
+
+        const entries = [
+            {
+                name: 'bar',
+                state: 'foo',
+            },
+        ];
+
+        expect(() => app.add_action_entries(entries)).toThrow();
+    });
+});
diff -pruN 1.72.0-4/installed-tests/js/testGObjectClass.js 1.73.1-1/installed-tests/js/testGObjectClass.js
--- 1.72.0-4/installed-tests/js/testGObjectClass.js	2022-03-19 18:04:36.080217400 +0000
+++ 1.73.1-1/installed-tests/js/testGObjectClass.js	2022-07-10 19:35:20.000000000 +0000
@@ -1183,6 +1183,11 @@ describe('Auto accessor generation', fun
                 'Construct-only property with a setter method',
                 GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
                 0, 100, 80),
+            'construct-only-was-invalid-in-turkish': GObject.ParamSpec.int(
+                'construct-only-was-invalid-in-turkish', 'Camel name in Turkish',
+                'Camel-cased property that was wrongly transformed in Turkish',
+                GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+                0, 100, 55),
             'snake-name': GObject.ParamSpec.int('snake-name', 'Snake name',
                 'Snake-cased property', GObject.ParamFlags.READWRITE, 0, 100, 36),
             'camel-name': GObject.ParamSpec.int('camel-name', 'Camel name',
@@ -1302,6 +1307,21 @@ describe('Auto accessor generation', fun
         expect(a._constructOnlySetterCalled).toEqual(1);
     });
 
+    it('set properties at construct time with locale', function () {
+        const {gettext: Gettext} = imports;
+        const prevLocale = Gettext.setlocale(Gettext.LocaleCategory.ALL, null);
+
+        Gettext.setlocale(Gettext.LocaleCategory.ALL, 'tr_TR');
+        a = new AutoAccessors({
+            'construct-only-was-invalid-in-turkish': 35,
+        });
+        Gettext.setlocale(Gettext.LocaleCategory.ALL, prevLocale);
+
+        expect(a.constructOnlyWasInvalidInTurkish).toEqual(35);
+        expect(a.construct_only_was_invalid_in_turkish).toEqual(35);
+        expect(a['construct-only-was-invalid-in-turkish']).toEqual(35);
+    });
+
     it('notify when the property changes', function () {
         const notify = jasmine.createSpy('notify');
         a.connect('notify::simple', notify);
diff -pruN 1.72.0-4/installed-tests/js/testPrint.js 1.73.1-1/installed-tests/js/testPrint.js
--- 1.72.0-4/installed-tests/js/testPrint.js	2022-03-19 18:04:36.082217500 +0000
+++ 1.73.1-1/installed-tests/js/testPrint.js	2022-07-10 19:35:20.000000000 +0000
@@ -1,5 +1,11 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2020 Philip Chimento <philip.chimento@gmail.com>
+// SPDX-FileCopyrightText: 2022 Nasah Kuma <nasahnash19@gmail.com>
+
+imports.gi.versions.Gdk = '3.0';
+const Gdk = imports.gi.Gdk;
+const {getPrettyPrintFunction} = imports._print;
+let prettyPrint = getPrettyPrintFunction(globalThis);
 
 describe('print', function () {
     it('can be spied upon', function () {
@@ -32,3 +38,118 @@ describe('logError', function () {
         expect(logError).toHaveBeenCalledWith('foo', 'bar');
     });
 });
+
+describe('prettyPrint', function () {
+    it('property value primitive', function () {
+        expect(
+            prettyPrint({greeting: 'hi'})
+        ).toBe('{ greeting: "hi" }');
+    });
+
+    it('property value is object reference', function () {
+        let obj = {a: 5};
+        obj.b = obj;
+        expect(
+            prettyPrint(obj)
+        ).toBe('{ a: 5, b: [Circular] }');
+    });
+
+    it('more than one property', function () {
+        expect(
+            prettyPrint({a: 1, b: 2, c: 3})
+        ).toBe('{ a: 1, b: 2, c: 3 }');
+    });
+
+    it('add property value after property value object reference', function () {
+        let obj = {a: 5};
+        obj.b = obj;
+        obj.c = 4;
+        expect(
+            prettyPrint(obj)
+        ).toBe('{ a: 5, b: [Circular], c: 4 }');
+    });
+
+    it('array', function () {
+        expect(
+            prettyPrint([1, 2, 3, 4, 5])
+        ).toBe('[1, 2, 3, 4, 5]');
+    });
+
+    it('property value array', function () {
+        expect(
+            prettyPrint({arr: [1, 2, 3, 4, 5]})
+        ).toBe('{ arr: [1, 2, 3, 4, 5] }');
+    });
+
+    it('array reference is the only array element', function () {
+        let arr = [];
+        arr.push(arr);
+        expect(
+            prettyPrint(arr)
+        ).toBe('[[Circular]]');
+    });
+
+    it('array reference is one of multiple array elements', function () {
+        let arr = [];
+        arr.push(4);
+        arr.push(arr);
+        arr.push(5);
+        expect(
+            prettyPrint(arr)
+        ).toBe('[4, [Circular], 5]');
+    });
+
+    it('nested array', function () {
+        expect(
+            prettyPrint([1, 2, [3, 4], 5])
+        ).toBe('[1, 2, [3, 4], 5]');
+    });
+
+    it('property value nested array', function () {
+        expect(
+            prettyPrint({arr: [1, 2, [3, 4], 5]})
+        ).toBe('{ arr: [1, 2, [3, 4], 5] }');
+    });
+
+    it('function', function () {
+        expect(
+            prettyPrint(function sum(a, b) {
+                return a + b;
+            })
+        ).toBe('[ Function: sum ]');
+    });
+
+    it('property value function', function () {
+        expect(
+            prettyPrint({
+                sum: function sum(a, b) {
+                    return a + b;
+                },
+            })
+        ).toBe('{ sum: [ Function: sum ] }');
+    });
+
+    it('date', function () {
+        expect(
+            prettyPrint(new Date(Date.UTC(2018, 11, 24, 10, 33, 30)))
+        ).toBe('2018-12-24T10:33:30.000Z');
+    });
+
+    it('property value date', function () {
+        expect(
+            prettyPrint({date: new Date(Date.UTC(2018, 11, 24, 10, 33, 30))})
+        ).toBe('{ date: 2018-12-24T10:33:30.000Z }');
+    });
+
+    it('toString is overridden on object', function () {
+        expect(
+            prettyPrint(new Gdk.Rectangle())
+        ).toMatch(/\[boxed instance wrapper GIName:.*\]/);
+    });
+
+    it('string tag supplied', function () {
+        expect(
+            prettyPrint(Gdk)
+        ).toMatch('[object GIRepositoryNamespace]');
+    });
+});
diff -pruN 1.72.0-4/installed-tests/minijasmine.cpp 1.73.1-1/installed-tests/minijasmine.cpp
--- 1.72.0-4/installed-tests/minijasmine.cpp	2022-03-19 18:04:36.083217400 +0000
+++ 1.73.1-1/installed-tests/minijasmine.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -104,8 +104,18 @@ main(int argc, char **argv)
     if (!success)
         bail_out(cx, error->message);
 
-    if (code != 0)
-        g_print("# Test script failed; see test log for assertions\n");
+    if (code != 0) {
+        success = gjs_context_eval(cx, R"js(
+            printerr(globalThis._jasmineErrorsOutput.join('\n'));
+        )js",
+                                   -1, "<jasmine-error-logs>", &code, &error);
+
+        if (!success)
+            bail_out(cx, error->message);
+
+        if (code != 0)
+            g_print("# Test script failed; see test log for assertions\n");
+    }
 
     if (coverage) {
         gjs_coverage_write_statistics(coverage);
diff -pruN 1.72.0-4/libgjs-private/gjs-util.c 1.73.1-1/libgjs-private/gjs-util.c
--- 1.72.0-4/libgjs-private/gjs-util.c	2022-03-19 18:04:36.084217300 +0000
+++ 1.73.1-1/libgjs-private/gjs-util.c	2022-07-10 19:35:20.000000000 +0000
@@ -318,11 +318,19 @@ void gjs_gtk_custom_sorter_set_sort_func
 
 static void* log_writer_user_data = NULL;
 static GDestroyNotify log_writer_user_data_free = NULL;
+static GThread* log_writer_thread = NULL;
 
 static GLogWriterOutput gjs_log_writer_func_wrapper(GLogLevelFlags log_level,
                                                     const GLogField* fields,
                                                     size_t n_fields,
                                                     void* user_data) {
+    g_assert(log_writer_thread);
+
+    // If the wrapper is called from a thread other than the one that set it,
+    // return unhandled so the fallback logger is used.
+    if (g_thread_self() != log_writer_thread)
+        return g_log_writer_default(log_level, fields, n_fields, NULL);
+
     GjsGLogWriterFunc func = (GjsGLogWriterFunc)user_data;
     GVariantDict dict;
     g_variant_dict_init(&dict, NULL);
@@ -363,6 +371,12 @@ static GLogWriterOutput gjs_log_writer_f
         func(log_level, string_fields, log_writer_user_data);
 
     g_variant_unref(string_fields);
+
+    // If the function did not handle the log, fallback to the default
+    // handler.
+    if (output == G_LOG_WRITER_UNHANDLED)
+        return g_log_writer_default(log_level, fields, n_fields, NULL);
+
     return output;
 }
 
@@ -379,6 +393,7 @@ void gjs_log_set_writer_default() {
     g_log_set_writer_func(g_log_writer_default, NULL, NULL);
     log_writer_user_data_free = NULL;
     log_writer_user_data = NULL;
+    log_writer_thread = NULL;
 }
 
 /**
@@ -395,6 +410,7 @@ void gjs_log_set_writer_func(GjsGLogWrit
                              GDestroyNotify user_data_free) {
     log_writer_user_data = user_data;
     log_writer_user_data_free = user_data_free;
+    log_writer_thread = g_thread_self();
 
     g_log_set_writer_func(gjs_log_writer_func_wrapper, func, NULL);
 }
diff -pruN 1.72.0-4/meson.build 1.73.1-1/meson.build
--- 1.72.0-4/meson.build	2022-03-19 18:04:36.084217300 +0000
+++ 1.73.1-1/meson.build	2022-07-10 19:35:20.000000000 +0000
@@ -2,8 +2,8 @@
 # SPDX-FileCopyrightText: 2019 Philip Chimento <philip.chimento@gmail.com>
 # SPDX-FileCopyrightText: 2019 Chun-wei Fan <fanchunwei@src.gnome.org>
 
-project('gjs', 'cpp', 'c', version: '1.72.0', license: ['MIT', 'LGPL2+'],
-    meson_version: '>= 0.52.0',
+project('gjs', 'cpp', 'c', version: '1.73.1', license: ['MIT', 'LGPL2+'],
+    meson_version: '>= 0.54.0',
     default_options: ['cpp_std=c++17', 'cpp_rtti=false', 'c_std=c99',
         'warning_level=2', 'b_pch=true' ])
 
@@ -14,6 +14,7 @@ project('gjs', 'cpp', 'c', version: '1.7
 api_version = '1.0'
 api_name = '@0@-@1@'.format(meson.project_name(), api_version)
 
+fs = import('fs')
 gnome = import('gnome')
 pkg = import('pkgconfig')
 
@@ -147,12 +148,12 @@ sysprof_capture = dependency('sysprof-ca
     required: get_option('profiler'), include_type: 'system',
     fallback: ['sysprof', 'libsysprof_capture_dep'],
     default_options: [
-        'enable_examples=false',
-        'enable_gtk=false',
-        'enable_tests=false',
-        'enable_tools=false',
+        'examples=false',
+        'gtk=false',
+        'tests=false',
+        'tools=false',
         'libsysprof=false',
-        'with_sysprofd=none',
+        'sysprofd=none',
         'help=false',
     ])
 
@@ -707,6 +708,9 @@ valgrind_args = [
     '--error-exitcode=1'
 ]
 
+add_test_setup('quiet', env: ['GJS_DEBUG_TOPICS='], is_default: true)
+add_test_setup('verbose')
+
 add_test_setup('valgrind', timeout_multiplier: 40, env: valgrind_environment,
     exe_wrapper: ['valgrind'] + valgrind_args)
 
@@ -756,12 +760,52 @@ endif
 
 ### Summarize options ##########################################################
 
-message('\n'.join([
-    'Optional features',
-    '==========================',
-    'Build Cairo module: @0@'.format(build_cairo),
-    'Use readline for input in interactive shell and debugger: @0@'.format(
-        build_readline),
-    'Build profiler (Linux only): @0@'.format(build_profiler),
-    'Build with precompiled headers: @0@'.format(get_option('b_pch')),
-]))
+prefix = get_option('prefix')
+bindir = get_option('bindir')
+libdir = get_option('libdir')
+datadir = get_option('datadir')
+summary({
+    'prefix': prefix,
+    'bindir': fs.is_absolute(bindir) ? bindir : prefix / bindir,
+    'libdir': fs.is_absolute(libdir) ? libdir : prefix / libdir,
+    'datadir': fs.is_absolute(datadir) ? datadir : prefix / datadir,
+}, section: 'Directories')
+locations = []
+foreach dep: [ffi, glib, gi, spidermonkey, readline, sysprof_capture]
+    if dep.type_name() == 'pkgconfig'
+        locations += 'in @0@'.format(dep.get_pkgconfig_variable('prefix'))
+    else
+        locations += dep.type_name()
+    endif
+endforeach
+summary({
+    'libffi': '@0@ (@1@)'.format(ffi.version(), locations[0]),
+    'GLib': '@0@ (@1@)'.format(glib.version(), locations[1]),
+    'GObject introspection': '@0@ (@1@)'.format(gi.version(), locations[2]),
+    'SpiderMonkey': '@0@ (@1@, @2@ build)'.format(spidermonkey.version(),
+        locations[3], nondebug_spidermonkey ? 'release' : 'debug'),
+}, section: 'Dependencies')
+if build_readline
+    summary('Readline', '(@0@)'.format(locations[4]), section: 'Dependencies')
+endif
+if build_profiler
+    summary('Sysprof',
+        '@0@ (@1@)'.format(sysprof_capture.version(), locations[5]),
+        section: 'Dependencies')
+endif
+summary({
+    'Build type': get_option('buildtype'),
+    'Installed tests': get_option('installed_tests'),
+    '-Bsymbolic-functions': get_option('bsymbolic_functions'),
+    'Skip DBus tests': get_option('skip_dbus_tests'),
+    'Skip GTK tests': get_option('skip_gtk_tests'),
+    'Extra debug logs': get_option('verbose_logs'),
+    'Precompiled headers': get_option('b_pch'),
+}, section: 'Build options')
+summary({
+    'Cairo module': build_cairo,
+    'Use readline for input': build_readline,
+    'Profiler (Linux only)': build_profiler,
+    'Dtrace debugging': get_option('dtrace'),
+    'Systemtap debugging': get_option('systemtap'),
+}, section: 'Optional features')
diff -pruN 1.72.0-4/modules/console.cpp 1.73.1-1/modules/console.cpp
--- 1.72.0-4/modules/console.cpp	2022-03-19 18:04:36.085217500 +0000
+++ 1.73.1-1/modules/console.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -28,6 +28,7 @@
 #include <glib/gprintf.h>  // for g_fprintf
 
 #include <js/CallArgs.h>
+#include <js/CharacterEncoding.h>  // for JS_EncodeStringToUTF8
 #include <js/CompilationAndEvaluation.h>
 #include <js/CompileOptions.h>
 #include <js/ErrorReport.h>
@@ -35,11 +36,15 @@
 #include <js/RootingAPI.h>
 #include <js/SourceText.h>
 #include <js/TypeDecls.h>
+#include <js/Utility.h>  // for UniqueChars
+#include <js/Value.h>
+#include <js/ValueArray.h>
 #include <js/Warnings.h>
 #include <jsapi.h>  // for JS_IsExceptionPending, Exce...
 
 #include "gjs/atoms.h"
 #include "gjs/context-private.h"
+#include "gjs/global.h"
 #include "gjs/jsapi-util.h"
 #include "modules/console.h"
 
@@ -146,11 +151,26 @@ sigjmp_buf AutoCatchCtrlC::jump_buffer;
     return true;
 }
 
+std::string print_string_value(JSContext* cx, JS::HandleValue v_string) {
+    if (!v_string.isString())
+        return "[unexpected result from printing value]";
+
+    JS::RootedString printed_string(cx, v_string.toString());
+    JS::AutoSaveExceptionState exc_state(cx);
+    JS::UniqueChars chars(JS_EncodeStringToUTF8(cx, printed_string));
+    exc_state.restore();
+    if (!chars)
+        return "[error printing value]";
+
+    return chars.get();
+}
+
 /* Return value of false indicates an uncatchable exception, rather than any
  * exception. (This is because the exception should be auto-printed around the
  * invocation of this function.)
  */
 [[nodiscard]] static bool gjs_console_eval_and_print(JSContext* cx,
+                                                     JS::HandleObject global,
                                                      const std::string& bytes,
                                                      int lineno) {
     JS::SourceText<mozilla::Utf8Unit> source;
@@ -173,7 +193,23 @@ sigjmp_buf AutoCatchCtrlC::jump_buffer;
     if (result.isUndefined())
         return true;
 
-    g_fprintf(stdout, "%s\n", gjs_value_debug_string(cx, result).c_str());
+    JS::AutoSaveExceptionState exc_state(cx);
+    JS::RootedValue v_printed_string(cx);
+    JS::RootedValue v_pretty_print(
+        cx, gjs_get_global_slot(global, GjsGlobalSlot::PRETTY_PRINT_FUNC));
+    bool ok = JS::Call(cx, global, v_pretty_print, JS::HandleValueArray(result),
+                       &v_printed_string);
+    if (!ok)
+        gjs_log_exception(cx);
+    exc_state.restore();
+
+    if (ok) {
+        g_fprintf(stdout, "%s\n",
+                  print_string_value(cx, v_printed_string).c_str());
+    } else {
+        g_fprintf(stdout, "[error printing value]\n");
+    }
+
     return true;
 }
 
@@ -251,7 +287,7 @@ gjs_console_interact(JSContext *context,
         bool ok;
         {
             AutoReportException are(context);
-            ok = gjs_console_eval_and_print(context, buffer, startline);
+            ok = gjs_console_eval_and_print(context, global, buffer, startline);
         }
         exit_warning = false;
 
diff -pruN 1.72.0-4/modules/core/overrides/Gio.js 1.73.1-1/modules/core/overrides/Gio.js
--- 1.72.0-4/modules/core/overrides/Gio.js	2022-03-19 18:04:36.086217400 +0000
+++ 1.73.1-1/modules/core/overrides/Gio.js	2022-07-10 19:35:20.000000000 +0000
@@ -185,8 +185,22 @@ function _addDBusConvenience() {
     let i, methods = info.methods;
     for (i = 0; i < methods.length; i++) {
         var method = methods[i];
-        this[`${method.name}Remote`] = _makeProxyMethod(methods[i], false);
+        let remoteMethod = _makeProxyMethod(methods[i], false);
+        this[`${method.name}Remote`] = remoteMethod;
         this[`${method.name}Sync`] = _makeProxyMethod(methods[i], true);
+        this[`${method.name}Async`] = function (...args) {
+            return new Promise((resolve, reject) => {
+                args.push((result, error, fdList) => {
+                    if (error)
+                        reject(error);
+                    else if (fdList)
+                        resolve([result, fdList]);
+                    else
+                        resolve(result);
+                });
+                remoteMethod.call(this, ...args);
+            });
+        };
     }
 
     let properties = info.properties;
@@ -443,13 +457,6 @@ function _init() {
     Gio = this;
 
     Gio.DBus = {
-        get session() {
-            return Gio.bus_get_sync(Gio.BusType.SESSION, null);
-        },
-        get system() {
-            return Gio.bus_get_sync(Gio.BusType.SYSTEM, null);
-        },
-
         // Namespace some functions
         get: Gio.bus_get,
         get_finish: Gio.bus_get_finish,
@@ -464,6 +471,21 @@ function _init() {
         unwatch_name: Gio.bus_unwatch_name,
     };
 
+    Object.defineProperties(Gio.DBus, {
+        'session': {
+            get() {
+                return Gio.bus_get_sync(Gio.BusType.SESSION, null);
+            },
+            enumerable: false,
+        },
+        'system': {
+            get() {
+                return Gio.bus_get_sync(Gio.BusType.SYSTEM, null);
+            },
+            enumerable: false,
+        },
+    });
+
     Gio.DBusConnection.prototype.watch_name = function (name, flags, appeared, vanished) {
         return Gio.bus_watch_name_on_connection(this, name, flags, appeared, vanished);
     };
@@ -621,4 +643,28 @@ function _init() {
 
         get_child: createCheckedMethod('get_child', '_checkChild'),
     });
+
+    // ActionMap
+    // add_action_entries is not introspectable
+    // https://gitlab.gnome.org/GNOME/gjs/-/issues/407
+    Gio.ActionMap.prototype.add_action_entries = function add_action_entries(entries) {
+        for (const {name, activate, parameter_type, state, change_state} of entries) {
+            if (typeof parameter_type === 'string' && !GLib.variant_type_string_is_valid(parameter_type))
+                throw new Error(`parameter_type "${parameter_type}" is not a valid VariantType`);
+
+            const action = new Gio.SimpleAction({
+                name,
+                parameter_type: typeof parameter_type === 'string' ? new GLib.VariantType(parameter_type) : null,
+                state: typeof state === 'string' ? GLib.Variant.parse(null, state, null, null) : null,
+            });
+
+            if (typeof activate === 'function')
+                action.connect('activate', activate.bind(action));
+
+            if (typeof change_state === 'function')
+                action.connect('change-state', change_state.bind(action));
+
+            this.add_action(action);
+        }
+    };
 }
diff -pruN 1.72.0-4/modules/print.cpp 1.73.1-1/modules/print.cpp
--- 1.72.0-4/modules/print.cpp	2022-03-19 18:04:36.087217300 +0000
+++ 1.73.1-1/modules/print.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -17,8 +17,10 @@
 #include <js/RootingAPI.h>
 #include <js/TypeDecls.h>
 #include <js/Utility.h>  // for UniqueChars
+#include <js/Value.h>
 #include <jsapi.h>
 
+#include "gjs/global.h"
 #include "gjs/jsapi-util.h"
 #include "modules/print.h"
 
@@ -135,12 +137,57 @@ static bool gjs_printerr(JSContext* cont
     return true;
 }
 
+// The pretty-print functionality is best written in JS, but needs to be used
+// from C++ code. This stores the prettyPrint() function in a slot on the global
+// object so that it can be used internally by the Console module.
+// This function is not available to user code.
+GJS_JSAPI_RETURN_CONVENTION
+static bool set_pretty_print_function(JSContext*, unsigned argc,
+                                      JS::Value* vp) {
+    JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+    // can only be called internally, so OK to assert correct arguments
+    g_assert(args.length() == 2 && "setPrettyPrintFunction takes 2 arguments");
+
+    JS::Value v_global = args[0];
+    JS::Value v_func = args[1];
+
+    g_assert(v_global.isObject() && "first argument must be an object");
+    g_assert(v_func.isObject() && "second argument must be an object");
+
+    gjs_set_global_slot(&v_global.toObject(), GjsGlobalSlot::PRETTY_PRINT_FUNC,
+                        v_func);
+
+    args.rval().setUndefined();
+    return true;
+}
+
+GJS_JSAPI_RETURN_CONVENTION
+static bool get_pretty_print_function(JSContext*, unsigned argc,
+                                      JS::Value* vp) {
+    JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+    g_assert(args.length() == 1 && "getPrettyPrintFunction takes 1 arguments");
+
+    JS::Value v_global = args[0];
+
+    g_assert(v_global.isObject() && "argument must be an object");
+
+    JS::Value pretty_print = gjs_get_global_slot(
+        &v_global.toObject(), GjsGlobalSlot::PRETTY_PRINT_FUNC);
+
+    args.rval().set(pretty_print);
+    return true;
+}
+
 // clang-format off
 static constexpr JSFunctionSpec funcs[] = {
     JS_FN("log", gjs_log, 1, GJS_MODULE_PROP_FLAGS),
     JS_FN("logError", gjs_log_error, 2, GJS_MODULE_PROP_FLAGS),
     JS_FN("print", gjs_print, 0, GJS_MODULE_PROP_FLAGS),
     JS_FN("printerr", gjs_printerr, 0, GJS_MODULE_PROP_FLAGS),
+    JS_FN("setPrettyPrintFunction", set_pretty_print_function, 1, GJS_MODULE_PROP_FLAGS),
+    JS_FN("getPrettyPrintFunction", get_pretty_print_function, 1, GJS_MODULE_PROP_FLAGS),
     JS_FS_END};
 // clang-format on
 
diff -pruN 1.72.0-4/modules/script/_bootstrap/default.js 1.73.1-1/modules/script/_bootstrap/default.js
--- 1.72.0-4/modules/script/_bootstrap/default.js	2022-03-19 18:04:36.088217300 +0000
+++ 1.73.1-1/modules/script/_bootstrap/default.js	2022-07-10 19:35:20.000000000 +0000
@@ -5,7 +5,93 @@
 (function (exports) {
     'use strict';
 
-    const {print, printerr, log, logError} = imports._print;
+    const {
+        print,
+        printerr,
+        log: nativeLog,
+        logError: nativeLogError,
+        setPrettyPrintFunction,
+    } = imports._print;
+
+    function log(...args) {
+        return nativeLog(args.map(prettyPrint).join(' '));
+    }
+
+    function logError(e, ...args) {
+        if (args.length === 0)
+            return nativeLogError(e);
+        return nativeLogError(e, args.map(prettyPrint).join(' '));
+    }
+
+    function prettyPrint(value) {
+        if (value.toString === Object.prototype.toString || value.toString === Array.prototype.toString || value.toString === Function.prototype.toString || value.toString === Date.prototype.toString) {
+            const printedObjects = new WeakSet();
+            switch (typeof value) {
+            case 'object':
+                return formatObject(value, printedObjects);
+            case 'function':
+                return formatFunction(value);
+            default:
+                return value.toString();
+            }
+        } else {
+            return value.toString();
+        }
+    }
+
+    function formatObject(obj, printedObjects) {
+        printedObjects.add(obj);
+        if (Array.isArray(obj))
+            return formatArray(obj, printedObjects).toString();
+
+        if (obj instanceof Date)
+            return formatDate(obj);
+
+        if (obj[Symbol.toStringTag] === 'GIRepositoryNamespace')
+            return obj.toString();
+
+        const formattedObject = [];
+        for (const [key, value] of Object.entries(obj)) {
+            switch (typeof value) {
+            case 'object':
+                if (printedObjects.has(value))
+                    formattedObject.push(`${key}: [Circular]`);
+                else
+                    formattedObject.push(`${key}: ${formatObject(value, printedObjects)}`);
+                break;
+            case 'function':
+                formattedObject.push(`${key}: ${formatFunction(value)}`);
+                break;
+            case 'string':
+                formattedObject.push(`${key}: "${value}"`);
+                break;
+            default:
+                formattedObject.push(`${key}: ${value}`);
+                break;
+            }
+        }
+        return `{ ${formattedObject.join(', ')} }`;
+    }
+
+    function formatArray(arr, printedObjects) {
+        const formattedArray = [];
+        for (const [key, value] of arr.entries()) {
+            if (printedObjects.has(value))
+                formattedArray[key] = '[Circular]';
+            else
+                formattedArray[key] = prettyPrint(value);
+        }
+        return `[${formattedArray.join(', ')}]`;
+    }
+
+    function formatDate(date) {
+        return date.toISOString();
+    }
+
+    function formatFunction(func) {
+        let funcOutput = `[ Function: ${func.name} ]`;
+        return funcOutput;
+    }
 
     Object.defineProperties(exports, {
         ARGV: {
@@ -41,4 +127,5 @@
             value: logError,
         },
     });
+    setPrettyPrintFunction(exports, prettyPrint);
 })(globalThis);
diff -pruN 1.72.0-4/NEWS 1.73.1-1/NEWS
--- 1.72.0-4/NEWS	2022-03-19 18:04:36.056217400 +0000
+++ 1.73.1-1/NEWS	2022-07-10 19:35:20.000000000 +0000
@@ -1,8 +1,96 @@
+Version 1.73.1
+--------------
+
+- The interactive interpreter now displays its output more intelligently,
+  pretty-printing the properties and values of objects based on their type. This
+  improvement also applies to the log() and logError() functions.
+
+- New API: DBus proxy classes now include methods named with the suffix 'Async',
+  which perform async calls to DBus APIs and return Promises. This is in
+  addition to the existing suffixes 'Sync' (for blocking calls) and 'Remote'
+  (for async calls with callbacks.)
+
+- There is an override for Gio.ActionMap.prototype.add_action_entries().
+  Previously this method wouldn't work because it required an array of
+  Gio.ActionEntry objects, which are not possible to construct in GJS. Now it
+  can be used with an array of plain objects. (e.g. `this.add_action_entries([
+  {name: 'open', activate() { ... }}]);`
+
+- GJS is now compatible with libffi 3.4.2 and later. All earlier versions of GJS
+  are not compatible with libffi 3.4.2 and later unless libffi is built with the
+  --disable-exec-static-tramp flag.
+
+- GJS now requires Meson 0.54 to build.
+
+- Closed bugs and merge requests:
+  * Verbose Object Print Output [#107, !587, Nasah Kuma]
+  * Add support for JS async calls in DBusProxyWrapper [!731, Sergio Costas]
+  * Crash after build against libffi 3.4.2 [#428, !737, Evan Welsh]
+  * Handle reference cycles in new console pretty print function [#469, !739,
+    Nasah Kuma]
+  * Gnome-Shell 42 - crash after login (general protection fault) [#479, !740,
+    Xi Ruoyao]
+  * Various maintenance [!741, Philip Chimento]
+  * jsapi-util-strings: Ignore locale to compute the upper case of a char (i.e.
+    fix implicit properties on Turkish locale) [!742, Marco Trevisan]
+  * Dockerfile: Install Turkish locale in CI for UTF-8 locale too [!743, Marco
+    Trevisan]
+  * Improve pretty-print output for GObject-introspected objects [#476, !744,
+    Nasah Kuma]
+  * Expose pretty print function to tests [!745, Nasah Kuma]
+  * build: track changes to Sysprof meson options [!747, Christian Hergert]
+  * Make Gio.ActionMap.add_action_entries work [#407, !749, Sonny Piers]
+  * Make DBus session and system props non-enumerable [!750, Sonny Piers]
+  * gi/arg-inl: Mark the arg functions as constexpr [!752, Marco Trevisan]
+  * build: Do not use verbose GJS debug logging in tests by default [!753, Marco
+    Trevisan]
+  * minijasmine: Print test JS errors output if any [!754, Marco Trevisan]
+  * doc: document the existence of the console object in GJS [!759, Andy Holmes]
+  * arg-cache: Use a switch to select the not-introspectable error [!762, Marco
+    Trevisan]
+  * log_set_writer_func is not safe to use [#481, !766, Evan Welsh]
+
+Version 1.72.1
+--------------
+
+- Various fixes ported from the development branch.
+
+- Closed bugs and merge requests:
+  * Compilation error: call to deleted function 'js_value_to_c' [#473, !738,
+    Evan Miller]
+  * jsapi-util-strings: Ignore locale to compute the upper case of a char (i.e.
+    fix implicit properties on Turkish locale) [!742, Marco Trevisan]
+  * Fix memory leak when passing a "transfer none" GBytes parameter to a native
+    function [!746, msizanoen1]
+  * arg-cache: Do not leak an interface info structures on Callbacks [!751,
+    Marco Trevisan]
+  * test-ci: Ignore safe directory errors on CI [!755, Marco Trevisan]
+
 Version 1.72.0
 --------------
 
 - No changes from release candidate 1.71.90.
 
+Version 1.70.2
+--------------
+
+- Build and compatibility fixes backported from the development branch.
+
+- Closed bugs and merge requests:
+  * package: Reverse order of running-from-source checks [!734, Philip Chimento]
+
+- Fix build error on Darwin [Evan Miller]
+
+Version 1.68.6
+--------------
+
+- Build and compatibility fixes backported from the development branch.
+
+- Closed bugs and merge requests:
+  * package: Reverse order of running-from-source checks [!734, Philip Chimento]
+
+- Fix build error on Darwin [Evan Miller]
+
 Version 1.71.90
 ---------------
 
@@ -17,7 +105,7 @@ Version 1.71.90
   * GNOME Shell crashes at startup with the AppIndicator extension enabled
     [#466, !729, Marco Trevisan]
   * Instances of classes implementing interfaces can override functions for all
-    implentations of an interface [#467, !730, Evan Welsh]
+    implementations of an interface [#467, !730, Evan Welsh]
   * package: Reverse order of running-from-source checks [!734, Philip Chimento]
   * Various maintenance [!735, Philip Chimento]
   * Various maintenance [!736, Evan Welsh]
diff -pruN 1.72.0-4/test/extra/Dockerfile 1.73.1-1/test/extra/Dockerfile
--- 1.72.0-4/test/extra/Dockerfile	2022-03-19 18:04:36.090217400 +0000
+++ 1.73.1-1/test/extra/Dockerfile	2022-07-10 19:35:20.000000000 +0000
@@ -31,6 +31,7 @@ RUN rm -f /root/mozjs-install/usr/lib64/
 
 FROM registry.fedoraproject.org/fedora:34
 
+ARG LOCALES=tr_TR
 ENV SHELL=/bin/bash
 
 # List is comprised of base dependencies for CI scripts, gjs, and debug packages
@@ -39,15 +40,49 @@ ENV SHELL=/bin/bash
 # Do everything in one RUN command so that the dnf cache is not cached in the
 # final Docker image.
 RUN dnf -y install --enablerepo=fedora-debuginfo,updates-debuginfo \
-    binutils cairo-debuginfo cairo-debugsource cairo-gobject-devel clang \
-    compiler-rt dbus-daemon dbus-x11 diffutils fontconfig-debuginfo \
-    fontconfig-debugsource gcc-c++ git glib2-debuginfo glib2-debugsource \
-    glib2-devel glibc-debuginfo glibc-debuginfo-common gnome-desktop-testing \
-    gobject-introspection-debuginfo gobject-introspection-debugsource \
-    gobject-introspection-devel gtk3-debuginfo gtk3-debugsource gtk3-devel \
-    gtk4-debuginfo gtk4-debugsource gtk4-devel lcov libasan libubsan libtsan \
-    meson ninja-build pkgconf readline-devel systemtap-sdt-devel valgrind \
-    which Xvfb xz && \
+    binutils \
+    cairo-debuginfo \
+    cairo-debugsource \
+    cairo-gobject-devel \
+    clang \
+    compiler-rt \
+    dbus-daemon \
+    dbus-x11 \
+    diffutils \
+    fontconfig-debuginfo \
+    fontconfig-debugsource \
+    gcc-c++ \
+    git \
+    glib2-debuginfo \
+    glib2-debugsource \
+    glib2-devel \
+    glibc-debuginfo \
+    glibc-debuginfo-common \
+    glibc-locale-source \
+    gnome-desktop-testing \
+    gobject-introspection-debuginfo \
+    gobject-introspection-debugsource \
+    gobject-introspection-devel \
+    gtk3-debuginfo \
+    gtk3-debugsource \
+    gtk3-devel \
+    gtk4-debuginfo \
+    gtk4-debugsource \
+    gtk4-devel \
+    lcov \
+    libasan \
+    libubsan \
+    libtsan \
+    meson \
+    ninja-build \
+    pkgconf \
+    readline-devel \
+    systemtap-sdt-devel \
+    valgrind \
+    which \
+    Xvfb \
+    xz \
+    && \
     dnf clean all && rm -rf /var/cache/dnf
 
 COPY --from=mozjs-build /root/mozjs-install/usr /usr
@@ -59,6 +94,12 @@ RUN sed -i -e 's/# %wheel/%wheel/' -e '0
 ENV HOST_USER_ID 5555
 RUN useradd -u $HOST_USER_ID -G wheel -ms /bin/bash user
 
+# Enable locales needed for specific tests
+RUN for locale in ${LOCALES}; do \
+        localedef --verbose --force -i "$locale" "$locale" || true; \
+        localedef --verbose --force -i "$locale" -f UTF-8 "$locale".UTF-8 || true; \
+    done
+
 USER user
 WORKDIR /home/user
 
diff -pruN 1.72.0-4/test/extra/Dockerfile.debug 1.73.1-1/test/extra/Dockerfile.debug
--- 1.72.0-4/test/extra/Dockerfile.debug	2022-03-19 18:04:36.090217400 +0000
+++ 1.73.1-1/test/extra/Dockerfile.debug	2022-07-10 19:35:20.000000000 +0000
@@ -45,6 +45,7 @@ RUN rm -f /root/mozjs-install/usr/lib64/
 
 FROM registry.fedoraproject.org/fedora:34
 
+ARG LOCALES=tr_TR
 ENV SHELL=/bin/bash
 
 # List is comprised of base dependencies for CI scripts, gjs, and debug packages
@@ -53,15 +54,50 @@ ENV SHELL=/bin/bash
 # Do everything in one RUN command so that the dnf cache is not cached in the
 # final Docker image.
 RUN dnf -y install --enablerepo=fedora-debuginfo,updates-debuginfo \
-    binutils cairo-debuginfo cairo-debugsource cairo-gobject-devel clang \
-    compiler-rt dbus-daemon dbus-x11 diffutils fontconfig-debuginfo \
-    fontconfig-debugsource gcc-c++ git glib2-debuginfo glib2-debugsource \
-    glib2-devel glibc-debuginfo glibc-debuginfo-common gnome-desktop-testing \
-    gobject-introspection-debuginfo gobject-introspection-debugsource \
-    gobject-introspection-devel gtk3-debuginfo gtk3-debugsource gtk3-devel \
-    gtk4-debuginfo gtk4-debugsource gtk4-devel lcov libasan libubsan libtsan \
-    meson ninja-build pkgconf readline-devel sysprof-devel systemtap-sdt-devel \
-    valgrind which Xvfb xz && \
+    binutils \
+    cairo-debuginfo \
+    cairo-debugsource \
+    cairo-gobject-devel \
+    clang \
+    compiler-rt \
+    dbus-daemon \
+    dbus-x11 \
+    diffutils \
+    fontconfig-debuginfo \
+    fontconfig-debugsource \
+    gcc-c++ \
+    git \
+    glib2-debuginfo \
+    glib2-debugsource \
+    glib2-devel \
+    glibc-debuginfo \
+    glibc-debuginfo-common \
+    glibc-locale-source \
+    gnome-desktop-testing \
+    gobject-introspection-debuginfo \
+    gobject-introspection-debugsource \
+    gobject-introspection-devel \
+    gtk3-debuginfo \
+    gtk3-debugsource \
+    gtk3-devel \
+    gtk4-debuginfo \
+    gtk4-debugsource \
+    gtk4-devel \
+    lcov \
+    libasan \
+    libubsan \
+    libtsan \
+    meson \
+    ninja-build \
+    pkgconf \
+    readline-devel \
+    sysprof-devel \
+    systemtap-sdt-devel \
+    valgrind \
+    which \
+    Xvfb \
+    xz \
+    && \
     dnf clean all && rm -rf /var/cache/dnf
 
 COPY --from=build /root/mozjs-install/usr /usr
@@ -75,6 +111,12 @@ RUN sed -i -e 's/# %wheel/%wheel/' -e '0
 ENV HOST_USER_ID 5555
 RUN useradd -u $HOST_USER_ID -G wheel -ms /bin/bash user
 
+# Enable locales needed for specific tests
+RUN for locale in ${LOCALES}; do \
+        localedef --verbose --force -i "$locale" "$locale" || true; \
+        localedef --verbose --force -i "$locale" -f UTF-8 "$locale".UTF-8 || true; \
+    done
+
 USER user
 WORKDIR /home/user
 
diff -pruN 1.72.0-4/test/gjs-tests.cpp 1.73.1-1/test/gjs-tests.cpp
--- 1.72.0-4/test/gjs-tests.cpp	2022-03-19 18:04:36.091217300 +0000
+++ 1.73.1-1/test/gjs-tests.cpp	2022-07-10 19:35:20.000000000 +0000
@@ -17,7 +17,6 @@
 #include <glib.h>
 #include <glib/gstdio.h>  // for g_unlink
 
-#include <js/Array.h>
 #include <js/BigInt.h>
 #include <js/CharacterEncoding.h>
 #include <js/Exception.h>
@@ -27,7 +26,6 @@
 #include <js/TypeDecls.h>
 #include <js/Utility.h>  // for UniqueChars
 #include <js/Value.h>
-#include <js/ValueArray.h>
 #include <jsapi.h>
 #include <jspubtd.h>  // for JSProto_Number
 #include <mozilla/Span.h>  // for MakeStringSpan
@@ -687,44 +685,6 @@ static void test_jsapi_util_string_to_uc
     g_free(chars);
 }
 
-static void test_jsapi_util_debug_string_valid_utf8(GjsUnitTestFixture* fx,
-                                                    const void*) {
-    JS::RootedValue v_string(fx->cx);
-    g_assert_true(gjs_string_from_utf8(fx->cx, VALID_UTF8_STRING, &v_string));
-
-    std::string debug_output = gjs_value_debug_string(fx->cx, v_string);
-
-    g_assert_cmpstr("\"" VALID_UTF8_STRING "\"", ==, debug_output.c_str());
-}
-
-static void test_jsapi_util_debug_string_invalid_utf8(GjsUnitTestFixture* fx,
-                                                      const void*) {
-    g_test_skip("SpiderMonkey doesn't validate UTF-8 after encoding it");
-
-    JS::RootedValue v_string(fx->cx);
-    const char16_t invalid_unicode[] = { 0xffff, 0xffff };
-    v_string.setString(JS_NewUCStringCopyN(fx->cx, invalid_unicode, 2));
-
-    std::string debug_output = gjs_value_debug_string(fx->cx, v_string);
-    // g_assert_cmpstr("\"\\xff\\xff\\xff\\xff\"", ==, debug_output.c_str());
-}
-
-static void test_jsapi_util_debug_string_object_with_complicated_to_string(
-    GjsUnitTestFixture* fx, const void*) {
-    const char16_t desserts[] = {
-        0xd83c, 0xdf6a,  /* cookie */
-        0xd83c, 0xdf69,  /* doughnut */
-    };
-    JS::RootedValueArray<2> contents(fx->cx);
-    contents[0].setString(JS_NewUCStringCopyN(fx->cx, desserts, 2));
-    contents[1].setString(JS_NewUCStringCopyN(fx->cx, desserts + 2, 2));
-    JS::RootedObject array(fx->cx, JS::NewArrayObject(fx->cx, contents));
-    JS::RootedValue v_array(fx->cx, JS::ObjectValue(*array));
-    std::string debug_output = gjs_value_debug_string(fx->cx, v_array);
-
-    g_assert_cmpstr(u8"🍪,🍩", ==, debug_output.c_str());
-}
-
 static void test_gjs_debug_id_string_no_quotes(GjsUnitTestFixture* fx,
                                                const void*) {
     jsid id = gjs_intern_string_to_id(fx->cx, "prop_key");
@@ -1164,12 +1124,6 @@ main(int    argc,
                         test_jsapi_util_string_char16_data);
     ADD_JSAPI_UTIL_TEST("string/to_ucs4",
                         test_jsapi_util_string_to_ucs4);
-    ADD_JSAPI_UTIL_TEST("debug_string/valid-utf8",
-                        test_jsapi_util_debug_string_valid_utf8);
-    ADD_JSAPI_UTIL_TEST("debug_string/invalid-utf8",
-                        test_jsapi_util_debug_string_invalid_utf8);
-    ADD_JSAPI_UTIL_TEST("debug_string/object-with-complicated-to-string",
-                        test_jsapi_util_debug_string_object_with_complicated_to_string);
 
     ADD_JSAPI_UTIL_TEST("gi/args/safe-integer/max",
                         gjstest_test_safe_integer_max);
diff -pruN 1.72.0-4/test/test-ci.sh 1.73.1-1/test/test-ci.sh
--- 1.72.0-4/test/test-ci.sh	2022-03-19 18:04:36.091217300 +0000
+++ 1.73.1-1/test/test-ci.sh	2022-07-10 19:35:20.000000000 +0000
@@ -25,6 +25,11 @@ do_Get_Upstream_Base () {
     echo '-----------------------------------------'
     echo 'Finding common ancestor'
 
+    if git show-branch ci-upstream-base-branch 2> /dev/null; then
+        echo "Already found"
+        return
+    fi
+
     # We need to add a new remote for the upstream target branch, since this
     # script could be running in a personal fork of the repository which has out
     # of date branches.
@@ -122,6 +127,9 @@ echo "Doing: $1 $extra_opts"
 
 do_Create_Artifacts_Folder "$1"
 
+# Ignore extra git security checks as we don't care in CI.
+git config --global --add safe.directory "${PWD}"
+
 if test "$1" = "SETUP"; then
     do_Show_Info
     do_Print_Labels 'Show GJS git information'
