<html>
    <head>
      <base href="https://bugs.webkit.org/" />
    </head>
    <body><span class="vcard"><a class="email" href="mailto:cgarcia&#64;igalia.com" title="Carlos Garcia Campos &lt;cgarcia&#64;igalia.com&gt;"> <span class="fn">Carlos Garcia Campos</span></a>
</span> changed
              <a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [GTK] Initial implementation of JavaScriptCore glib bindings"
   href="https://bugs.webkit.org/show_bug.cgi?id=164061">bug 164061</a>
        <br>
             <table border="1" cellspacing="0" cellpadding="8">
          <tr>
            <th>What</th>
            <th>Removed</th>
            <th>Added</th>
          </tr>

         <tr>
           <td style="text-align:right;">Attachment #294417 Flags</td>
           <td>review?, commit-queue?
           </td>
           <td>review-, commit-queue-
           </td>
         </tr></table>
      <p>
        <div>
            <b><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [GTK] Initial implementation of JavaScriptCore glib bindings"
   href="https://bugs.webkit.org/show_bug.cgi?id=164061#c10">Comment # 10</a>
              on <a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [GTK] Initial implementation of JavaScriptCore glib bindings"
   href="https://bugs.webkit.org/show_bug.cgi?id=164061">bug 164061</a>
              from <span class="vcard"><a class="email" href="mailto:cgarcia&#64;igalia.com" title="Carlos Garcia Campos &lt;cgarcia&#64;igalia.com&gt;"> <span class="fn">Carlos Garcia Campos</span></a>
</span></b>
        <pre>Comment on <span class=""><a href="attachment.cgi?id=294417&amp;action=diff" name="attach_294417" title="Patch">attachment 294417</a> <a href="attachment.cgi?id=294417&amp;action=edit" title="Patch">[details]</a></span>
Patch

View in context: <a href="https://bugs.webkit.org/attachment.cgi?id=294417&amp;action=review">https://bugs.webkit.org/attachment.cgi?id=294417&amp;action=review</a>

<span class="quote">&gt; Source/JavaScriptCore/ChangeLog:9
&gt; +        according to the discussion on webklit-gtk mailing list thread</span >

webklit-gtk -&gt; webkit-gtk

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.cpp:46
&gt; +JSCBoolean* jscBooleanCreate(JSCContext* context, JSValueRef jsValue)</span >

I think it's easier if this also returns a JSCValue*

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.cpp:51
&gt; +    JSCBoolean* boolean = JSC_BOOLEAN(g_object_new(JSC_TYPE_BOOLEAN, &quot;context&quot;, context, NULL));</span >

NULL -&gt; nullptr

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.cpp:52
&gt; +    jscValueSetJSValue(JSC_VALUE(boolean), jsValue);</span >

If this returns a JSCValue, you only need to cast the g_object_new(), and here we don't need to cast again.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.cpp:68
&gt; +    g_return_val_if_fail(JSC_IS_CONTEXT(context), false);</span >

false -&gt; nullptr

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.cpp:73
&gt; +    JSContextRef jsContext = jscContextGetJSContext(context);
&gt; +    JSValueRef jsValue = JSValueMakeBoolean(jsContext, value);
&gt; +
&gt; +    return JSC_VALUE(jscBooleanCreate(context, jsValue));</span >

If Create returns a JSCValue you don't need to cast here once again. I think this could be a single line:

return jscBooleanCreate(context, JSValueMakeBoolean(jscContextGetJSContext(context), value)));

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.cpp:86
&gt; +    g_return_val_if_fail(JSC_IS_BOOLEAN(boolean), false);</span >

false -&gt; FALSE

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.cpp:89
&gt; +    JSCContext* context;
&gt; +    g_object_get(G_OBJECT(context), &quot;context&quot;, &amp;context, nullptr);</span >

You are getting the context from the context here, I guess it should be boolean instead of context. But don't use g_object_get for this, add a private method to JSCValue to get its context without taking any extra reference.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.cpp:95
&gt; +    return JSValueToBoolean(jsContext, jsValue);</span >

