RESOLVED FIXED 237088
[GLib] Expose ArrayBuffer in the public API
https://bugs.webkit.org/show_bug.cgi?id=237088
Summary [GLib] Expose ArrayBuffer in the public API
Adrian Perez
Reported 2022-02-23 08:47:37 PST
To allow passing binary data efficiently between the C/C++ world and the JavaScript world, we want to expose the ArrayBuffer primitive in the GLib public API. This is related to bug #197535 and will be a building block for it.
Attachments
Draft Patch (8.44 KB, patch)
2022-02-23 09:08 PST, Adrian Perez
no flags
Draft patch v2 (9.48 KB, patch)
2022-02-23 16:22 PST, Adrian Perez
no flags
Patch (16.66 KB, patch)
2022-03-02 14:56 PST, Adrian Perez
no flags
Patch (17.09 KB, patch)
2022-03-03 03:06 PST, Adrian Perez
no flags
Patch (17.10 KB, patch)
2022-03-07 15:12 PST, Adrian Perez
no flags
Patch for landing (18.19 KB, patch)
2022-03-11 07:24 PST, Adrian Perez
no flags
Adrian Perez
Comment 1 2022-02-23 09:08:22 PST
Created attachment 452988 [details] Draft Patch Missing some documentation and API tests, will add them later.
Adrian Perez
Comment 2 2022-02-23 16:22:13 PST
Created attachment 453048 [details] Draft patch v2 Now with documentation, tests still missing
Alberto Garcia
Comment 3 2022-03-02 07:14:43 PST
Comment on attachment 453048 [details] Draft patch v2 View in context: https://bugs.webkit.org/attachment.cgi?id=453048&action=review > Source/JavaScriptCore/API/glib/JSCValue.cpp:1486 > + * Creates a new %ArrayBuffer from existing @data in memory. It's implicit by the context, but you could still say that the new ArrayBuffer does not copy the data so the caller must keep the pointer valid while the object is alive. > Source/JavaScriptCore/API/glib/JSCValue.cpp:1567 > + * Returns: pointer to memory. (transfer none) ? > Source/JavaScriptCore/API/glib/JSCValue.h:261 > +JSC_API JSCValue * > +jsc_value_new_array_buffer (JSCContext *context, > + gpointer data, > + size_t length, > + gpointer user_data, > + GDestroyNotify destroy_notify); > + > +JSC_API gboolean > +jsc_value_is_array_buffer (JSCValue *value); > + > +JSC_API gpointer > +jsc_value_array_buffer_get_data (JSCValue *value, > + gsize *length); You use size_t in one case and gsize in the other one.
Patrick Griffis
Comment 4 2022-03-02 10:09:18 PST Comment hidden (obsolete)
Patrick Griffis
Comment 5 2022-03-02 10:10:01 PST Comment hidden (obsolete)
Adrian Perez
Comment 6 2022-03-02 13:35:13 PST
(In reply to Alberto Garcia from comment #3) > Comment on attachment 453048 [details] > Draft patch v2 > > View in context: > https://bugs.webkit.org/attachment.cgi?id=453048&action=review > > > Source/JavaScriptCore/API/glib/JSCValue.cpp:1486 > > + * Creates a new %ArrayBuffer from existing @data in memory. > > It's implicit by the context, but you could still say that the new > ArrayBuffer does not copy the data so the caller must keep the pointer valid > while the object is alive. Good idea, I'll rewrite the documentation to make this clear. > > Source/JavaScriptCore/API/glib/JSCValue.cpp:1567 > > + * Returns: pointer to memory. > > (transfer none) ? Good catch, I'll add the annotation. > > Source/JavaScriptCore/API/glib/JSCValue.h:261 > > +JSC_API JSCValue * > > +jsc_value_new_array_buffer (JSCContext *context, > > + gpointer data, > > + size_t length, > > + gpointer user_data, > > + GDestroyNotify destroy_notify); > > + > > +JSC_API gboolean > > +jsc_value_is_array_buffer (JSCValue *value); > > + > > +JSC_API gpointer > > +jsc_value_array_buffer_get_data (JSCValue *value, > > + gsize *length); > > You use size_t in one case and gsize in the other one. In practice doesn't matter (they are the same type) but for the sake of consistency let's use “gsize” as this is a GLib-style API header :)
Adrian Perez
Comment 7 2022-03-02 14:56:05 PST
Alberto Garcia
Comment 8 2022-03-03 00:54:10 PST
Comment on attachment 453665 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=453665&action=review > Source/JavaScriptCore/API/glib/JSCValue.cpp:1484 > + * jsc_value_new_array_buffer: > + * @context: A #JSCContext > + * @data: Pointer to a region of memory. > + * @length: Size in bytes of the memory region. > + * @user_data: (closure): user data. > + * @destroy_notify: (nullable): destroy notifier for @user_data. I think that since @user_data is only used for the destroy notifier it should probably come *afterwards* in the list of parameters. Compare g_bytes_new_with_free_func(), which has separate @data and @user_data like this one (https://docs.gtk.org/glib/ctor.Bytes.new_with_free_func.html) with g_source_set_callback(), where the same data pointer is also used for the destroy notifier (https://docs.gtk.org/glib/method.Source.set_callback.html).
Adrian Perez
Comment 9 2022-03-03 01:38:44 PST
(In reply to Alberto Garcia from comment #8) > Comment on attachment 453665 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=453665&action=review > > > Source/JavaScriptCore/API/glib/JSCValue.cpp:1484 > > + * jsc_value_new_array_buffer: > > + * @context: A #JSCContext > > + * @data: Pointer to a region of memory. > > + * @length: Size in bytes of the memory region. > > + * @user_data: (closure): user data. > > + * @destroy_notify: (nullable): destroy notifier for @user_data. > > I think that since @user_data is only used for the destroy notifier it > should probably come *afterwards* in the list of parameters. > > Compare g_bytes_new_with_free_func(), which has separate @data and > @user_data like this one > (https://docs.gtk.org/glib/ctor.Bytes.new_with_free_func.html) with > g_source_set_callback(), where the same data pointer is also used for the > destroy notifier (https://docs.gtk.org/glib/method.Source.set_callback.html). Good point, let's swap the order of the user_data and destroy_notify parameters to make this more consistent with other GLib-style APIs.
Adrian Perez
Comment 10 2022-03-03 03:06:02 PST
Created attachment 453715 [details] Patch New version, with parameters for jsc_value_new_array_buffer() swapped as suggested by Alberto, and documentation for jsc_value_array_buffer_get_data() hopefully clearer.
Alberto Garcia
Comment 11 2022-03-07 09:28:02 PST
Comment on attachment 453715 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=453715&action=review > Source/JavaScriptCore/API/glib/JSCValue.cpp:1566 > + * will be also stored in the pointed location. "will be also" -> "will also be". The patch looks otherwise fine to me, thanks!
Adrian Perez
Comment 12 2022-03-07 15:12:35 PST
Created attachment 454042 [details] Patch > "will be also" -> "will also be". Change applied, thanks for the suggestion.
Carlos Garcia Campos
Comment 13 2022-03-11 04:01:04 PST
Comment on attachment 454042 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=454042&action=review > Source/JavaScriptCore/API/glib/JSCValue.cpp:1510 > + * Returns: (transfer full): A #JSCValue or %NULL in case of exception > Source/JavaScriptCore/API/glib/JSCValue.cpp:1517 > + g_return_val_if_fail(JSC_IS_CONTEXT(context), nullptr); > + g_return_val_if_fail(data || !size, nullptr); Assuming it's valid to create and empty array buffer, I would add a test case for that too. > Source/JavaScriptCore/API/glib/JSCValue.cpp:1527 > + auto* jsArrayBuffer = JSObjectMakeArrayBufferWithBytesNoCopy(jsContext, data, length, deallocatorContext ? jscArrayBufferDeallocate : nullptr, deallocatorContext, &exception); Why not just always pass a function and simply return early if the given context is nullptr? We could use a lambda. > Source/JavaScriptCore/API/glib/JSCValue.cpp:1551 > + auto jsTypedArrayType = JSValueGetTypedArrayType(jsContext, value->priv->jsValue, &exception); This is confusing. I know this is how JSValueGetTypedArrayType is implemented, it checks if the given value is an ArrayBuffer and then returns kJSTypedArrayTypeArrayBuffer. I would add a comment here, or even better I prefer to be explicit here even if it's more code I would do the jsDynamicCast<JSArrayBuffer*>(vm, object) here
Adrian Perez
Comment 14 2022-03-11 05:25:59 PST
(In reply to Carlos Garcia Campos from comment #13) > Comment on attachment 454042 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=454042&action=review > > > Source/JavaScriptCore/API/glib/JSCValue.cpp:1510 > > + * Returns: (transfer full): A #JSCValue > > or %NULL in case of exception 👌️ > > Source/JavaScriptCore/API/glib/JSCValue.cpp:1517 > > + g_return_val_if_fail(JSC_IS_CONTEXT(context), nullptr); > > + > > g_return_val_if_fail(data || !size, nullptr); > > Assuming it's valid to create and empty array buffer, I would add a test > case for that too. Yes, it's valid to have a zero-sized ArrayBuffer. I missed that case when writing tests, I'll add it. > > Source/JavaScriptCore/API/glib/JSCValue.cpp:1527 > > + auto* jsArrayBuffer = JSObjectMakeArrayBufferWithBytesNoCopy(jsContext, data, length, deallocatorContext ? jscArrayBufferDeallocate : nullptr, deallocatorContext, &exception); > > Why not just always pass a function and simply return early if the given > context is nullptr? We could use a lambda. Good idea, the code will look a bit less messy that way. > > Source/JavaScriptCore/API/glib/JSCValue.cpp:1551 > > + auto jsTypedArrayType = JSValueGetTypedArrayType(jsContext, value->priv->jsValue, &exception); > > This is confusing. I know this is how JSValueGetTypedArrayType is > implemented, it checks if the given value is an ArrayBuffer and then returns > kJSTypedArrayTypeArrayBuffer. I would add a comment here, or even better I > prefer to be explicit here even if it's more code I would do the > jsDynamicCast<JSArrayBuffer*>(vm, object) here Sure, I can put the jsDynamicCast directly here for the sake of clarity. Thanks for all the comments!
Adrian Perez
Comment 15 2022-03-11 06:21:55 PST
Also, as per discusstion with Carlos Garcia in a private chat, we are going to change _array_buffer_get_length() to be _get_size(), because in GLib style APIs “size” is more commonly used for “amount of bytes” and “length” for “number of elements”.
Adrian Perez
Comment 16 2022-03-11 07:24:21 PST
Created attachment 454483 [details] Patch for landing
EWS
Comment 17 2022-03-11 14:56:58 PST
Committed r291194 (248350@main): <https://commits.webkit.org/248350@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 454483 [details].
Note You need to log in before you can comment on or make changes to this bug.