Title: [235023] trunk
Revision
235023
Author
carlo...@webkit.org
Date
2018-08-19 23:57:12 -0700 (Sun, 19 Aug 2018)

Log Message

[GLIB] Complete the JSCException API
https://bugs.webkit.org/show_bug.cgi?id=188695

Reviewed by Michael Catanzaro.

Source/_javascript_Core:

Add more API to JSCException:
 - New function to get the column number
 - New function get exception as string (toString())
 - Add the possibility to create exceptions with a custom error name.
 - New function to get the exception error name
 - New function to get the exception backtrace.
 - New convenience function to report a exception by returning a formatted string with all the exception
   details, to be shown as a user error message.

* API/glib/JSCContext.cpp:
(jsc_context_throw_with_name):
* API/glib/JSCContext.h:
* API/glib/JSCException.cpp:
(jscExceptionEnsureProperties):
(jsc_exception_new):
(jsc_exception_new_with_name):
(jsc_exception_get_name):
(jsc_exception_get_column_number):
(jsc_exception_get_back_trace_string):
(jsc_exception_to_string):
(jsc_exception_report):
* API/glib/JSCException.h:
* API/glib/docs/jsc-glib-4.0-sections.txt:

Tools:

Add cases to test the new API.

* TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
(testJSCCheckSyntax):
(createCustomError):
(testJSCExceptions):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/glib/JSCContext.cpp (235022 => 235023)


--- trunk/Source/_javascript_Core/API/glib/JSCContext.cpp	2018-08-20 00:53:34 UTC (rev 235022)
+++ trunk/Source/_javascript_Core/API/glib/JSCContext.cpp	2018-08-20 06:57:12 UTC (rev 235023)
@@ -644,6 +644,23 @@
 }
 
 /**
+ * jsc_context_throw_with_name:
+ * @context: a #JSCContext
+ * @error_name: the error name
+ * @error_message: an error message
+ *
+ * Throw an exception to @context using the given error name and message. The created #JSCException
+ * can be retrieved with jsc_context_get_exception().
+ */
+void jsc_context_throw_with_name(JSCContext* context, const char* errorName, const char* errorMessage)
+{
+    g_return_if_fail(JSC_IS_CONTEXT(context));
+    g_return_if_fail(errorName);
+
+    context->priv->exception = adoptGRef(jsc_exception_new_with_name(context, errorName, errorMessage));
+}
+
+/**
  * jsc_context_throw_exception:
  * @context: a #JSCContext
  * @exception: a #JSCException

Modified: trunk/Source/_javascript_Core/API/glib/JSCContext.h (235022 => 235023)


--- trunk/Source/_javascript_Core/API/glib/JSCContext.h	2018-08-20 00:53:34 UTC (rev 235022)
+++ trunk/Source/_javascript_Core/API/glib/JSCContext.h	2018-08-20 06:57:12 UTC (rev 235023)
@@ -98,6 +98,11 @@
                                       const char         *error_message);
 
 JSC_API void
+jsc_context_throw_with_name          (JSCContext         *context,
+                                      const char         *error_name,
+                                      const char         *error_message);
+
+JSC_API void
 jsc_context_throw_exception          (JSCContext         *context,
                                       JSCException       *exception);
 

Modified: trunk/Source/_javascript_Core/API/glib/JSCException.cpp (235022 => 235023)


--- trunk/Source/_javascript_Core/API/glib/JSCException.cpp	2018-08-20 00:53:34 UTC (rev 235022)
+++ trunk/Source/_javascript_Core/API/glib/JSCException.cpp	2018-08-20 06:57:12 UTC (rev 235023)
@@ -42,9 +42,12 @@
     JSCContext* context;
     JSC::Strong<JSC::JSObject> jsException;
     bool cached;
+    GUniquePtr<char> errorName;
     GUniquePtr<char> message;
     unsigned lineNumber;
+    unsigned columnNumber;
     GUniquePtr<char> sourceURI;
+    GUniquePtr<char> backtrace;
 };
 
 WEBKIT_DEFINE_TYPE(JSCException, jsc_exception, G_TYPE_OBJECT)
@@ -95,15 +98,24 @@
     priv->cached = true;
 
     auto value = jscContextGetOrCreateValue(priv->context, toRef(priv->jsException.get()));
-    auto propertyValue = adoptGRef(jsc_value_object_get_property(value.get(), "message"));
+    auto propertyValue = adoptGRef(jsc_value_object_get_property(value.get(), "name"));
     if (!jsc_value_is_undefined(propertyValue.get()))
+        priv->errorName.reset(jsc_value_to_string(propertyValue.get()));
+    propertyValue = adoptGRef(jsc_value_object_get_property(value.get(), "message"));
+    if (!jsc_value_is_undefined(propertyValue.get()))
         priv->message.reset(jsc_value_to_string(propertyValue.get()));
     propertyValue = adoptGRef(jsc_value_object_get_property(value.get(), "line"));
     if (!jsc_value_is_undefined(propertyValue.get()))
         priv->lineNumber = jsc_value_to_int32(propertyValue.get());
+    propertyValue = adoptGRef(jsc_value_object_get_property(value.get(), "column"));
+    if (!jsc_value_is_undefined(propertyValue.get()))
+        priv->columnNumber = jsc_value_to_int32(propertyValue.get());
     propertyValue = adoptGRef(jsc_value_object_get_property(value.get(), "sourceURL"));
     if (!jsc_value_is_undefined(propertyValue.get()))
         priv->sourceURI.reset(jsc_value_to_string(propertyValue.get()));
+    propertyValue = adoptGRef(jsc_value_object_get_property(value.get(), "stack"));
+    if (!jsc_value_is_undefined(propertyValue.get()))
+        priv->backtrace.reset(jsc_value_to_string(propertyValue.get()));
 }
 
 /**
@@ -113,10 +125,25 @@
  *
  * Create a new #JSCException in @context with @message.
  *
- * Returns: (transfer full): a new JSCException.
+ * Returns: (transfer full): a new #JSCException.
  */
 JSCException* jsc_exception_new(JSCContext* context, const char* message)
 {
+    return jsc_exception_new_with_name(context, nullptr, message);
+}
+
+/**
+ * jsc_exception_new_with_name:
+ * @context: a #JSCContext
+ * @name: the error name
+ * @message: the error message
+ *
+ * Create a new #JSCException in @context with @name and @message.
+ *
+ * Returns: (transfer full): a new #JSCException.
+ */
+JSCException* jsc_exception_new_with_name(JSCContext* context, const char* name, const char* message)
+{
     g_return_val_if_fail(JSC_IS_CONTEXT(context), nullptr);
 
     auto* jsContext = jscContextGetJSContext(context);
@@ -125,10 +152,37 @@
         JSRetainPtr<JSStringRef> jsMessageString(Adopt, JSStringCreateWithUTF8CString(message));
         jsMessage = JSValueMakeString(jsContext, jsMessageString.get());
     }
