[webkit-dev] WebKit gobject bindings: Who is guiding their future?

Carlos Garcia Campos carlosgc at webkit.org
Mon Aug 29 01:16:30 PDT 2016

El sáb, 27-08-2016 a las 23:12 -0700, Darin Adler escribió:
> Hi folks.
> You may have noticed the substantial improvements we’ve made to our
> WebIDL support over the last year.
> Also, the last few days I’ve been working on one small exciting
> improvement to our JavaScript bindings. We can express exceptions as
> a special return value inside the DOM implementations,
> ExceptionOr<ReturnType>, instead of using an ExceptionCode& out
> argument. This has many benefits; one of them is that we don’t need
> the [RaisesException] family of extended attributes to generate
> JavaScript bindings. Instead the bindings use C++ templates to
> generate exception-propagating code when needed based on function
> return types without having to specify anything in the IDL.

Does that mean than from the WebIDL point of view all methods can now
raise a exception? If don't tell the code generator that a method can
raise a exception, we assume all could return a Exception?

> The first step in this direction is in
> <https://bugs.webkit.org/show_bug.cgi?id=161295>.

I'll take a look.

> For Objective-C bindings, our approach is now that instead of trying
> to implement WebIDL features, we instead hand maintain a legacy set
> of bindings as we change the underlying DOM implementation. This
> works because we decided to “freeze” the bindings and no longer
> intend to automatically generate them or have them automatically
> track additions to the web platform. For WebKit at Apple, we consider
> the Objective-C bindings a part of the legacy WebKit, and for the
> modern WebKit API (WebKit2) we use different approaches inside
> injected bundles, such as dynamically bridging from Swift and
> Objective-C to JavaScript rather statically bridging to the DOM.
> Stability is more important than features for our Objective-C
> bindings; they are there largely for compatibility rather than being
> our favorite forward-looking API for manipulating webpage content.

In the GTK+ port the GObject DOM bindings API is a key feature, and
it's used by most of the applications using WebKitGTK+. When we
switched to WebKit2 we realized we could keep the exactly same API,
exposed via injected bundle. This made porting applications from
WebKit1 to WebKit2 a lot easier, because it made possible to just move
some existing code to the injected bundle.

> For gobject bindings, I have not yet found a simple solution to
> moving forward. For most WebIDL features we have simply been coding
> the gobject bindings generator so it does not try to generate code
> for functions that make use of them. For this new exception approach
> we have another challenge: Unlike the Objective-C bindings or the
> JavaScript bindings, the signature of the gobject binding functions
> is different when an exception is involved, because there is a
> GError** out argument for each of them. So unlike JavaScript or
> Objective-C, both of which use an exception system for the bindings
> which does not affect function signatures, the gobject bindings
> generator today depends on exception extended attributes to determine
> what the interface is to each binding function. This is a problem I
> must solve to move forward with the new exception model for our DOM
> and WebIDL without breaking gobject bindings.

The GObject DOM bindings are part of the public WebKitGTK+ API, which
means we never break the backwards API/ABI compatibility. We realized
how problematic is that for a code that is autogenerated. That's we
deiced to split the API into "stable" and "unstable". The main
different is that we don't guarantee any compatibility for the unstable
part, and we require the users to define a macro to be able to actually
use it. Any new method or object that is added the bindings goes to the
unstable API, so it can't break anything. The stable part is a subset
of the DOM API, pretty much the same to what you have currently frozen
for Objective-C, I think. Only changes to those existing methods can
actually break something. In most of the cases the API/ABI is broken
but the build isn't affected. We have a script run by the bots to
detect those cases and fixing them is usually trivial. Build breaks
happen even less often and are the actual problem. In this particular
case, I think the exception system change is a exceptional case and not
the rule, so we could just find a solution for this, instead of a
general solution for something that doesn't happen that often.

> I see a few different options, maybe not all real practical ones:
> Option 1) Freeze gobject bindings as we did the Objective-C ones;
> stop auto generating them. Add new bindings by hand as desired and
> needed. This has major benefit for people working on WebIDL features
> for the JavaScript bindings; we have a lot of work to do on those and
> we are not easily able to make the gobject bindings come along. There
> are all sorts of new WebIDL features that we cannot easily implement
> for gobject without considerable effort, such as enum and union
> types, various types of overloading and default argument values,
> setlike, the list goes on and on and this has been going on for
> months at least already. There’s a good reason we did this “freezing”
> for Objective-C and it seems likely to be worthwhile for gobject too.
> This will also let us get rid of the 88 places in the IDL files where
> we have gobject-binding-specific #if statements, many of which were
> originally added for Objective-C and probably have not all been
> carefully audited.

That worked for Objective-C because the DOM bindings are no legacy
WebKit, but that's not the case of the GObject bindings. I never liked
the ifdefs in the idl files, maybe we can find a different way to move
that to the code generator itself to skip whatever.

> Option 2) Express the list of which functions have a GError** out
> argument as an explicit list of function names inside the gobject
> bindings generator and generate code accordingly. This is not all
> that farfetched given we already have .symbols files to help keep the
> set of gobject bindings functions stay stable, and there is already a
> list inside the bindings generator of functions that used to raise
> exceptions and therefore have a GError** out argument that is never
> used, showing that this issue is not a new one. Compared to (1) this
> is just a stopgap measure. It can keep existing functions working,
> but does not give us a clear path for what to do as we add more and
> more DOM APIs that don’t fit in with what the gobject binding code
> generator can do.

Exceptions are indeed the main cause of API breaks in GObject DOM
bindings, methods that now raise exceptions or the other way around.
New WebIDL features that don't fit in GObject model are not a problem
at all, as long as they don't affect the existing stable API, are there
other features planned that you think can break existing stable API?

> Option 3) Keep the extended attributes telling whether something
> raises exceptions in the IDL files as gobject-specific attributes
> that are ignored by the JavaScript bindings.
> Are there other practical options?

Yes, I think so, at least for the exceptions issue. If there will
actually be more changes like this maybe we need to find another
solution more general. But for the particular case of extensions, I
think we can find a different way to handle exceptions in GObject API.
We are using the GError because it's the GLib way, but it's very
problematic for generated code like this. We are limited to C, so we
can probably move to a global way to ask for exception. this could even
be limited to a particular object. We basically have a Exception member
in WebKitDOMObject base class that is reset for every method call, and
set in case of exception. Then we add webkit_dom_object_get_exception()
to query if there were a exception. That's not the GLib way, but DOM
bindings is a special API anyway. That would allow to change the
methods that can raise exceptions without affecting the API anymore. To
not break the API, we would need to collect the current methods in the
stable API that have a GError parameter, and handle them manually.

> I strongly prefer option 1, and I would like to hear from the people
> who are working to make the gobject bindings work well to get an idea
> of how they feel about this and how they’d like to proceed, before I
> decide what to do.

It actually depends on whether this is an exception or not. If you
really think that build is going to be broken often because of things
very difficult to do in the GObject bindings, then we should indeed
find a more general solution. Otherwise I prefer to solve this problem
now, and keep the existing way of generating the bindings. We can add a
rule that you can break the GObject DOM bindings build, to not block
your work, and I'll try to fix it asap as we currently do with WebKit2.

> — Darin
Carlos Garcia Campos

More information about the webkit-dev mailing list