Re: Spec for CryptoKey.algorithm and CryptoKey.usages doesn't really make sense

On Mon, Jul 14, 2014 at 12:16 PM, Boris Zbarsky <bzbarsky@mit.edu> wrote:

> Well, what's stored in the [[algorithm]] internal slot is an IDL
> dictionary, right?
>
> That's not the same thing as an interface...  I'm not sure how to make
> that clearer.
>
> Where in that is it made clear that http://heycam.github.io/
> webidl/#es-dictionary is what's getting invoked?  That's all I'm asking
> for here: that you s/interface/dictionary/ and ideally directly link to
> that link.  Even better would be fixing Web IDL to allow linking directly
> to the "An IDL dictionary value V is converted to an ECMAScript Object
> value" part, but that's not really under your control.


Aha! Now I understand the concern, got it.


>  As for why you can't modify the resulting object
>>
>
> I think we're talking past each other.  Can you clearly explain what your
> mental model is here?  I'm happy to accept plain English, ES6 spec terms,
> whatever, as long as you clearly explain what behavior you _think_ these
> objects should have.
>
> Right now nothing in the spec produces objects that "you can't modify".


So, I think we're in violent agreement that any modifications to .algorithm
/ .usages have no effect on the internal object or it's behaviour.

Where we're in disagreement / where I'm confused about is whether the
correct behaviour for

var x = ...;  // A CryptoKey

Scenario 1) x.algorithm = { foo: 'bar' };

Scenario 2) x.algorithm.foo = bar;

As it relates to Web IDL, ergo one can presume "every other spec", the
behaviour of Scenario 1 is to no-op (non-strict mode) or to throw a
TypeError (strict mode)

Now, Scenario 2 "shouldn't happen", because of the
dictionaries-as-attributes-being-forbidden. If we had the KeyAlgorithm
interface (versus dictionary), then Scenario 2 should fold into Scenario 1,
in as much as .algorithm returns the KeyAlgorithm platform object, and .foo
is an attempt to invoke a setter on a platform object, ergo no-op/TypeError.

Are we in agreement there?

If so, then the desired behaviour seems to be to reduce or eliminate the
distinction between Algorithm-as-a-Dictionary (from the TAG review) versus
KeyAlgorithm-as-an-interface (the original specification).

So having [[algorithm_copy]] (or whatever) seems to violate that, in that
it leads to different behaviour that KeyAlgorithm-as-an-interface.


> Sure.  The point is, it's always some dictionary inheriting from
> KeyAlgorithm, yes?


Yeah


>  Can you point to any explanation as to the "why"? I don't say so glibly,
>> it's just that multiple people from different organizations have clearly
>> different views on the "right" way to do things, and whether or not
>> something is really "desired".
>>
>
> I'm going to pass this off to Domenic, because he's written this sort of
> thing up before and can probably just link you to it.  But the gist of it
> is that that's the behavior JS programmers expect from their objects,
> basically.
>
>
>  For example, I could not find discussion that the rationale for not
>> exposing dictionaries is because they create new objects
>>
>
> From the horse's mouth, so to say: http://lists.w3.org/Archives/
> Public/public-script-coord/2012AprJun/0186.html
>
>
>  and separately heard requests that it does create new objects (from
>> non-Googlers, to be
>> clear)
>>
>
> There's no issue with exposing an API that returns a new object each time.
>  It just needs to be a method, not an attribute.
>
>
>  Since Web IDL declares read-only in terms of the absence of a setter
>> (and a possible TypeError), it seems that B is the only option that
>> matches Web IDL.
>>
>
> No, any of those options are fine in Web IDL.  You're confusing whether
> there is a setter on CryptoKey that would allow you to affect what sort of
> thing .algorithm involves (or which object it returns), and what the
> behavior of setting properties on the thing returned from .algorithm is.
>  We all agree CryptoKey should have no setter for this property.  We're
> disagreeing about what the getter should return.


Well, I'm not sure I see the two as separable, in that the goal here is to
maintain the "readonly" aspect of .algorithm, ideally in a way that is
identical to Web IDL.