-    return jscExceptionCreate(context, JSObjectMakeError(jsContext, jsMessage ? 1 : 0, &jsMessage, nullptr)).leakRef();
+
+    auto exception = jscExceptionCreate(context, JSObjectMakeError(jsContext, jsMessage ? 1 : 0, &jsMessage, nullptr));
+    if (name) {
+        auto value = jscContextGetOrCreateValue(context, toRef(exception->priv->jsException.get()));
+        GRefPtr<JSCValue> nameValue = adoptGRef(jsc_value_new_string(context, name));
+        jsc_value_object_set_property(value.get(), "name", nameValue.get());
+    }
+
+    return exception.leakRef();
 }
 
 /**
+ * jsc_exception_get_name:
+ * @exception: a #JSCException
+ *
+ * Get the error name of @exception
+ *
+ * Returns: the @exception error name.
+ */
+const char* jsc_exception_get_name(JSCException* exception)
+{
+    g_return_val_if_fail(JSC_IS_EXCEPTION(exception), nullptr);
+
+    JSCExceptionPrivate* priv = exception->priv;
+    g_return_val_if_fail(priv->context, nullptr);
+
+    jscExceptionEnsureProperties(exception);
+    return priv->errorName.get();
+}
+
+/**
  * jsc_exception_get_message:
  * @exception: a #JSCException
  *
@@ -167,6 +221,25 @@
 }
 
 /**
+ * jsc_exception_get_column_number:
+ * @exception: a #JSCException
+ *
+ * Get the column number at which @exception happened.
+ *
+ * Returns: the column number of @exception.
+ */
+guint jsc_exception_get_column_number(JSCException* exception)
+{
+    g_return_val_if_fail(JSC_IS_EXCEPTION(exception), 0);
+
+    JSCExceptionPrivate* priv = exception->priv;
+    g_return_val_if_fail(priv->context, 0);
+
+    jscExceptionEnsureProperties(exception);
+    return priv->columnNumber;
+}
+
+/**
  * jsc_exception_get_source_uri:
  * @exception: a #JSCException
  *
@@ -184,3 +257,80 @@
     jscExceptionEnsureProperties(exception);
     return priv->sourceURI.get();
 }
+
+/**
+ * jsc_exception_get_backtrace_string:
+ * @exception: a #JSCException
+ *
+ * Get a string with the exception backtrace.
+ *
+ * Returns: (nullable): the exception backtrace string or %NULL.
+ */
+const char* jsc_exception_get_backtrace_string(JSCException* exception)
+{
+    g_return_val_if_fail(JSC_IS_EXCEPTION(exception), nullptr);
+
+    JSCExceptionPrivate* priv = exception->priv;
+    g_return_val_if_fail(priv->context, nullptr);
+
+    jscExceptionEnsureProperties(exception);
+    return priv->backtrace.get();
+}
+
+/**
+ * jsc_exception_to_string:
+ * @exception: a #JSCException
+ *
+ * Get the string representation of @exception error.
+ *
+ * Returns: (transfer full): the string representation of @exception.
+ */
+char* jsc_exception_to_string(JSCException* exception)
+{
+    g_return_val_if_fail(JSC_IS_EXCEPTION(exception), nullptr);
+
+    JSCExceptionPrivate* priv = exception->priv;
+    g_return_val_if_fail(priv->context, nullptr);
+
+    auto value = jscContextGetOrCreateValue(priv->context, toRef(priv->jsException.get()));
+    return jsc_value_to_string(value.get());
+}
+
+/**
+ * jsc_exception_report:
+ * @exception: a #JSCException
+ *
+ * Return a report message of @exception, containing all the possible details such us
+ * source URI, line, column and backtrace, and formatted to be printed.
+ *
+ * Returns: (transfer full): a new string with the exception report
+ */
+char* jsc_exception_report(JSCException* exception)
+{
+    g_return_val_if_fail(JSC_IS_EXCEPTION(exception), nullptr);
+
+    JSCExceptionPrivate* priv = exception->priv;
+    g_return_val_if_fail(priv->context, nullptr);
+
+    jscExceptionEnsureProperties(exception);
+    GString* report = g_string_new(nullptr);
+    if (priv->sourceURI)
+        report = g_string_append(report, priv->sourceURI.get());
+    if (priv->lineNumber)
+        g_string_append_printf(report, ":%d", priv->lineNumber);
+    if (priv->columnNumber)
+        g_string_append_printf(report, ":%d", priv->columnNumber);
+    report = g_string_append_c(report, ' ');
+    GUniquePtr<char> errorMessage(jsc_exception_to_string(exception));
+    if (errorMessage)
+        report = g_string_append(report, errorMessage.get());
+    report = g_string_append_c(report, '\n');
+
+    if (priv->backtrace) {
+        GUniquePtr<char*> lines(g_strsplit(priv->backtrace.get(), "\n", 0));
+        for (unsigned i = 0; lines.get()[i]; ++i)
+            g_string_append_printf(report, "  %s\n", lines.get()[i]);
+    }
+
+    return g_string_free(report, FALSE);
+}

