I landed bug 780970 today, which adds [infallible], a new XPIDL attribute.

You can only use [infallible] within interfaces marked as
[builtinclass] (which means the interface may not be implemented in
JS), and [infallible] is only applicable at the moment on XPIDL
attributes which return primitives.  For example

[builtinclass]
interface nsIFoo {
  [infallible] attribute long foo; // ok

  [infallible] attribute nsIBar bar; // ERROR, nsIBar is not a primitive.
  [infallible] long doCalculation(); // ERROR, doCalculation is a
method, not an attribute.
}

[infallible] is a promise that your attribute's getter will never
return anything other than NS_OK, and, as a corollary, that the getter
will always assign a value to its outparam.

When you mark an attribute as infallible, we generate a helper in the
header file which lets you call the attribute's getter without using
an outparam.  For instance, if we ignore the erroneous lines in the
interface above, it is equivalent to:

[builtinclass]
interface nsIFoo {
  attribute long foo;

  %{C++
  inline int32_t GetFoo() {
    int32_t result;
    nsresult rv = GetFoo(&result);
    MOZ_ASSERT(NS_SUCCEEDED(rv));
    return result;
  }
  %}
}

So now you can do

  nsCOMPtr<nsIFoo> foo;
  int32_t f = foo->GetFoo();

A few things to note:

1. The MOZ_ASSERT is debug-only.  That means that in release builds,
if GetFoo(int32_t*) returns an error code and doesn't set *result,
GetFoo()'s return value will be undefined.  [infallible] is a promise
that we can't (at the moment) statically enforce, but it's a promise
nonetheless!  (If we ever get static analysis back up and running,
that infallible methods never fail would be a great thing to check.)

2. [infallible] does not change the implementation of nsFoo::GetFoo in
C++.  You still write the same NS_IMETHODIMP nsFoo::GetFoo(int32_t*)
that you used to, and you can still call GetFoo(int32_t*) if you want
to.  The only difference is that now you may also call GetFoo().

For an example of how to use [infallible], see [1, 2].

I encourage you to consider using [infallible] in new code for
attributes whose getters never fail.  Not only is it cleaner to call
such methods, but using [infallible] also draws attention to those
attributes which /may/ fail.

If this experiment goes well, I think we should expand [infallible] to
methods and to methods/attributes which return interfaces -- that is,
the two ERROR lines in the interface at the top would no longer be
errors.  There's no technical reason I can think of not to do this; I
just wanted to start small.


One reasonable question to ask at this point is: Why not make GetFoo()
the canonical implementation and either implement GetFoo(int32_t*) in
terms of GetFoo(), or otherwise modify XPCOM to call GetFoo()
directly?

There's some discussion of this in the bug, but basically: I rejected
the first approach because it meant that every call to GetFoo from
XPCOM would need to go through two virtual calls: GetFoo(int32_t*) and
then GetFoo().  Moreover, this approach doesn't let us avoid modifying
XPCOM, because we'd be adding a new virtual method to nsIFoo.  This
modifies nsIFoo's vtable, so XPCOM would need to be aware of this.

I think the second approach, of eliminating the outparam version of
GetFoo altogether, is definitely cleaner than what I've implemented.
It could yield a perf improvement, and it also means that the compiler
will enforce the rule that GetFoo can't fail.  But modifying XPCOM to
call an entirely new type of method was not an exciting proposition to
me.  Anyway, we can always make this modification at a later date.

Happy hacking,
-Justin

[1] https://hg.mozilla.org/integration/mozilla-inbound/rev/bd0bf4b676da
[2] https://hg.mozilla.org/integration/mozilla-inbound/rev/eb81ebe55d99
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to