[gjs/gnome-3-36] jsapi-util: Fix gjs_log_exception() for InternalError



commit 4492f89daf186cb567602d85f9abf850d94eac4a
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun Mar 8 17:58:01 2020 -0700

    jsapi-util: Fix gjs_log_exception() for InternalError
    
    Apparently in some cases we can receive an InternalError from the JS
    engine whose ToString doesn't do anything, returning null instead. Treat
    InternalError differently in gjs_log_exception_full(), creating an error
    report to get at the error message and using the internal SavedFrame
    object to print the stack.
    
    See: #306

 gjs/jsapi-util.cpp | 55 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 39 insertions(+), 16 deletions(-)
---
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index c270dd71..25b9945b 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -400,24 +400,35 @@ gjs_log_exception_full(JSContext       *context,
                        JS::HandleValue  exc,
                        JS::HandleString message)
 {
-    bool is_syntax;
+    JS::AutoSaveExceptionState saved_exc(context);
     const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
 
     JS::RootedObject exc_obj(context);
-    JS::RootedString exc_str(context, JS::ToString(context, exc));
-    JS::UniqueChars utf8_exception;
-    if (exc_str)
-        utf8_exception = JS_EncodeStringToUTF8(context, exc_str);
-    if (!utf8_exception)
-        JS_ClearPendingException(context);
-
-    is_syntax = false;
+    JS::RootedString exc_str(context);
+    bool is_syntax = false, is_internal = false;
     if (exc.isObject()) {
         exc_obj = &exc.toObject();
         const JSClass* syntax_error =
             js::Jsvalify(js::ProtoKeyToClass(JSProto_SyntaxError));
         is_syntax = JS_InstanceOf(context, exc_obj, syntax_error, nullptr);
+
+        const JSClass* internal_error =
+            js::Jsvalify(js::ProtoKeyToClass(JSProto_InternalError));
+        is_internal = JS_InstanceOf(context, exc_obj, internal_error, nullptr);
+    }
+
+    if (is_internal) {
+        JSErrorReport* report = JS_ErrorFromException(context, exc_obj);
+        if (!report->message())
+            exc_str = JS_NewStringCopyZ(context, "(unknown internal error)");
+        else
+            exc_str = JS_NewStringCopyUTF8Z(context, report->message());
+    } else {
+        exc_str = JS::ToString(context, exc);
     }
+    JS::UniqueChars utf8_exception;
+    if (exc_str)
+        utf8_exception = JS_EncodeStringToUTF8(context, exc_str);
 
     JS::UniqueChars utf8_message;
     if (message)
@@ -457,13 +468,23 @@ gjs_log_exception_full(JSContext       *context,
 
     } else {
         JS::UniqueChars utf8_stack;
-        JS::RootedValue stack(context);
-
-        if (exc.isObject() &&
-            JS_GetPropertyById(context, exc_obj, atoms.stack(), &stack) &&
-            stack.isString()) {
-            JS::RootedString str(context, stack.toString());
-            utf8_stack = JS_EncodeStringToUTF8(context, str);
+        if (exc.isObject()) {
+            // Check both the internal SavedFrame object and the stack property.
+            // GErrors will not have the former, and internal errors will not
+            // have the latter.
+            JS::RootedObject saved_frame(context,
+                                         JS::ExceptionStackOrNull(exc_obj));
+            JS::RootedString str(context);
+            if (saved_frame) {
+                JS::BuildStackString(context, nullptr, saved_frame, &str, 0);
+            } else {
+                JS::RootedValue stack(context);
+                JS_GetPropertyById(context, exc_obj, atoms.stack(), &stack);
+                if (stack.isString())
+                    str = stack.toString();
+            }
+            if (str)
+                utf8_stack = JS_EncodeStringToUTF8(context, str);
         }
 
         if (message) {
@@ -482,6 +503,8 @@ gjs_log_exception_full(JSContext       *context,
         }
     }
 
+    saved_exc.restore();
+
     return true;
 }
 


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