Modified: trunk/Source/_javascript_Core/API/glib/JSCException.h (235022 => 235023)


--- trunk/Source/_javascript_Core/API/glib/JSCException.h	2018-08-20 00:53:34 UTC (rev 235022)
+++ trunk/Source/_javascript_Core/API/glib/JSCException.h	2018-08-20 06:57:12 UTC (rev 235023)
@@ -59,21 +59,41 @@
 };
 
 JSC_API GType
-jsc_exception_get_type        (void);
+jsc_exception_get_type              (void);
 
 JSC_API JSCException *
-jsc_exception_new             (JSCContext   *context,
-                               const char   *message);
+jsc_exception_new                   (JSCContext   *context,
+                                     const char   *message);
 
+JSC_API JSCException *
+jsc_exception_new_with_name         (JSCContext   *context,
+                                     const char   *name,
+                                     const char   *message);
+
 JSC_API const char *
-jsc_exception_get_message     (JSCException *exception);
+jsc_exception_get_name              (JSCException *exception);
 
+JSC_API const char *
+jsc_exception_get_message           (JSCException *exception);
+
 JSC_API guint
-jsc_exception_get_line_number (JSCException *exception);
+jsc_exception_get_line_number       (JSCException *exception);
 
+JSC_API guint
+jsc_exception_get_column_number     (JSCException *exception);
+
 JSC_API const char *
