Title: [254331] trunk
Revision
254331
Author
[email protected]
Date
2020-01-10 02:53:29 -0800 (Fri, 10 Jan 2020)

Log Message

[GLIB] Add GLib specific API for JSC JSValueRef.h's JSValueMakeFromJSONString and JSValueCreateJSONString methods
https://bugs.webkit.org/show_bug.cgi?id=205161

Reviewed by Adrian Perez de Castro.

Source/_javascript_Core:

Add jsc_value_new_from_json() and jsc_value_to_json().

* API/glib/JSCValue.cpp:
(jsc_value_new_from_json):
(jsc_value_to_json):
* API/glib/JSCValue.h:
* API/glib/docs/jsc-glib-4.0-sections.txt:

Tools:

Add tests for new API.

* TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
(testJSCJSON):
(main):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/glib/JSCValue.cpp (254330 => 254331)


--- trunk/Source/_javascript_Core/API/glib/JSCValue.cpp	2020-01-10 08:45:56 UTC (rev 254330)
+++ trunk/Source/_javascript_Core/API/glib/JSCValue.cpp	2020-01-10 10:53:29 UTC (rev 254331)
@@ -28,6 +28,7 @@
 #include "JSCInlines.h"
 #include "JSCValuePrivate.h"
 #include "JSRetainPtr.h"
+#include "LiteralParser.h"
 #include "OpaqueJSString.h"
 #include <gobject/gvaluecollector.h>
 #include <wtf/glib/GRefPtr.h>
@@ -1446,3 +1447,83 @@
 
     return jscContextGetOrCreateValue(priv->context.get(), result).leakRef();
 }
+
+/**
+ * jsc_value_new_from_json:
+ * @context: a #JSCContext
+ * @json: the JSON string to be parsed
+ *
+ * Create a new #JSCValue referencing a new value created by parsing @json.
+ *
+ * Returns: (transfer full): a #JSCValue.
+ *
+ * Since: 2.28
+ */
+JSCValue* jsc_value_new_from_json(JSCContext* context, const char* json)
+{
+    g_return_val_if_fail(JSC_IS_CONTEXT(context), nullptr);
+
+    if (!json)
+        return jsc_value_new_null(context);
+
+    auto* jsContext = jscContextGetJSContext(context);
+    JSC::JSGlobalObject* globalObject = toJS(jsContext);
+    JSC::JSLockHolder locker(globalObject);
+
+    JSValueRef exception = nullptr;
+    JSC::JSValue jsValue;
+    String jsonString = String::fromUTF8(json);
+    if (jsonString.is8Bit()) {
+        JSC::LiteralParser<LChar> jsonParser(globalObject, jsonString.characters8(), jsonString.length(), JSC::StrictJSON);
+        jsValue = jsonParser.tryLiteralParse();
+        if (!jsValue)
+            exception = toRef(JSC::createSyntaxError(globalObject, jsonParser.getErrorMessage()));
+    } else {
+        JSC::LiteralParser<UChar> jsonParser(globalObject, jsonString.characters16(), jsonString.length(), JSC::StrictJSON);
+        jsValue = jsonParser.tryLiteralParse();
+        if (!jsValue)
+            exception = toRef(JSC::createSyntaxError(globalObject, jsonParser.getErrorMessage()));
+    }
+
+    if (exception) {
+        jscContextHandleExceptionIfNeeded(context, exception);
+        return nullptr;
+    }
+
+    return jsValue ? jscContextGetOrCreateValue(context, toRef(globalObject, jsValue)).leakRef() : nullptr;
+}
+
+/**
+ * jsc_value_to_json:
+ * @value: a #JSCValue
+ * @indent: The number of spaces to indent when nesting.
+ *
+ * Create a JSON string of @value serialization. If @indent is 0, the resulting JSON will
+ * not contain newlines. The size of the indent is clamped to 10 spaces.
+ *
+ * Returns: (transfer full): a null-terminated JSON string with serialization of @value
+ *
+ * Since: 2.28
+ */
+char* jsc_value_to_json(JSCValue* value, unsigned indent)
+{
+    g_return_val_if_fail(JSC_IS_VALUE(value), nullptr);
+
+    JSCValuePrivate* priv = value->priv;
+    JSValueRef exception = nullptr;
+    JSRetainPtr<JSStringRef> jsJSON(Adopt, JSValueCreateJSONString(jscContextGetJSContext(priv->context.get()), priv->jsValue, indent, &exception));
+    if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception))
+        return nullptr;
+
+    if (!jsJSON)
+        return nullptr;
+
+    size_t maxSize = JSStringGetMaximumUTF8CStringSize(jsJSON.get());
+    auto* json = static_cast<char*>(g_malloc(maxSize));
+    if (!JSStringGetUTF8CString(jsJSON.get(), json, maxSize)) {
+        g_free(json);
+        return nullptr;
+    }
+
+    return json;
+}

