- From: Ryan Sleevi <sleevi@google.com>
- Date: Mon, 14 Jul 2014 13:07:26 -0700
- To: Domenic Denicola <domenic@domenicdenicola.com>
- Cc: Boris Zbarsky <bzbarsky@mit.edu>, "public-webcrypto@w3.org" <public-webcrypto@w3.org>
- Message-ID: <CACvaWvZL7VQSWbvcGHPjHFNcxMrB_PV2Pvp+oc4t6nPvdqoiMA@mail.gmail.com>
On Mon, Jul 14, 2014 at 1:03 PM, Domenic Denicola < domenic@domenicdenicola.com> wrote: > From: Boris Zbarsky <bzbarsky@MIT.EDU> > > >> 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. > > So first, I apologize Ryan for leaving out this crucial detail when we > went over this last. I know you've gone through a lot of back-and-forth to > make these particular properties behave well, and you're right that we did > seem satisfied with where things ended up. Boris brings up a point though > that we didn't properly consider. > > Also, given that I am stepping into this thread late, let me know if I get > something horribly wrong. > > I still think having these properties return objects (not class instances) > is great, as it massively simplifies the spec. But Boris is right that as > currently specced, it seems that each call to the getter creates a new > object by copying from the internal slot. This breaks expected JS > semantics, e.g. `key.algorithm !== key.algorithm` since each getter > invocation returns a new object. In general the guidance for getters is > that they should behave as much like data-properties as possible, e.g. the > returned value should not change unless something happens that could change > it. > > Now, let's say that we changed things around so that the internal slot > stored a JS object, and the getter just returned it directly. Then the > problem is that outside consumers could modify those objects. Is this bad? > Yes, because the spec depends on the integrity of the internal slots. OK, > so now we have a few options: > > 1. Lock down the objects. This only works if they are truly immutable (not > just readonly), but from a brief glance at the spec, that appears to be the > case? In that case, you can store a frozen object in the internal slot, > which is tamper-proof against consumers, and just return that same frozen > object every time, while also consulting it internally. If consumers try to > modify it, they will get an error (in strict mode). > 2. Use Boris's strategy, of separating the "model layer" [[algorithm]] > from the user-exposed "API layer" [[algorithm_exposed]]. Then > [[algorithm_exposed]] can be mutated by external consumers for whatever > reason, but that will not break anything, since it is just a manifestation > of the external values. (This strategy seems a bit overcomplicated because > WebIDL only supports getters, leading to [[algorithm]] + > [[algorithm_exposed]] + algorithm getter. In normal JS usage you would > probably just do [[algorithm]] + an exposed algorithm data property.) > 3. Bulletproof your spec algorithms against mutations to the object, e.g. > check for invalid values and throw/reject with appropriate errors. This is > how the ES spec does things, generally, but I am going to assume it is > probably a big pain to do here, and not really worth considering. Let me > know if I'm wrong! > > 1 seems nice to me; it provides a clear signal to users that modifying > these properties is not useful, and has a straightforward conceptual > model---you are actually tracking these values in JS objects, instead of > having to convert between layers and type systems. > > Others on the TAG have defended 2, saying that frozen JS objects are not > used very often, and also emphasizing the importance of separating the > model layer and the API layer. > > I think either would be OK. What do you think? > > Again, sorry that we're spending so much time on making these properties > into objects, especially after all the grief I already gave you on them. I > appreciate you being willing to chart new territory in this regard, since I > really think we have run up against a place where the path of least > resistance in WebIDL (a bunch of algorithm classes) is a very bad path. > Hopefully what we do here can help set a precedent for similar situations > in the future---I know your usage of internal slots has already inspired a > couple other specs, with great increases in clarity IMO. Our replies crossed in flight, but I think Option 2 still has issues (with respect to cloning), for the reason that you note internal slot storing JS object is tricky. So that leaves 1 and 3. 1 certainly has issues, even if it's clean. 3 seems to introduce a ton of boiler plate, and loses a lot of clarity for the spec, because now you can no longer rely on your pre-conditions still being valid.
Received on Monday, 14 July 2014 20:07:53 UTC