[gjs: 1/5] jsapi-util: Improve BigInt debug functions




commit b18ff84c1b15c25722a9a3e15812d0ff2c5a5e7c
Author: Philip Chimento <philip chimento gmail com>
Date:   Sat Jan 22 11:13:46 2022 -0800

    jsapi-util: Improve BigInt debug functions
    
    Using JS::ToBigInt64 to debug BigInt means that we can only access the
    first 64-bit digit of the BigInt. (We can convert the whole thing to a
    string, but that might allocate and fail, which we don't want in a debug
    function.) Note this in debug messages, because I got myself confused a
    few times while working on this branch.
    
    Also use the new JS::BigIntIsNegative() API in mozjs91 to improve the
    output, casting the first digit into a signed int if the BigInt was
    negative, and an unsigned int if it was positive.

 gjs/jsapi-util-string.cpp | 20 ++++++++++++++------
 gjs/jsapi-util.h          |  1 +
 test/gjs-tests.cpp        | 27 ++++++++++++++++++---------
 3 files changed, 33 insertions(+), 15 deletions(-)
---
diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
index 238134e5f..2b880e6fc 100644
--- a/gjs/jsapi-util-string.cpp
+++ b/gjs/jsapi-util-string.cpp
@@ -479,6 +479,18 @@ gjs_intern_string_to_id(JSContext  *cx,
     return JS::PropertyKey::fromPinnedString(str);
 }
 
+std::string gjs_debug_bigint(JS::BigInt* bi) {
+    // technically this prints the value % INT64_MAX, cast into an int64_t if
+    // the value is negative, otherwise cast into uint64_t
+    std::ostringstream out;
+    if (JS::BigIntIsNegative(bi))
+        out << JS::ToBigInt64(bi);
+    else
+        out << JS::ToBigUint64(bi);
+    out << "n (modulo 2^64)";
+    return out.str();
+}
+
 enum Quotes {
     DoubleQuotes,
     NoQuotes,
@@ -630,12 +642,8 @@ gjs_debug_value(JS::Value v)
         out << v.toDouble();
         return out.str();
     }
-    if (v.isBigInt()) {
-        std::ostringstream out;
-        // technically this prints v % INT64_MAX
-        out << JS::ToBigInt64(v.toBigInt()) << 'n';
-        return out.str();
-    }
+    if (v.isBigInt())
+        return gjs_debug_bigint(v.toBigInt());
     if (v.isString())
         return gjs_debug_string(v.toString());
     if (v.isSymbol())
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 1300eaaf5..9a8ff1084 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -560,6 +560,7 @@ bool gjs_object_require_converted_property(JSContext       *context,
                                            JS::HandleId     property_name,
                                            uint32_t        *value);
 
+[[nodiscard]] std::string gjs_debug_bigint(JS::BigInt* bi);
 [[nodiscard]] std::string gjs_debug_string(JSString* str);
 [[nodiscard]] std::string gjs_debug_symbol(JS::Symbol* const sym);
 [[nodiscard]] std::string gjs_debug_object(JSObject* obj);
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index 074a7844b..aaffc779a 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -712,10 +712,14 @@ static void test_gjs_debug_string_quotes(GjsUnitTestFixture* fx, const void*) {
 
 static void test_gjs_debug_value_bigint(GjsUnitTestFixture* fx, const void*) {
     JS::BigInt* bi = JS::NumberToBigInt(fx->cx, 42);
-    JS::Value v = JS::BigIntValue(bi);
-    std::string debug_output = gjs_debug_value(v);
+    std::string debug_output = gjs_debug_bigint(bi);
+
+    g_assert_cmpstr(debug_output.c_str(), ==, "42n (modulo 2^64)");
 
-    g_assert_cmpstr(debug_output.c_str(), ==, "42n");
+    bi = JS::NumberToBigInt(fx->cx, -42);
+    debug_output = gjs_debug_bigint(bi);
+
+    g_assert_cmpstr(debug_output.c_str(), ==, "-42n (modulo 2^64)");
 }
 
 static void test_gjs_debug_value_bigint_uint64(GjsUnitTestFixture* fx,
@@ -723,20 +727,25 @@ static void test_gjs_debug_value_bigint_uint64(GjsUnitTestFixture* fx,
     // gjs_debug_value(BigIntValue) prints whatever fits into int64_t, because
     // more complicated operations might be fallible
     JS::BigInt* bi = JS::NumberToBigInt(fx->cx, G_MAXUINT64);
-    JS::Value v = JS::BigIntValue(bi);
-    std::string debug_output = gjs_debug_value(v);
+    std::string debug_output = gjs_debug_bigint(bi);
 
-    g_assert_cmpstr(debug_output.c_str(), ==, "-1n");
+    g_assert_cmpstr(debug_output.c_str(), ==,
+                    "18446744073709551615n (modulo 2^64)");
 }
 
 static void test_gjs_debug_value_bigint_huge(GjsUnitTestFixture* fx,
                                              const void*) {
     JS::BigInt* bi = JS::SimpleStringToBigInt(
         fx->cx, mozilla::MakeStringSpan("10000000000000001"), 16);
-    JS::Value v = JS::BigIntValue(bi);
-    std::string debug_output = gjs_debug_value(v);
+    std::string debug_output = gjs_debug_bigint(bi);
+
+    g_assert_cmpstr(debug_output.c_str(), ==, "1n (modulo 2^64)");
+
+    bi = JS::SimpleStringToBigInt(
+        fx->cx, mozilla::MakeStringSpan("-10000000000000001"), 16);
+    debug_output = gjs_debug_bigint(bi);
 
-    g_assert_cmpstr(debug_output.c_str(), ==, "1n");
+    g_assert_cmpstr(debug_output.c_str(), ==, "-1n (modulo 2^64)");
 }
 
 static void test_gjs_debug_value_string_quotes(GjsUnitTestFixture* fx,


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