This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 27354 - Internal slots
Summary: Internal slots
Status: RESOLVED MOVED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: WebIDL (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Cameron McCormack
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 24652 27355 27381
  Show dependency treegraph
 
Reported: 2014-11-17 18:47 UTC by Anne
Modified: 2017-12-06 11:03 UTC (History)
8 users (show)

See Also:


Attachments

Description Anne 2014-11-17 18:47:23 UTC
Within an object definition each attribute should automatically represent an internal slot of the object, preferably addressable as /object/@[[attributeName]] from prose. (Combined with the other bug on defining this, we could have this@[[attributeName]], which would be nice.)

This formalizes something specifications already do, and helps us lay the groundwork to better define creation of associated objects (in particular their Realm).


To accompany this we also need something like a [NoSlot] annotation. E.g. while innerHTML has a getter/setter pair, it does not need an internal slot. The return value is computed fresh and any caching is up to the UA.


We will also need a way to declare slots when there are no attributes available, e.g. in the case of getSelection(). Something like

  [[selection]] = Selection

would do.


And we need a way to define default values for these slots, by adding default values to attributes, e.g.

  readonly attribute boolean cancelable = false;


See http://lists.w3.org/Archives/Public/public-script-coord/2014OctDec/thread.html#msg156 for background.
Comment 1 Travis Leithead [MSFT] 2014-11-18 00:42:28 UTC
(In reply to Anne from comment #0)
> To accompany this we also need something like a [NoSlot] annotation. E.g.
> while innerHTML has a getter/setter pair, it does not need an internal slot.
> The return value is computed fresh and any caching is up to the UA.

Yes, for innerHTML this makes sense; however, I wonder if we're taking this too far. I'd prefer to leave this as an implementation detail--even for innerHTML you can imagine an implementation that "pre-computes" the result before a call and then returns it--invalidating it on every tree mutation. It's probably a bad implementation design, but illustrates that it is an implementation detail. I don't see why you would annotate the exclusion of this possibility from the spec's standpoint.
Comment 2 Boris Zbarsky 2014-11-18 01:00:18 UTC
I think the idea is to annotate the places where a spec is defined in terms of internal slots.   The spec for innerHTML wouldn't be.

In general, nothing requires an implementation to have any internal slots, of course; just to act as if it does if that's how a spec is defined.
Comment 3 Travis Leithead [MSFT] 2014-11-18 01:19:50 UTC
(In reply to Boris Zbarsky from comment #2)
> I think the idea is to annotate the places where a spec is defined in terms
> of internal slots.   The spec for innerHTML wouldn't be.
> 
> In general, nothing requires an implementation to have any internal slots,
> of course; just to act as if it does if that's how a spec is defined.

Would this allow Anne to replace text like this (from DOM4):

  The stopPropagation() method must set the stop propagation flag. 

With a reference to the Event's [[stopPropagation]] slot value?

In the same spec, he uses other prose to initialize various accessors:

  To initialize an event, with type, bubbles, and cancelable, run these steps: 
  1.Set the initialized flag. 
  2.If the dispatch flag is set, terminate these steps. 
  3.Unset the stop propagation flag, stop immediate propagation flag, and canceled flag. 
  4.Set the isTrusted attribute to false. 
  5.Set the target attribute to null. 
  6.Set the type attribute to type. 
  7.Set the bubbles attribute to bubbles. 
  8.Set the cancelable attribute to cancelable. 

This effectively is already treating the accessor properties as if they were data properties...?

Is the distinction really that necessary?
Comment 4 Boris Zbarsky 2014-11-18 02:27:20 UTC
> Would this allow Anne to replace text like this (from DOM4):

Possibly.

> This effectively is already treating the accessor properties as if they were
> data properties...?

It actually causes a lot of confusion, because it uses the same term "isTrusted" to refer to both the JS property and the internal state, and while the former is readonly the latter is not...  So when you talk about setting it, people aren't sure what you mean until they realize the same term is being used for two totally different things.

This is why it would be good to make a clear distinction between the externally visible props and the internal state, so you can unambiguously refer to one or the other.
Comment 5 Anne 2014-11-18 10:10:57 UTC
(In reply to Travis Leithead [MSFT] from comment #3)
> Is the distinction really that necessary?

Note that while having internal slots would make many specifications far less ambiguous about what is actually going on, the real driver here is bug 27355. When you instantiate an object, you need to figure out if it has associated objects that need to be instantiated as well (and make sure they all have the correct Realm). Having a concept of internal slots helps formalizing finding those associated objects.

interface Document {
  readonly attribute DOMImplementation implementation;
}

Helps establishing that when a Document is created, a DOMImplementation object is created as well and stored in Document's [[implementation]].

(A nice follow up might be to have default IDL getter/setter implementations for these scenarios. E.g. for the above the getter will simply return this@[[implementation]]. There's no need to spell that out in the specification anymore.)
Comment 6 Olli Pettay 2014-11-18 11:20:34 UTC
I'm tiny bit worried we end up having hard to read idls, though it is 
not quite clear to me what kind of syntax would be used here.

And talking about slots in idl feels wrong. Because if it is bug 27355
which is driving this, the key thing isn't slot or not-slot, since "slot"
doesn't really hint strongly that object and its slot belong always to the 
same Realm.
Why would Document.implementation be expressed as a slot, but
Event.target wouldn't be.

If we want the idl to explain that some attribute is supposed to be in the same
Realm as its owner, shouldn't the annotation be something like
[SameRealm] or so.
Comment 7 Anne 2014-11-18 11:32:55 UTC
Event's target attribute would also have an associated slot, expressed as

  readonly attribute EventTarget? target = null;

I don't think you have to worry about readability. Apart from adding default values and [NoSlot] nothing much would be affected.
Comment 8 Ian 'Hixie' Hickson 2014-11-20 18:39:39 UTC
After a long conversation with Anne on IRC, I really don't think this is a good idea.

- The [[slots]] stuff in ES6, IMHO, makes the ES6 spec very very hard to read. We really should not encourage that style in more specs.

- We already have the equivalent readable way to do this; HTML does it all over, for example. You just say that "A Foo object has a bar state" and then define things in terms of a bar state. (It's indeed a mistake to do this by reusing the names of exposed attributes; don't do that.)

- Anne suggested that this would help with defining what is going on when you use .call() to invoke a method from one object on another object of the same type, but I don't understand why that is hard to do today, nor why that problem really has anything to do with globals or slots.

- Anne suggested it might help with defining associated globals, but that seems like a non-issue to me. I don't understand the problem there at all. Why are globals hard to define in prose? It seems like a one or two sentence definition would cover all cases.

- Anne suggested it might help with changing prototypes during element adoption across global objects. First, I think changing prototypes at all here is a mistake (most browsers don't do it), and second, even if we do want to do this, it's just a bit of prose in the DOM spec.

- Anne suggested it might help with creation of objects, but I don't understand how.

- Anne said something about Object.observe(), but didn't elaborate. I'm guessing the idea is to be able to watch attributes. However, we want to be REALLY CAREFUL about which attributes we expose to Object.observe(), because every property we expose forces the implementation to not have lazy evaluation for that attribute. IMHO we should not make this trivial to spec. If there's a property we really want to expose, we should make that clear somehow, e.g. with an [Observable] annotation, and we should define in prose when the value changes.

None of this requires any changes to IDL.
Comment 9 Olli Pettay 2014-11-20 19:04:30 UTC
(In reply to Ian 'Hixie' Hickson from comment #8)
> - The [[slots]] stuff in ES6, IMHO, makes the ES6 spec very very hard to
> read. We really should not encourage that style in more specs.
I agree with this.

I can see some use of some kind of implicit "interface's member variables"
(I wouldn't call them slots) based on the attribute names. But in general specs
tend to be quite easy to read even without them. 


> - Anne said something about Object.observe(), but didn't elaborate. I'm
> guessing the idea is to be able to watch attributes. However, we want to be
> REALLY CAREFUL about which attributes we expose to Object.observe(), because
> every property we expose forces the implementation to not have lazy
> evaluation for that attribute. IMHO we should not make this trivial to spec.
> If there's a property we really want to expose, we should make that clear
> somehow, e.g. with an [Observable] annotation, and we should define in prose
> when the value changes.
That is bug 27381
Comment 10 Anne 2015-04-18 06:01:32 UTC
(In reply to Ian 'Hixie' Hickson from comment #8)
> - We already have the equivalent readable way to do this; HTML does it all
> over, for example. You just say that "A Foo object has a bar state" and then
> define things in terms of a bar state. (It's indeed a mistake to do this by
> reusing the names of exposed attributes; don't do that.)

This gets very verbose though, e.g. for Event. Currently Event and its many subclasses do not do this and instead rely on some implicit understanding of internal slots. I think it would be much better if we started making that concept a) explicit and b) easy to work with by having IDL do a bunch of it for you.
Comment 11 Tab Atkins Jr. 2015-04-22 19:50:18 UTC
(In reply to Anne from comment #10)
> (In reply to Ian 'Hixie' Hickson from comment #8)
> > - We already have the equivalent readable way to do this; HTML does it all
> > over, for example. You just say that "A Foo object has a bar state" and then
> > define things in terms of a bar state. (It's indeed a mistake to do this by
> > reusing the names of exposed attributes; don't do that.)
> 
> This gets very verbose though, e.g. for Event. Currently Event and its many
> subclasses do not do this and instead rely on some implicit understanding of
> internal slots. I think it would be much better if we started making that
> concept a) explicit and b) easy to work with by having IDL do a bunch of it
> for you.

In particular, Bikeshed makes this easy to talk about - it recognizes attributes named like "[[Foo]]" as private slots.  You just have to define them manually, rather than putting them in the WebIDL, currently.