-jsc_exception_get_source_uri  (JSCException *exception);
+jsc_exception_get_source_uri        (JSCException *exception);
 
+JSC_API const char *
+jsc_exception_get_backtrace_string  (JSCException *exception);
+
+JSC_API char *
+jsc_exception_to_string             (JSCException *exception);
+
+JSC_API char *
+jsc_exception_report                (JSCException *exception);
+
 G_END_DECLS
 
 #endif /* JSCException_h */

Modified: trunk/Source/_javascript_Core/API/glib/docs/jsc-glib-4.0-sections.txt (235022 => 235023)


--- trunk/Source/_javascript_Core/API/glib/docs/jsc-glib-4.0-sections.txt	2018-08-20 00:53:34 UTC (rev 235022)
+++ trunk/Source/_javascript_Core/API/glib/docs/jsc-glib-4.0-sections.txt	2018-08-20 06:57:12 UTC (rev 235023)
@@ -33,6 +33,7 @@
 jsc_context_get_virtual_machine
 jsc_context_get_exception
 jsc_context_throw
+jsc_context_throw_with_name
 jsc_context_throw_exception
 jsc_context_clear_exception
 jsc_context_push_exception_handler
@@ -151,9 +152,15 @@
 <TITLE>JSCException</TITLE>
 JSCException
 jsc_exception_new
+jsc_exception_new_with_name
+jsc_exception_get_name
 jsc_exception_get_message
 jsc_exception_get_line_number
+jsc_exception_get_column_number
 jsc_exception_get_source_uri
+jsc_exception_get_backtrace_string
+jsc_exception_to_string
+jsc_exception_report
 
 <SUBSECTION Standard>
 JSCExceptionClass

Modified: trunk/Source/_javascript_Core/ChangeLog (235022 => 235023)


--- trunk/Source/_javascript_Core/ChangeLog	2018-08-20 00:53:34 UTC (rev 235022)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-08-20 06:57:12 UTC (rev 235023)
@@ -1,3 +1,34 @@
+2018-08-19  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        [GLIB] Complete the JSCException API
+        https://bugs.webkit.org/show_bug.cgi?id=188695
+
+        Reviewed by Michael Catanzaro.
+
+        Add more API to JSCException:
+         - New function to get the column number
+         - New function get exception as string (toString())
+         - Add the possibility to create exceptions with a custom error name.
+         - New function to get the exception error name
+         - New function to get the exception backtrace.
+         - New convenience function to report a exception by returning a formatted string with all the exception
+           details, to be shown as a user error message.
+
+        * API/glib/JSCContext.cpp:
+        (jsc_context_throw_with_name):
+        * API/glib/JSCContext.h:
+        * API/glib/JSCException.cpp:
+        (jscExceptionEnsureProperties):
+        (jsc_exception_new):
+        (jsc_exception_new_with_name):
+        (jsc_exception_get_name):
+        (jsc_exception_get_column_number):
+        (jsc_exception_get_back_trace_string):
+        (jsc_exception_to_string):
+        (jsc_exception_report):
+        * API/glib/JSCException.h:
+        * API/glib/docs/jsc-glib-4.0-sections.txt:
+
 2018-08-19  Commit Queue  <commit-qu...@webkit.org>
 
         Unreviewed, rolling out r234852.

Modified: trunk/Tools/ChangeLog (235022 => 235023)


--- trunk/Tools/ChangeLog	2018-08-20 00:53:34 UTC (rev 235022)
+++ trunk/Tools/ChangeLog	2018-08-20 06:57:12 UTC (rev 235023)
@@ -1,3 +1,17 @@
+2018-08-19  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        [GLIB] Complete the JSCException API
+        https://bugs.webkit.org/show_bug.cgi?id=188695
+
+        Reviewed by Michael Catanzaro.
+
+        Add cases to test the new API.
+
+        * TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
+        (testJSCCheckSyntax):
+        (createCustomError):
+        (testJSCExceptions):
+
 2018-08-18  Wenson Hsieh  <wenson_hs...@apple.com>
 
         [iOS] Paste is missing from callout bar when pasteboard only contains custom data

