WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
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
Details
Formatted Diff
Diff
Draft patch v2
(9.48 KB, patch)
2022-02-23 16:22 PST
,
Adrian Perez
no flags
Details
Formatted Diff
Diff
Patch
(16.66 KB, patch)
2022-03-02 14:56 PST
,
Adrian Perez
no flags
Details
Formatted Diff
Diff
Patch
(17.09 KB, patch)
2022-03-03 03:06 PST
,
Adrian Perez
no flags
Details
Formatted Diff
Diff
Patch
(17.10 KB, patch)
2022-03-07 15:12 PST
,
Adrian Perez
no flags
Details
Formatted Diff
Diff
Patch for landing
(18.19 KB, patch)
2022-03-11 07:24 PST
,
Adrian Perez
no flags
Details
Formatted Diff
Diff
Show Obsolete
(5)
View All
Add attachment
proposed patch, testcase, etc.
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)
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:1571 > +gpointer jsc_value_array_buffer_get_data(JSCValue* value, gsize* length)
Could there be a variant of `GBytes* jsc_value_array_buffer_get_data(JSCValue*)`? It would be safer and nicer for bindings.
Patrick Griffis
Comment 5
2022-03-02 10:10:01 PST
Comment hidden (obsolete)
(In reply to Patrick Griffis from
comment #4
)
> Could there be a variant of `GBytes* > jsc_value_array_buffer_get_data(JSCValue*)`?
I meant `GBytes* jsc_value_array_buffer_get_bytes(JSCValue*)`
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
Created
attachment 453665
[details]
Patch
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.
Top of Page
Format For Printing
XML
Clone This Bug