Modified: trunk/Source/_javascript_Core/API/glib/JSCValue.h (254330 => 254331)


--- trunk/Source/_javascript_Core/API/glib/JSCValue.h	2020-01-10 08:45:56 UTC (rev 254330)
+++ trunk/Source/_javascript_Core/API/glib/JSCValue.h	2020-01-10 10:53:29 UTC (rev 254331)
@@ -260,6 +260,14 @@
                                            guint                 n_parameters,
                                            JSCValue            **parameters);
 
+JSC_API JSCValue *
+jsc_value_new_from_json                   (JSCContext           *context,
+                                           const char           *json);
+
+JSC_API char *
+jsc_value_to_json                         (JSCValue             *value,
+                                           guint                 indent);
+
 G_END_DECLS
 
 #endif /* JSCValue_h */

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


--- trunk/Source/_javascript_Core/API/glib/docs/jsc-glib-4.0-sections.txt	2020-01-10 08:45:56 UTC (rev 254330)
+++ trunk/Source/_javascript_Core/API/glib/docs/jsc-glib-4.0-sections.txt	2020-01-10 10:53:29 UTC (rev 254331)
@@ -113,6 +113,8 @@
 jsc_value_is_constructor
 jsc_value_constructor_call
 jsc_value_constructor_callv
+jsc_value_new_from_json
+jsc_value_to_json
 
 <SUBSECTION Standard>
 JSCValueClass

Modified: trunk/Source/_javascript_Core/ChangeLog (254330 => 254331)


--- trunk/Source/_javascript_Core/ChangeLog	2020-01-10 08:45:56 UTC (rev 254330)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-01-10 10:53:29 UTC (rev 254331)
@@ -1,3 +1,18 @@
+2020-01-10  Carlos Garcia Campos  <[email protected]>
+
+        [GLIB] Add GLib specific API for JSC JSValueRef.h's JSValueMakeFromJSONString and JSValueCreateJSONString methods
+        https://bugs.webkit.org/show_bug.cgi?id=205161
+
+        Reviewed by Adrian Perez de Castro.
+
+        Add jsc_value_new_from_json() and jsc_value_to_json().
+
+        * API/glib/JSCValue.cpp:
+        (jsc_value_new_from_json):
+        (jsc_value_to_json):
+        * API/glib/JSCValue.h:
+        * API/glib/docs/jsc-glib-4.0-sections.txt:
+
 2020-01-10  Adrian Perez de Castro  <[email protected]>
 
         Fix various non-unified build issues introduced since r253538

Modified: trunk/Tools/ChangeLog (254330 => 254331)


--- trunk/Tools/ChangeLog	2020-01-10 08:45:56 UTC (rev 254330)
+++ trunk/Tools/ChangeLog	2020-01-10 10:53:29 UTC (rev 254331)
@@ -1,3 +1,16 @@
+2020-01-10  Carlos Garcia Campos  <[email protected]>
+
+        [GLIB] Add GLib specific API for JSC JSValueRef.h's JSValueMakeFromJSONString and JSValueCreateJSONString methods
+        https://bugs.webkit.org/show_bug.cgi?id=205161
+
+        Reviewed by Adrian Perez de Castro.
+
+        Add tests for new API.
+
+        * TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
+        (testJSCJSON):
+        (main):
+
 2020-01-09  Ryan Haddad  <[email protected]>
 
         Move macOS Test262, JSC, and perf queues to Catalina

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


--- trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2020-01-10 08:45:56 UTC (rev 254330)
+++ trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2020-01-10 10:53:29 UTC (rev 254331)
@@ -3737,6 +3737,144 @@
 }
 #endif
 