return JSValueToBoolean(jscContextGetJSContext(context), jscValueGetJSValue(JSC_VALUE(boolean));

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.h:43
&gt; +    JSCValueClass parentClass;</span >

parent_class

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.h:48
&gt; +JSCValue* jsc_boolean_new       (JSCContext* context,</span >

JSCContext* context -&gt; JSCContext *context

In public headers we follow the GNOME style.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBoolean.h:51
&gt; +gboolean  jsc_boolean_get_value (JSCBoolean* value);</span >

JSCBoolean* value -&gt; JSCBoolean *value

I'm not sure value is the best name here, it's a bit weird that the function is get_value and receives a value parameter. And in _new() value refers to the gboolean too, not the object. I would use boolean instead, like in the implementation

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCBooleanPrivate.h:25
&gt; +</span >

Remove this extra line

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:49
&gt; +typedef HashMap&lt;const gchar*, GRefPtr&lt;JSCValue&gt; &gt; ValueMap;</span >

const char*? Who is the owner of that pointer? How do you know it will be alive for the life of the map? Use CString better. Also you don't need the extra space between &gt; &gt;

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:55
&gt; +    _JSCContextPrivate()
&gt; +    {
&gt; +        context = JSRetainPtr&lt;JSGlobalContextRef&gt;(Adopt, JSGlobalContextCreate(nullptr));
&gt; +    }</span >

I think we can add a GObjectClass::constructed implementation and do all the initializations there.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:60
&gt; +    ~_JSCContextPrivate()
&gt; +    {
&gt; +        context.clear();
&gt; +    }</span >

This is done automatically, you don't need to explicitly clear the smart pointer.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:74
&gt; +static void jscContextDispose(GObject* obj)
&gt; +{
&gt; +    JSCContextPrivate* priv = JSC_CONTEXT(obj)-&gt;priv;
&gt; +
&gt; +    if (priv-&gt;cachedValues.size() &gt; 0)
&gt; +        priv-&gt;cachedValues.clear();
&gt; +}</span >

We don't need this unless we really want to explicitly clear the cache on dispose. This will be done automatically by the JSCContextPrivate destructor on finalize().

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:89
&gt; +    JSCContextPrivate* priv = context-&gt;priv;
&gt; +
&gt; +    return priv-&gt;context.get();</span >

return context-&gt;priv-&gt;context.get();

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:122
&gt; +        return JSC_VALUE(jscStringCreate(context, jsValue));
&gt; +
&gt; +    if (JSValueIsBoolean(priv-&gt;context.get(), jsValue))
&gt; +        return JSC_VALUE(jscBooleanCreate(context, jsValue));
&gt; +
&gt; +    if (JSValueIsNumber(priv-&gt;context.get(), jsValue))
&gt; +        return JSC_VALUE(jscNumberCreate(context, jsValue));
&gt; +
&gt; +    if (JSValueIsUndefined(priv-&gt;context.get(), jsValue))
&gt; +        return JSC_VALUE(jscUndefinedCreate(context, jsValue));</span >

You don't need all these JSC_VALUE casts if Create functions return a JSCValue

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:125
&gt; +    if (JSValueIsNull(priv-&gt;context.get(), jsValue))
&gt; +        return nullptr;</span >

I'm not sure if we will need a null value implementation too. In any case, you are handling here the null value, but null is not allowed in jsc_context_set_value

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:165
&gt; +    if (!cachedValue) {
&gt; +        // If we don't have a cached value, we cache it
&gt; +        cachedValue = jsValueToJSCValue(context, jsValue);
&gt; +        priv-&gt;cachedValues.set(name, cachedValue);
&gt; +    } else {
&gt; +        // If we already have a cached value for this property, we check if the value has changed
&gt; +        JSValueRef cachedJSValue = jscValueGetJSValue(cachedValue);
&gt; +        if (!JSValueIsStrictEqual(priv-&gt;context.get(), jsValue, cachedJSValue)) {
&gt; +            cachedValue = jsValueToJSCValue(context, jsValue);
&gt; +            priv-&gt;cachedValues.set(name, cachedValue);
&gt; +        }
&gt; +    }</span >

This is not how we want to cache the values, I think. We should cache all wrapped values, not only the ones added to the global object. As I said in a previous review, let's forget about objects lifecycle for now, do not cache anything, to make this simpler, and then we can discuss, design and implement the way we want to handle objects lifecycle.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.cpp:189
&gt; +    JSObjectSetProperty(priv-&gt;context.get(), object, strName.get(), jsValue, kJSPropertyAttributeReadOnly, nullptr);</span >

Why kJSPropertyAttributeReadOnly? That means we can call this twice for the same name to update the value.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.h:51
&gt; +JSCContext*</span >

JSCContext* -&gt; JSCContext *

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.h:54
&gt; +JSCValue*</span >

JSCValue* -&gt; JSCValue *

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCContext.h:56
&gt; +jsc_context_get_value (JSCContext*  context,
&gt; +                       const gchar* name);</span >

Same here about the *

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCNumber.cpp:58
&gt; +JSCValue* jsc_number_new_double(JSCContext* context, gdouble value)</span >

This needs documentation

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCNumber.cpp:68
&gt; +JSCValue* jsc_number_new_int32(JSCContext* context, gint32 value)</span >

Ditto.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCNumber.cpp:78
&gt; +JSCValue* jsc_number_new_uint32(JSCContext* context, guint32 value)</span >

Ditto.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCNumber.cpp:110
&gt; +gdouble jsc_number_get_double(JSCNumber* number)</span >

Since all other JSCValue implementations use the pattern jsc_foo_get_value, maybe for numbr we could use jsc_number_get_value_as_double|int32|uint32

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCNumber.cpp:125
&gt; +guint jsc_number_get_uint32(JSCNumber* number)</span >

guint -&gt; guint32

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCNumber.cpp:140
&gt; +gint jsc_number_get_int32(JSCNumber* number)</span >

gint -&gt; gint32

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCNumber.h:62
&gt; +jsc_number_get_double (JSCNumber*);</span >

Do not omit parameter names in public headers

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCPrivate.h:22
&gt; +#define WEBKIT_DEFINE_SIMPLE_TYPE(TypeName, type_name, TYPE_PARENT) \</span >

Why is this needed? What's different compared to G_DEFINE_TYPE?

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCString.cpp:39
&gt; +WEBKIT_DEFINE_SIMPLE_TYPE(JSCString, jsc_string, JSC_TYPE_VALUE)</span >

Can't we use G_DEFINE_TYPE here?

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCString.cpp:97
&gt; +    return g_strdup(&quot;the string value&quot;);</span >

What? I guess this should be return buff

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCValue.cpp:53
&gt; +    kPROP_0,</span >

Do not use k prefix for this

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCValue.cpp:58
&gt; +static void jscValueGetProperty(GObject* obj, guint prop_id, GValue* value, GParamSpec* param_spec)</span >

obj -&gt;object, prop_id -&gt; propID, param_spec -&gt; paramSpec

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCValue.cpp:64
&gt; +        g_value_set_object(value, priv-&gt;context);</span >

g_value_set_object(value, JSC_VALUE(obj)-&gt;priv-&gt;context);

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCValue.cpp:71
&gt; +static void jscValueSetProperty(GObject* obj, guint prop_id, const GValue* value, GParamSpec* param_spec)</span >

obj -&gt;object, prop_id -&gt; propID, param_spec -&gt; paramSpec

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCValue.cpp:79
&gt; +        g_object_add_weak_pointer(G_OBJECT(context), (gpointer*)&amp;priv-&gt;context);</span >

Use C++ style cast. I'm not sure I understand this weak pointer, since we only null check the context in dispose method. I think the context should never be released if it still contains values, so values should take a reference to the context.

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCValue.cpp:123
&gt; +            (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));</span >

static_cast&lt;GParamFlags&gt;()

<span class="quote">&gt; Source/JavaScriptCore/API/glib/JSCValue.cpp:132
&gt; +    JSCValuePrivate* priv = value-&gt;priv;
&gt; +
&gt; +    return priv-&gt;value;</span >

return value-&gt;priv-&gt;value;

<span class="quote">&gt; Source/JavaScriptCore/API/glib/jsc.h:28
&gt; +</span >

JSCUndefined is missing here.

<span class="quote">&gt; Source/JavaScriptCore/PlatformGTK.cmake:52
&gt; +if (ENABLE_JSC_GLIB)</span >

As I said in my previous review: I don't think we should make this conditional. It doesn't add any new dependency and the api should always be available.

<span class="quote">&gt; Tools/ChangeLog:17
&gt; +        * TestWebKitAPI/Tests/JavaScriptCoreGlib/TestJSCBoolean.cpp: Added.</span >

Since we already have a TestWebKitAPI/Tests/JavaScriptCore dir that is currently empty, I would add a glib subdir there for our tests.

<span class="quote">&gt; Tools/TestWebKitAPI/JavaScriptCoreGlib/main.cpp:26
&gt; +#include &quot;Tests/JavaScriptCoreGlib/TestJSCBoolean.h&quot;
&gt; +#include &quot;Tests/JavaScriptCoreGlib/TestJSCContext.h&quot;
&gt; +#include &quot;Tests/JavaScriptCoreGlib/TestJSCNumber.h&quot;
&gt; +#include &quot;Tests/JavaScriptCoreGlib/TestJSCString.h&quot;
&gt; +#include &quot;Tests/JavaScriptCoreGlib/TestJSCUndefined.h&quot;</span >

The main should be in Tests/JavaScriptCoreGlib/ too. Do not add a file for every test case, move them all here to the same file and rename this as TestJSCValue for example

<span class="quote">&gt; Tools/TestWebKitAPI/JavaScriptCoreGlib/main.cpp:34
&gt; +    g_test_add_func(&quot;/JavaScriptCoreGlib/JSCContext&quot;,   testJSCContext);</span >

And for tests cases I would use /jsc/jsc-value/foo pattern

<span class="quote">&gt; Tools/TestWebKitAPI/PlatformGTK.cmake:165
&gt; +    add_executable(TestJavaScriptCoreGlib</span >

This is created in bin directlry, it should be in ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/JavaScriptCore/glib, I think you need to use add_test()

<span class="quote">&gt; Tools/TestWebKitAPI/Tests/JavaScriptCoreGlib/TestJSCBoolean.cpp:36
&gt; +    getValue = jsc_context_get_value(context, &quot;true&quot;);</span >

JSCValue* getValue = jsc_context_get_value(context, &quot;true&quot;);

<span class="quote">&gt; Tools/TestWebKitAPI/Tests/JavaScriptCoreGlib/TestJSCContext.cpp:35
&gt; +    JSCContext* context = jsc_context_new();
&gt; +    g_object_add_weak_pointer(G_OBJECT(context), (gpointer*)&amp;context);
&gt; +
&gt; +    g_object_ref(context);
&gt; +    g_object_unref(context);
&gt; +    g_assert(context);
&gt; +
&gt; +    g_object_unref(context);
&gt; +    g_assert(!context);</span >

Here you are actually testing GObject weak references, since you are checking that GObject is setting the pointer to null when destroyed. I don't think we need a specific test case for contexts, since they ar eused everywhere, they will be tested in all other tests.

<span class="quote">&gt; Tools/TestWebKitAPI/Tests/JavaScriptCoreGlib/TestJSCNumber.cpp:83
&gt; +    g_assert_cmpfloat(jsc_number_get_uint32(JSC_NUMBER(n)), ==, 4294967295);</span >

g_assert_cmpuint

<span class="quote">&gt; Tools/TestWebKitAPI/Tests/JavaScriptCoreGlib/TestJSCNumber.cpp:116
&gt; +    g_assert_cmpfloat(jsc_number_get_int32(JSC_NUMBER(n)), ==, -2147483648);</span >

g_assert_cmpint

<span class="quote">&gt; Tools/TestWebKitAPI/Tests/JavaScriptCoreGlib/TestJSCUndefined.cpp:40
&gt; +    g_assert(JSC_IS_VALUE(nonExistant));
&gt; +    g_assert(JSC_IS_UNDEFINED(nonExistant));</span >

This is redundant, if it's UNDEFINED, it's VALUE</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are the assignee for the bug.</li>
      </ul>
    </body>
</html>