Modified: trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp (235022 => 235023)


--- trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2018-08-20 00:53:34 UTC (rev 235022)
+++ trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2018-08-20 06:57:12 UTC (rev 235023)
@@ -777,9 +777,11 @@
     g_assert_cmpuint(jsc_context_check_syntax(context.get(), "f = 42; b =", -1, JSC_CHECK_SYNTAX_MODE_SCRIPT, nullptr, 0, &exception.outPtr()), ==, JSC_CHECK_SYNTAX_RESULT_RECOVERABLE_ERROR);
     checker.watch(exception.get());
     g_assert_true(JSC_IS_EXCEPTION(exception.get()));
+    g_assert_cmpstr(jsc_exception_get_name(exception.get()), ==, "SyntaxError");
     g_assert_cmpstr(jsc_exception_get_message(exception.get()), ==, "Unexpected end of script");
     g_assert_cmpuint(jsc_exception_get_line_number(exception.get()), ==, 1);
-    g_assert_false(jsc_exception_get_source_uri(exception.get()));
+    g_assert_null(jsc_exception_get_source_uri(exception.get()));
+    g_assert_null(jsc_exception_get_backtrace_string(exception.get()));
     GRefPtr<JSCValue> globalObject = adoptGRef(jsc_context_get_global_object(context.get()));
     checker.watch(globalObject.get());
     g_assert_false(jsc_value_object_has_property(globalObject.get(), "f"));
@@ -798,8 +800,8 @@
     g_assert_cmpuint(jsc_context_check_syntax(context.get(), "f ==== 42", -1, JSC_CHECK_SYNTAX_MODE_SCRIPT, "file:///foo/script.js", 2, &exception.outPtr()), ==, JSC_CHECK_SYNTAX_RESULT_IRRECOVERABLE_ERROR);
     checker.watch(exception.get());
     g_assert_true(JSC_IS_EXCEPTION(exception.get()));
+    g_assert_cmpstr(jsc_exception_get_name(exception.get()), ==, "SyntaxError");
     g_assert_cmpstr(jsc_exception_get_message(exception.get()), ==, "Unexpected token '='");
-    g_assert_cmpuint(jsc_exception_get_line_number(exception.get()), ==, 2);
     g_assert_cmpstr(jsc_exception_get_source_uri(exception.get()), ==, "file:///foo/script.js");
 
     g_assert_cmpuint(jsc_context_check_syntax(context.get(), "f := 42", -1, JSC_CHECK_SYNTAX_MODE_SCRIPT, nullptr, 0, nullptr), ==, JSC_CHECK_SYNTAX_RESULT_IRRECOVERABLE_ERROR);
@@ -2488,6 +2490,11 @@
     jsc_context_throw(jsc_context_get_current(), "API exception");
 }
 
+static void createCustomError()
+{
+    jsc_context_throw_with_name(jsc_context_get_current(), "CustomAPIError", "API custom exception");
+}
+
 static void testJSCExceptions()
 {
     {
@@ -2503,9 +2510,16 @@
         auto* exception = jsc_context_get_exception(context.get());
         g_assert_true(JSC_IS_EXCEPTION(exception));
         checker.watch(exception);
+        g_assert_cmpstr(jsc_exception_get_name(exception), ==, "ReferenceError");
         g_assert_cmpstr(jsc_exception_get_message(exception), ==, "Can't find variable: foo");
         g_assert_cmpuint(jsc_exception_get_line_number(exception), ==, 1);
-        g_assert_false(jsc_exception_get_source_uri(exception));
+        g_assert_cmpuint(jsc_exception_get_column_number(exception), ==, 4);
+        g_assert_null(jsc_exception_get_source_uri(exception));
+        g_assert_cmpstr(jsc_exception_get_backtrace_string(exception), ==, "global code");
+        GUniquePtr<char> errorString(jsc_exception_to_string(exception));
+        g_assert_cmpstr(errorString.get(), ==, "ReferenceError: Can't find variable: foo");
+        GUniquePtr<char> reportString(jsc_exception_report(exception));
+        g_assert_cmpstr(reportString.get(), ==, ":1:4 ReferenceError: Can't find variable: foo\n  global code\n");
 
         jsc_context_clear_exception(context.get());
         g_assert_null(jsc_context_get_exception(context.get()));
@@ -2525,6 +2539,7 @@
         g_assert_true(JSC_IS_EXCEPTION(exception));
         checker.watch(exception);
         g_assert_cmpuint(jsc_exception_get_line_number(exception), ==, 2);
+        g_assert_cmpuint(jsc_exception_get_column_number(exception), ==, 4);
 
         jsc_context_clear_exception(context.get());
         g_assert_null(jsc_context_get_exception(context.get()));
@@ -2536,7 +2551,18 @@
         checker.watch(context.get());
         g_assert_false(jsc_context_get_exception(context.get()));
 
-        GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate_with_source_uri(context.get(), "foo", -1, "file:///foo/script.js", 3));
+        GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate_with_source_uri(context.get(),
+            "let a = 25;\n"
+            "function foo() {\n"
+            "    let b = baz();\n"
+            "    return b;\n"
+            "}\n"
+            "function bar() {\n"
+            "    let c = 75;\n"
+            "    return foo();\n"
+            "}\n"
+            "let d = bar();\n",
+            -1, "file:///foo/script.js", 1));
         checker.watch(result.get());
 
         g_assert_true(jsc_value_is_undefined(result.get()));
