Re: WebIDL usage for Algorithms

Richard asked me to comment in this thread.  My apologies for the lack 
of sane threading/quoting; I wasn't subscribed to the list...

On Tue, Mar 11, 2014 at 3:07 PM, Mark Watson <watsonm@netflix.com> wrote:

> even type mapping to IDL "any" can throw an exception.

I believe this is incorrect.  http://heycam.github.io/webidl/#es-any 
doesn't mention any cases when it would, and certainly Gecko's 
implementation doesn't.

Converting an ES value to an IDL "object" type can in fact throw if the 
passed-in value is a primitive, though.

> It does seem that, longer term, it would make sense for WebIDL to
> incorporate Promises explicitly

It already has, in the spec.  Browser implementations may not have 
caught up yet; this is a recent change.

For example, http://heycam.github.io/webidl/#es-operations explicitly 
says that if an exception is thrown at any point during the steps 
defined for the function and the return type is a promise type, then the 
exception is caught and a promise rejected with that exception is returned.

So in your spec you should be able to just write:

   typedef (object or DOMString) AlgorithmIdentifier;
...

   Promise<any> encrypt(AlgorithmIdentifier algorithm,
                        Key key,
                        CryptoOperationData data);

and calling encrypt would never throw per current WebIDL spec (modulo 
things like out of memory exceptions, naturally; you can't exactly 
return a promise in that situation).  You do NOT have to explicitly do 
anything with "key" and "data" as the spec tries to do right now; they 
will be converted to the relevant WebIDL types before the method 
returns, but any resulting errors will be reported async via the 
returned promise that wraps the thrown exception.

What you _will_ have to do by hand, as things stand, is to explicitly 
call out when, if an object is passed, it is converted to the various 
WebIDL dictionary types the specification uses.  Since conversion to a 
WebIDL dictionary type can have side-effects, its ordering with other 
things needs to be precisely defined to avoid creating racy behavior. 
Doing it async is not the way to go, in my opinion; you want to go ahead 
and do it before you create the promise and get to the "asynchronously 
perform the remaining steps" bit.  That is, the "algorithm 
normalization" bit will happen synchronously before the method returns, 
but any exceptions from it will be reported asynchronously via the 
returned Promise.

One way to do this in your spec is probably to have an Algorithm 
dictionary type that just has a "name" attribute, to have a bunch of 
more specific dictionary types that do _not_ inherit from Algorithm or 
contain a "name" attribute, to manually invoke the "convert to an IDL 
dictionary type" algorithm from 
http://heycam.github.io/webidl/#es-dictionary at the right points, and 
then pass (Algorithm, OtherDictionary) pairs to anything that needs the 
name in addition to the information from the other dictionary.  You 
_could_ make the other dictionaries inherit from Algorithm, but then you 
have to worry about the getter for the "name" property on the object not 
being idempotent and what your spec should do if it returns a different 
value the second time around.

Ryan's proposal for synchronously creating a snapshot of the object 
passed in seems to me to be more complicated to specify than the above, 
for what it's worth, though I welcome him to prove me wrong with a 
concrete proposal about how it should work.

> WebIDL could consider having Dictionary IDL types carry with them a
> reference to the original object so that downcasts are possible.

That's true.  You have to be careful, because of the side-effects issue, 
but it might be possible to do this sort of thing.  Please send mail to 
public-script-coord?  I agree that dictionary inheritance is pretty 
weird in WebIDL right now...

Hope that helps,
Boris

Received on Thursday, 13 March 2014 18:45:58 UTC