Title: [243997] releases/WebKitGTK/webkit-2.24
Revision
243997
Author
carlo...@webkit.org
Date
2019-04-08 03:44:47 -0700 (Mon, 08 Apr 2019)

Log Message

Merge r243289 - [GLIB] User data not correctly passed to callback of functions and constructors with no parameters
https://bugs.webkit.org/show_bug.cgi?id=196073

Patch by Carlos Garcia Campos <cgar...@igalia.com> on 2019-03-21
Reviewed by Michael Catanzaro.

Source/_javascript_Core:

This is because GClosure always expects a first parameter as instance. In case of functions or constructors with
no parameters we insert a fake instance which is just a null pointer that is ignored by the callback. But
if the function/constructor has user data the callback will expect one parameter for the user data. In that case
we can simply swap instance/user data so that the fake instance will be the second argument and user data the
first one.

* API/glib/JSCClass.cpp:
(jscClassCreateConstructor): Use g_cclosure_new_swap() if parameters is empty and user data was provided.
* API/glib/JSCValue.cpp:
(jscValueFunctionCreate): Ditto.

Tools:

Add test cases to check functions and constructors with no arguments but receiving user data.

* TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
(checkUserData):
(testJSCFunction):
(fooCreateWithUserData):
(testJSCClass):

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/API/glib/JSCClass.cpp (243996 => 243997)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/API/glib/JSCClass.cpp	2019-04-08 10:44:42 UTC (rev 243996)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/API/glib/JSCClass.cpp	2019-04-08 10:44:47 UTC (rev 243997)
@@ -554,8 +554,14 @@
 
 static GRefPtr<JSCValue> jscClassCreateConstructor(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, Optional<Vector<GType>>&& parameters)
 {
+    // If the constructor doesn't have arguments, we need to swap the fake instance and user data to ensure
+    // user data is the first parameter and fake instance ignored.
+    GRefPtr<GClosure> closure;
+    if (parameters && parameters->isEmpty() && userData)
+        closure = adoptGRef(g_cclosure_new_swap(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
+    else
+        closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
     JSCClassPrivate* priv = jscClass->priv;
-    GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
     JSC::ExecState* exec = toJS(jscContextGetJSContext(priv->context));
     JSC::VM& vm = exec->vm();
     JSC::JSLockHolder locker(vm);

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/API/glib/JSCValue.cpp (243996 => 243997)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/API/glib/JSCValue.cpp	2019-04-08 10:44:42 UTC (rev 243996)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/API/glib/JSCValue.cpp	2019-04-08 10:44:47 UTC (rev 243997)
@@ -1140,7 +1140,13 @@
 
 static GRefPtr<JSCValue> jscValueFunctionCreate(JSCContext* context, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, Optional<Vector<GType>>&& parameters)
 {
-    GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
+    GRefPtr<GClosure> closure;
+    // If the function doesn't have arguments, we need to swap the fake instance and user data to ensure
+    // user data is the first parameter and fake instance ignored.
+    if (parameters && parameters->isEmpty() && userData)
+        closure = adoptGRef(g_cclosure_new_swap(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
+    else
+        closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
     JSC::ExecState* exec = toJS(jscContextGetJSContext(context));
     JSC::VM& vm = exec->vm();
     JSC::JSLockHolder locker(vm);

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/ChangeLog (243996 => 243997)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/ChangeLog	2019-04-08 10:44:42 UTC (rev 243996)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/ChangeLog	2019-04-08 10:44:47 UTC (rev 243997)
@@ -1,5 +1,23 @@
 2019-03-21  Carlos Garcia Campos  <cgar...@igalia.com>
 
+        [GLIB] User data not correctly passed to callback of functions and constructors with no parameters
+        https://bugs.webkit.org/show_bug.cgi?id=196073
+
+        Reviewed by Michael Catanzaro.
+
+        This is because GClosure always expects a first parameter as instance. In case of functions or constructors with
+        no parameters we insert a fake instance which is just a null pointer that is ignored by the callback. But
+        if the function/constructor has user data the callback will expect one parameter for the user data. In that case
+        we can simply swap instance/user data so that the fake instance will be the second argument and user data the
+        first one.
+
+        * API/glib/JSCClass.cpp:
+        (jscClassCreateConstructor): Use g_cclosure_new_swap() if parameters is empty and user data was provided.
+        * API/glib/JSCValue.cpp:
+        (jscValueFunctionCreate): Ditto.
+
+2019-03-21  Carlos Garcia Campos  <cgar...@igalia.com>
+
         [GLib] Returning G_TYPE_OBJECT from a method does not work
         https://bugs.webkit.org/show_bug.cgi?id=195574
 

Modified: releases/WebKitGTK/webkit-2.24/Tools/ChangeLog (243996 => 243997)


--- releases/WebKitGTK/webkit-2.24/Tools/ChangeLog	2019-04-08 10:44:42 UTC (rev 243996)
+++ releases/WebKitGTK/webkit-2.24/Tools/ChangeLog	2019-04-08 10:44:47 UTC (rev 243997)
@@ -1,5 +1,20 @@
 2019-03-21  Carlos Garcia Campos  <cgar...@igalia.com>
 
+        [GLIB] User data not correctly passed to callback of functions and constructors with no parameters
+        https://bugs.webkit.org/show_bug.cgi?id=196073
+
+        Reviewed by Michael Catanzaro.
+
+        Add test cases to check functions and constructors with no arguments but receiving user data.
+
+        * TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
+        (checkUserData):
+        (testJSCFunction):
+        (fooCreateWithUserData):
+        (testJSCClass):
+
+2019-03-21  Carlos Garcia Campos  <cgar...@igalia.com>
+
         [GLib] Returning G_TYPE_OBJECT from a method does not work
         https://bugs.webkit.org/show_bug.cgi?id=195574
 

Modified: releases/WebKitGTK/webkit-2.24/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp (243996 => 243997)


--- releases/WebKitGTK/webkit-2.24/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2019-04-08 10:44:42 UTC (rev 243996)
+++ releases/WebKitGTK/webkit-2.24/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2019-04-08 10:44:47 UTC (rev 243997)
@@ -847,6 +847,11 @@
     return g_strjoinv(sep, const_cast<char**>(strv));
 }
 
+static gboolean checkUserData(GFile* file)
+{
+    return G_IS_FILE(file);
+}
+
 static void testJSCFunction()
 {
     {
@@ -1092,6 +1097,30 @@
         g_assert_true(jsc_value_is_number(value.get()));
         g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 0);
     }
+
+    {
+        LeakChecker checker;
+        GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
+        checker.watch(context.get());
+        ExceptionHandler exceptionHandler(context.get());
+
+        GFile* file = g_file_new_for_path(".");
+        checker.watch(file);
+        GRefPtr<JSCValue> function = adoptGRef(jsc_value_new_function(context.get(), "checkUserData", G_CALLBACK(checkUserData),
+            file, g_object_unref, G_TYPE_BOOLEAN, 0, G_TYPE_NONE));
+        checker.watch(function.get());
+        jsc_context_set_value(context.get(), "checkUserData", function.get());
+
+        GRefPtr<JSCValue> value = adoptGRef(jsc_context_evaluate(context.get(), "checkUserData()", -1));
+        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_function_call(function.get(), G_TYPE_NONE));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_boolean(value.get()));
+        g_assert_true(jsc_value_to_boolean(value.get()));
+    }
 }
 
 static void testJSCObject()
@@ -1397,6 +1426,12 @@
     return f;
 }
 
+static Foo* fooCreateWithUserData(GFile* file)
+{
+    g_assert_true(G_IS_FILE(file));
+    return fooCreate();
+}
+
 static void fooFree(Foo* foo)
 {
     foo->~Foo();
@@ -1799,6 +1834,19 @@
         g_assert_true(jsc_value_is_number(value.get()));
         g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 0);
 
+        GFile* file = g_file_new_for_path(".");
+        checker.watch(file);
+        GRefPtr<JSCValue> constructorUserData = adoptGRef(jsc_class_add_constructor(jscClass, "CreateWithUserData", G_CALLBACK(fooCreateWithUserData),
+            file, g_object_unref, G_TYPE_POINTER, 0, G_TYPE_NONE));
+        checker.watch(constructorUserData.get());
+        g_assert_true(jsc_value_is_constructor(constructorUserData.get()));
+        jsc_value_object_set_property(constructor.get(), "CreateWithUserData", constructorUserData.get());
+
+        GRefPtr<JSCValue> foo5 = adoptGRef(jsc_context_evaluate(context.get(), "f5 = new Foo.CreateWithUserData();", -1));
+        checker.watch(foo5.get());
+        g_assert_true(jsc_value_is_object(foo5.get()));
+        g_assert_true(jsc_value_object_is_instance_of(foo5.get(), jsc_class_get_name(jscClass)));
+
         JSCClass* otherClass = jsc_context_register_class(context.get(), "Baz", nullptr, nullptr, g_free);
         checker.watch(otherClass);
         g_assert_false(jsc_class_get_parent(otherClass));
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to