@@ -2543,8 +2569,16 @@
         auto* exception = jsc_context_get_exception(context.get());
         g_assert_true(JSC_IS_EXCEPTION(exception));
         checker.watch(exception);
+        g_assert_cmpstr(jsc_exception_get_name(exception), ==, "ReferenceError");
+        g_assert_cmpstr(jsc_exception_get_message(exception), ==, "Can't find variable: baz");
         g_assert_cmpstr(jsc_exception_get_source_uri(exception), ==, "file:///foo/script.js");
         g_assert_cmpuint(jsc_exception_get_line_number(exception), ==, 3);
+        g_assert_cmpuint(jsc_exception_get_column_number(exception), ==, 16);
+        g_assert_cmpstr(jsc_exception_get_backtrace_string(exception), ==, "foo@file:///foo/script.js:3:16\nbar@file:///foo/script.js:8:15\nglobal code@file:///foo/script.js:10:12");
+        GUniquePtr<char> errorString(jsc_exception_to_string(exception));
+        g_assert_cmpstr(errorString.get(), ==, "ReferenceError: Can't find variable: baz");
+        GUniquePtr<char> reportString(jsc_exception_report(exception));
+        g_assert_cmpstr(reportString.get(), ==, "file:///foo/script.js:3:16 ReferenceError: Can't find variable: baz\n  foo@file:///foo/script.js:3:16\n  bar@file:///foo/script.js:8:15\n  global code@file:///foo/script.js:10:12\n");
 
         jsc_context_clear_exception(context.get());
         g_assert_null(jsc_context_get_exception(context.get()));
@@ -2573,9 +2607,16 @@
         auto* exception = jsc_context_get_exception(context.get());
         g_assert_true(JSC_IS_EXCEPTION(exception));
         checker.watch(exception);
+        g_assert_cmpstr(jsc_exception_get_name(exception), ==, "Error");
         g_assert_cmpstr(jsc_exception_get_message(exception), ==, "API exception");
         g_assert_cmpuint(jsc_exception_get_line_number(exception), ==, 1);
-        g_assert_false(jsc_exception_get_source_uri(exception));
+        g_assert_cmpuint(jsc_exception_get_column_number(exception), ==, 24);
+        g_assert_null(jsc_exception_get_source_uri(exception));
+        g_assert_cmpstr(jsc_exception_get_backtrace_string(exception), ==, "createError@[native code]\nglobal code");
+        GUniquePtr<char> errorString(jsc_exception_to_string(exception));
+        g_assert_cmpstr(errorString.get(), ==, "Error: API exception");
+        GUniquePtr<char> reportString(jsc_exception_report(exception));
+        g_assert_cmpstr(reportString.get(), ==, ":1:24 Error: API exception\n  createError@[native code]\n  global code\n");
 
         jsc_context_clear_exception(context.get());
         g_assert_null(jsc_context_get_exception(context.get()));
@@ -2587,6 +2628,61 @@
         checker.watch(context.get());
         g_assert_false(jsc_context_get_exception(context.get()));
 