+static void testJSCJSON()
+{
+    {
+        LeakChecker checker;
+        GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
+        checker.watch(context.get());
+        ExceptionHandler exceptionHandler(context.get());
+
+        GRefPtr<JSCValue> value = adoptGRef(jsc_value_new_from_json(context.get(), nullptr));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_null(value.get()));
+
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "25"));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_number(value.get()));
+        g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 25);
+
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "2.5"));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_number(value.get()));
+        g_assert_cmpfloat(jsc_value_to_double(value.get()), ==, 2.5);
+
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "true"));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_boolean(value.get()));
+        g_assert_true(jsc_value_to_boolean(value.get()));
+
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "false"));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_boolean(value.get()));
+        g_assert_false(jsc_value_to_boolean(value.get()));
+
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "\"\""));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_string(value.get()));
+        GUniquePtr<char> valueString(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "");
+
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "\"Foo\""));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_string(value.get()));
+        valueString.reset(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "Foo");
+
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "[1,2]"));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_array(value.get()));
+        GRefPtr<JSCValue> arrayLength = adoptGRef(jsc_value_object_get_property(value.get(), "length"));
+        checker.watch(arrayLength.get());
+        g_assert_true(jsc_value_is_number(arrayLength.get()));
+        g_assert_cmpint(jsc_value_to_int32(arrayLength.get()), ==, 2);
+        valueString.reset(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "1,2");
+
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "{\"foo\":42}"));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_object(value.get()));
+        GRefPtr<JSCValue> property = adoptGRef(jsc_value_object_get_property(value.get(), "foo"));
+        checker.watch(property.get());
+        g_assert_true(jsc_value_is_number(property.get()));
+        g_assert_cmpint(jsc_value_to_int32(property.get()), ==, 42);
+
+        bool didThrow = false;
+        g_assert_throw_begin(exceptionHandler, didThrow);
+        value = adoptGRef(jsc_value_new_from_json(context.get(), "[1,"));
+        g_assert_null(value.get());
+        g_assert_did_throw(exceptionHandler, didThrow);
+    }
+
+    {
+        LeakChecker checker;
+        GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
+        checker.watch(context.get());
+        ExceptionHandler exceptionHandler(context.get());
+
+        GRefPtr<JSCValue> value = adoptGRef(jsc_value_new_null(context.get()));
+        checker.watch(value.get());
+        GUniquePtr<char> jsonString(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "null");
+
+        value = adoptGRef(jsc_value_new_undefined(context.get()));
+        checker.watch(value.get());
+        g_assert_null(jsc_value_to_json(value.get(), 0));
+
+        value = adoptGRef(jsc_value_new_number(context.get(), 25));
+        checker.watch(value.get());
+        jsonString.reset(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "25");
+
+        value = adoptGRef(jsc_value_new_number(context.get(), 2.5));
+        checker.watch(value.get());
+        jsonString.reset(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "2.5");
+
+        value = adoptGRef(jsc_value_new_boolean(context.get(), TRUE));
+        checker.watch(value.get());
+        jsonString.reset(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "true");
+
+        value = adoptGRef(jsc_value_new_boolean(context.get(), FALSE));
+        checker.watch(value.get());
+        jsonString.reset(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "false");
+
+        value = adoptGRef(jsc_value_new_string(context.get(), nullptr));
+        checker.watch(value.get());
+        jsonString.reset(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "\"\"");
+
+        value = adoptGRef(jsc_value_new_string(context.get(), "Foo"));
+        checker.watch(value.get());
+        jsonString.reset(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "\"Foo\"");
+
+        value = adoptGRef(jsc_value_new_array(context.get(), G_TYPE_INT, 1, G_TYPE_INT, 2, G_TYPE_NONE));
+        checker.watch(value.get());
+        jsonString.reset(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "[1,2]");
+
+        value = adoptGRef(jsc_value_new_object(context.get(), nullptr, nullptr));
+        checker.watch(value.get());
+        GRefPtr<JSCValue> property = adoptGRef(jsc_value_new_number(context.get(), 42));
+        jsc_value_object_set_property(value.get(), "foo", property.get());
+        jsonString.reset(jsc_value_to_json(value.get(), 0));
+        g_assert_cmpstr(jsonString.get(), ==, "{\"foo\":42}");
+
+        jsonString.reset(jsc_value_to_json(value.get(), 4));
+        g_assert_cmpstr(jsonString.get(), ==, "{\n    \"foo\": 42\n}");
+
+        value = adoptGRef(jsc_context_evaluate(context.get(), "({get a(){ throw '';}})", -1));
+        checker.watch(value.get());
+        bool didThrow = false;
+        g_assert_throw_begin(exceptionHandler, didThrow);
+        g_assert_null(jsc_value_to_json(value.get(), 0));
+        g_assert_did_throw(exceptionHandler, didThrow);
+    }
+}
+
 int main(int argc, char** argv)
 {
     g_test_init(&argc, &argv, nullptr);
@@ -3761,6 +3899,7 @@
 #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
     g_test_add_func("/jsc/autocleanups", testsJSCAutocleanups);
 #endif
+    g_test_add_func("/jsc/json", testJSCJSON);
 
     return g_test_run();
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to