What the getter returns is affected (potentially) by how the setter is
handled, hence the desire to treat the two together. In an 'ideal' world,
yes, the getter returns the same object, but I think that's only safe if we
don't allow the caller to influence that by the setter.

Perhaps I've been confused by your explanation. If we were to think of
KeyAlgorithm as an interface (rather than a Dictionary), it would seem to
align with Option C, in as much as the object is 'frozen' by virtue of no
setters / setters that throw TypeError, recursively?


> See above for where I think it should be documented.  But also, right now
> this is basically defined via "it stores whatever it stores".  And what's
> stored in the places that store to it is not "IDL objects" but "IDL
> dictionaries" and "IDL sequences" (for [[algorithm]] and [[usages]]
> respectively).
>

Terminology issue again. I suspect "IDL types" is the correct term here,
not "IDL objects", but sure, I can buy the need for more specificity.


>
> Ah, I see your concern.  So this _is_ one place where the HTML spec is
> less precise than it could be.  In this case, it's talking about the width
> and height internal slots, not actual JS-exposed properties of any sort.
>  You're correct that this could be made clearer, and it should be; we've
> learned a bit about spec writing since that text was written.
>
> Nevertheless, even though these are not called out as internal properties,
> that is what they are.


Yeah, I tried that handwaving, and Domenic rightfully raised concerns
during the TAG review.

So the question here, absent the editorial bandwidth in the specs I'm using
as references, is what is the best way to express this in a way that the
community has consensus?

Coming late to the party, I've tried to "do things as I see them", and been
met with a "Don't do that" many steps of the way, so for Web Crypto, it's
unclear what the concrete language needs to be in order to satisfy this, as
opposed to an series of iterations where I make a well-intentioned stab at
it, but then flail miserably.

Put differently, can you provide specific language that you think should be
done to address this, so that it's clear, or can you recommend someone who
is vested enough and with some degree of editorial bandwith to suggest
something? Otherwise, I feel like I'll be wasting everyone's time, mine
included, to make a stab here.


>
>  So naturally, on the Web Crypto side, it's equally frustrating that
>> there's
>> no "right way" to do this.
>>
>
> I think the right way to define structured cloning is as follows:
>
> 1)  Delegate to the generic algorithm for any values already covered by it
> (e.g. typed arrays, strings, plain objects, etc).
>
> 2)  Clearly define cloning behavior for any object that has a special set
> of internal slots.  This cloning behavior needs to define what to do for
> the value in each slot.
>
> -Boris
>

Well, 2) is unclear, especially in light of your comment about "these types
have internal slots, it's not clear in the spec" above.

As you note, declaring "structured clone" on an IDL type doesn't make
sense, since "structured clone" doesn't operate on such types. If we say
internal slots shouldn't hold IDL types, but converted ES types, well, then
you have the possibility of global state affecting such IDL types
throughout all of the spec's algorithms (not structured clone)

Put differently:
- If [[algorithm]] holds an IDL type, such as a dictionary, it can't refer
to structured clone
- If [[algorithm]] holds an ES type, such as an Object, then every time we
access [[algorithm]] in the spec (potentially asynchronously, via a
promise), then we're potentially returning to the ES global in a detectable
way
- Thus, we seem to need, for every internal slot, a [[foo]] and
[[foo_copy]] slot, where one holds an IDL type, the other holds an ES object

HOWEVER, the [[foo]] / [[foo_copy]] doesn't seem to solve the Structured
Clone problem, in that when I clone, if I structured clone [[foo_copy]],
the ES global might be able to affect the new object's [[foo_copy]].

Further, since I can't "directly" copy [[foo]], I presumably invoke the Web
IDL conversion from [[foo_copy]] to recreate [[foo]] on the new object. In
doing so, I again potentially have a return to the callers' JS environment,
which would then allow them to manipulate [[foo]] in ways that shouldn't be
permitted by the API (which only allows [[foo]] to be set via defined
interfaces)

In short, this feels like a mess, and I'm no clear what the right path
forward is, although I can see the problems you're referring to.

Received on Monday, 14 July 2014 19:41:08 UTC