+        GRefPtr<JSCValue> function = adoptGRef(jsc_value_new_function(context.get(), "createCustomError", G_CALLBACK(createCustomError), nullptr, nullptr, G_TYPE_NONE, 0, G_TYPE_NONE));
+        checker.watch(function.get());
+        jsc_context_set_value(context.get(), "createCustomError", function.get());
+
+        GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate(context.get(), "var result; createCustomError(); result = 'No exception';", -1));
+        checker.watch(result.get());
+        g_assert_true(jsc_value_is_undefined(result.get()));
+        auto* exception = jsc_context_get_exception(context.get());
+        g_assert_true(JSC_IS_EXCEPTION(exception));
+        checker.watch(exception);
+        g_assert_cmpstr(jsc_exception_get_name(exception), ==, "CustomAPIError");
+        g_assert_cmpstr(jsc_exception_get_message(exception), ==, "API custom exception");
+        g_assert_cmpuint(jsc_exception_get_line_number(exception), ==, 1);
+        g_assert_cmpuint(jsc_exception_get_column_number(exception), ==, 30);
+        g_assert_null(jsc_exception_get_source_uri(exception));
+        g_assert_cmpstr(jsc_exception_get_backtrace_string(exception), ==, "createCustomError@[native code]\nglobal code");
+        GUniquePtr<char> errorString(jsc_exception_to_string(exception));
+        g_assert_cmpstr(errorString.get(), ==, "CustomAPIError: API custom exception");
+        GUniquePtr<char> reportString(jsc_exception_report(exception));
+        g_assert_cmpstr(reportString.get(), ==, ":1:30 CustomAPIError: API custom exception\n  createCustomError@[native code]\n  global code\n");
+
+        jsc_context_clear_exception(context.get());
+        g_assert_null(jsc_context_get_exception(context.get()));
+    }
+
+    {
+        LeakChecker checker;
+        GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
+        checker.watch(context.get());
+        g_assert_false(jsc_context_get_exception(context.get()));
+
+        GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate_with_source_uri(context.get(), "foo", -1, "file:///foo/script.js", 3));
+        checker.watch(result.get());
+
+        g_assert_true(jsc_value_is_undefined(result.get()));
+        auto* exception = jsc_context_get_exception(context.get());
+        g_assert_true(JSC_IS_EXCEPTION(exception));
+        checker.watch(exception);
+        g_assert_cmpstr(jsc_exception_get_source_uri(exception), ==, "file:///foo/script.js");
+        g_assert_cmpuint(jsc_exception_get_line_number(exception), ==, 3);
+        g_assert_cmpuint(jsc_exception_get_column_number(exception), ==, 4);
+        g_assert_cmpstr(jsc_exception_get_backtrace_string(exception), ==, "global code@file:///foo/script.js:3:4");
+        GUniquePtr<char> reportString(jsc_exception_report(exception));
+        g_assert_cmpstr(reportString.get(), ==, "file:///foo/script.js:3:4 ReferenceError: Can't find variable: foo\n  global code@file:///foo/script.js:3:4\n");
+
+        jsc_context_clear_exception(context.get());
+        g_assert_null(jsc_context_get_exception(context.get()));
+    }
+
+    {
+        LeakChecker checker;
+        GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
+        checker.watch(context.get());
+        g_assert_false(jsc_context_get_exception(context.get()));
+
         struct Test {
             JSCContext* context;
             GRefPtr<JSCException> exception;
@@ -2610,9 +2706,13 @@
         g_assert_false(jsc_context_get_exception(context.get()));
         g_assert_true(JSC_IS_EXCEPTION(test.exception.get()));
         checker.watch(test.exception.get());
+        g_assert_cmpstr(jsc_exception_get_name(test.exception.get()), ==, "ReferenceError");
         g_assert_cmpstr(jsc_exception_get_message(test.exception.get()), ==, "Can't find variable: foo");
         g_assert_cmpuint(jsc_exception_get_line_number(test.exception.get()), ==, 1);
+        g_assert_cmpuint(jsc_exception_get_column_number(test.exception.get()), ==, 4);
         g_assert_false(jsc_exception_get_source_uri(test.exception.get()));
+        GUniquePtr<char> errorString(jsc_exception_to_string(test.exception.get()));
+        g_assert_cmpstr(errorString.get(), ==, "ReferenceError: Can't find variable: foo");
 
         g_assert_false(test.wasDeleted);
         jsc_context_pop_exception_handler(context.get());
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to