Re: Figuring out easier readonly interfaces

On Wed, Oct 2, 2013 at 2:50 PM, Boris Zbarsky <bzbarsky@mit.edu> wrote:
> On 10/2/13 5:42 PM, Tab Atkins Jr. wrote:
>>> Say you had a readonly<Node> and you got the "id" setter off
>>> Element.prototype and called it.  What would happen, and why?
>>
>>
>> What *should* happen is that it tries to set "id" on the Node
>> instance
>
>
> Uh... Back up.  What does that actually _mean_?  I think your problem is
> you're skipping steps and handwaving instead of actually carefully stepping
> through what happens here.
>
> What the "id" setter is defined to do at
> http://dom.spec.whatwg.org/#dom-element-id and then at
> http://dom.spec.whatwg.org/#concept-reflect and then at
> http://dom.spec.whatwg.org/#concept-element-attributes-set is to take the
> "this" object, make sure it "implements the Element interface", then take
> that Element's "attribute list" (which is some other totally unrelated
> object, presumably looked up in a WeakMap if you're going to self-host) and
> mutate it.
>
> Similarly, the "id" getter is defined to do all of those, except at the end
> get some information out of the "attribute list" instead of mutating it.
>
> That's the state of things right now.
>
> What will the state of things be in your proposal?  Will using .apply() on
> the getter off Element.prototype with a thisArg that's a readonly<Element>
> work?  If so, how?

As Allen just said, it seems like anything with hidden internal state
like this will work badly.  Anything that uses more "traditional" JS
semantics will work "okay", but anything using WeakMaps for hidden
state will just fail (it won't find the proxy in the weakmap), and
anything using closures for internal state will ignore the proxy
entirely.

Okay, so that's a no go in general.

IDEA 2:

Interfaces can opt into readonly behavior with a [ReadonlyCapable]
extended attribute, where they describe what happens when they're
constructed readonly.  Implementation-wise I think this is pretty
simple - one way would be to hold a weakmap of readonly objects, and
the relevant methods on the object can then check whether the 'this'
object is in the map and act readonly if so.  When you write
"readonly<Foo>", this is an IDL error if Foo isn't [ReadonlyCapable].
If it is, then whenever you return that object, you add it to the
implementation's weakmap as well.  If an interface is
[ReadonlyCapable], so must be its parent interfaces.

If a [MapClass] or [SetClass] interface is [ReadonlyCapable], it
automatically gets readonly behavior for its default Map/Set methods.

This does require you to keep in mind that the interface is capable of
readonly-ness when you extend it, but only for things that cause
mutations, and I think this is far easier than maintaining two
interfaces.

~TJ

Received on Wednesday, 2 October 2013 23:03:02 UTC