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 12845 - Disallow shadowing attributes
Summary: Disallow shadowing attributes
Status: RESOLVED FIXED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: WebIDL (show other bugs)
Version: unspecified
Hardware: All All
: P2 normal
Target Milestone: ---
Assignee: Cameron McCormack
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 12844
  Show dependency treegraph
 
Reported: 2011-06-01 15:04 UTC by Ms2ger
Modified: 2016-05-03 07:54 UTC (History)
12 users (show)

See Also:
powelld584: needinfo? (powelld584)


Attachments
being shadowed can u tell me the source (29.29 KB, application/pdf)
2016-05-03 07:52 UTC, gnA
Details

Description Ms2ger 2011-06-01 15:04:54 UTC
The reasoning in bug 12844 applies generally, and it seems better to disallow them in WebIDL. One problem is the pattern

interface Foo {
  readonly attribute DOMString quux;
};
interface Bar : Foo {
  attribute DOMString quux;
};

(currently used in HTMLOptionsCollection.length). Boris suggests he'd prefer a syntax for defining just a setter.
Comment 1 Boris Zbarsky 2011-06-01 15:15:23 UTC
After I suggested that, I realized that ES has no way to express it unless the ES binding says explicitly that the getter is copied from the ancestor interface when defining the property on the proto of the derived interface (which would be fine by me).
Comment 2 Jonas Sicking (Not reading bugmail) 2011-06-01 16:16:58 UTC
Are there other examples of this than HTMLOptionsCollection.length? Do we expect others to appear?

This is a pretty strange so it seems likely to me that the answer to the above two questions is "no".

If that's the case, we could just make the property read/write on the base interface and make the setter throw.

In fact, can we do that for now and try to deal on a WebIDL level if the need artists in the future?
Comment 3 Boris Zbarsky 2011-06-01 16:21:58 UTC
There's apparently HTMLElement.disabled (which is readonly) vs HTMLInputElement.disabled (and textarea, etc)...
Comment 4 Allen Wirfs-Brock 2011-06-01 16:43:29 UTC
(In reply to comment #2)
> Are there other examples of this than HTMLOptionsCollection.length? Do we
> expect others to appear?
> 
> This is a pretty strange so it seems likely to me that the answer to the above
> two questions is "no".
> 

I think it would be fine for the Web IDL ES binding to explicitly say that the getter is copied down in these situations. I think this matches the expectation of interface designers.  If you really want to over-ride both the getter and setter you would need to explicitly specify that anyway.

The problem of clobbering the getter when defining a setter actually occurs anytime you use javascript objects to represent mix'n'match access and update behaviors that can be combined via prototype inheritance.

See for example, here is code fragment from https://github.com/allenwb/jsmirrors/blob/master/mirrors.js that exhibits it:

function mixinFunctionJSONMutableMirror(proto) {
   return Obj.create(proto,{
      //Implements functionMutableMirrorInterface
      name: {get: inheritedGetter(proto,"name"),
        set: function(n) {this.__domain[this.__ser].name=jsonReflectedValue(n)}},
      source: {get: inheritedGetter(proto,"source"),
        set: function(s) {this.__domain[this.__ser].src=jsonReflectedValue(s)}}
    });
};

Note that getters had to be explicitly defined in a manner that that "copy down" the inherited getter.

There is even a proposal for adding syntax to ES.next to explicitly support this pattern.  See http://wiki.ecmascript.org/doku.php?id=strawman:object_initialiser_super
Comment 5 Cameron McCormack 2011-06-02 00:36:04 UTC
I'm not actually sure what the problem with the shadowing attribute is.  As others say, the property on Bar.prototype will need to have both a getter and a setter.  The spec defining these interfaces should just define what Bar::quux returns on getting.  That definition could be "Returns the same thing as Foo::quux".

One question is whether we need to make `Object.getOwnPropertyDescriptor(Foo.prototype, "quux").get == Object.getOwnPropertyDescriptor(Bar.prototype, "quux").get`.  I don't think we do.
Comment 6 Brendan Eich 2011-06-02 00:41:03 UTC
I don't understand what bug 12844 is about, maybe someone could clarify.

This bug seems invalid on its face. Shadowing attributes is perfectly doable in ES5 as noted.

/be
Comment 7 Allen Wirfs-Brock 2011-06-02 01:43:18 UTC
(In reply to comment #5)
> I'm not actually sure what the problem with the shadowing attribute is.  As
> others say, the property on Bar.prototype will need to have both a getter and a
> setter.  The spec defining these interfaces should just define what Bar::quux
> returns on getting.  That definition could be "Returns the same thing as
> Foo::quux".

My reading of the original question is that Bar wants to define the setter while continuing to inherit the getter from Foo.  (of course, these are just interfaces, but the binding needs to say what concretely happens.)

If that is the intended meaning, then it doesn't match a naive JS implementation because JS always defines getter/setter pairs.  JS doesn't have the concept of over-riding just a getter or just a setter.

There are at least 2 ways you might interpret this in a JS binding,
1) say that the implementation of Bar's quux (either in Bar.prototype or copied to avoid MI issues) uses the same getter function as Foo's quux.
2) say that the implementation of Bar's quux getter dynamically delegates Foo's guux getter as if by evaluating Foo.prototype.quux.call(this)

In solution 1, if somebody dynamically changes the getter of Foo quux is won't be seen by objects that implement the Bar interface.  In solution 2, such a dynamic change would be visible to Bars

> 
> One question is whether we need to make
> `Object.getOwnPropertyDescriptor(Foo.prototype, "quux").get ==
> Object.getOwnPropertyDescriptor(Bar.prototype, "quux").get`.  I don't think we
> do.

For solution 1, it could be defined so it came out either way. For solution 2 it is going to have to be false.

Solution 2 seems to be the directly we are heading in ES.next.  I'd recommend you go that route.
Comment 8 Boris Zbarsky 2011-06-02 02:11:01 UTC
> I'm not actually sure what the problem with the shadowing attribute is.

The main issue I see is that it's a footgun for spec writers.  If you allow this, then it becomes easy for someone to introduce an attribute on Element, say, that's shadowed by preexisting attributes on Element subclasses, and then suddenly things get very weird.

If shadowing were disallowed (and if it were, Mozilla's webidl impl at least would make it a compile-time error), this would be detected as soon as anyone tries to implement the new property.

For that matter, defining a property on some Element subclass that shadows a preexisting Element property is a footgun too.  If the getter or setter don't match what the Element property does (assuming it has both a getter and setter) you're introducing a compat issue.  So in practice when you shadow you need to specify the same behavior for the shadower and shadowee getter/setter (whichever exists).  At which point, why should WebIDL allow anything else?
Comment 9 Boris Zbarsky 2011-06-02 02:14:37 UTC
> I don't understand what bug 12844 is about

It's about the fact that some HTML element interfaces already have a "label" attribute but HTML5 is adding a "label" attribute on HTMLElement.  The question then arises whether that "label" is compatible with the preexisting ones and if not why not and if so why we need the attributes on the derived interfaces.

As in, my concerns in comment 8 are very non-hypothetical.  Feet are being shot off right as we speak.  ;)
Comment 10 Cameron McCormack 2011-06-07 04:48:56 UTC
A little Perl script tells me these are the shadowing attributes from HTML5:

HTMLElement.checked (readonly) shadowed by HTMLCommandElement
HTMLElement.checked (readonly) shadowed by HTMLInputElement
HTMLElement.disabled (readonly) shadowed by HTMLButtonElement
HTMLElement.disabled (readonly) shadowed by HTMLCommandElement
HTMLElement.disabled (readonly) shadowed by HTMLFieldSetElement
HTMLElement.disabled (readonly) shadowed by HTMLInputElement
HTMLElement.disabled (readonly) shadowed by HTMLKeygenElement
HTMLElement.disabled (readonly) shadowed by HTMLLinkElement
HTMLElement.disabled (readonly) shadowed by HTMLOptGroupElement
HTMLElement.disabled (readonly) shadowed by HTMLOptionElement
HTMLElement.disabled (readonly) shadowed by HTMLSelectElement
HTMLElement.disabled (readonly) shadowed by HTMLStyleElement
HTMLElement.disabled (readonly) shadowed by HTMLTextAreaElement
HTMLElement.icon (readonly) shadowed by HTMLCommandElement
HTMLElement.label (readonly) shadowed by HTMLCommandElement
HTMLElement.label (readonly) shadowed by HTMLMenuElement
HTMLElement.label (readonly) shadowed by HTMLOptGroupElement
HTMLElement.label (readonly) shadowed by HTMLOptionElement
HTMLElement.label (readonly) shadowed by HTMLTrackElement

  The ones on HTMLElement are "command API attributes".  Some of them are
  writable versions with compatible semantics on the shadowing interfaces (like
  HTMLCommandElement.checked and HTMLButtonElement.disabled).  Some of them
  aren't compatible, like HTMLTrackElement.label.

HTMLElement.onblur shadowed by HTMLBodyElement
HTMLElement.onblur shadowed by HTMLFrameSetElement
HTMLElement.onerror shadowed by HTMLBodyElement
HTMLElement.onerror shadowed by HTMLFrameSetElement
HTMLElement.onfocus shadowed by HTMLBodyElement
HTMLElement.onfocus shadowed by HTMLFrameSetElement
HTMLElement.onload shadowed by HTMLBodyElement
HTMLElement.onload shadowed by HTMLFrameSetElement
HTMLElement.onscroll shadowed by HTMLBodyElement
HTMLElement.onscroll shadowed by HTMLFrameSetElement

  I think these all exist because on <body> and <frameset>s these event listener
  attributes cause listeners to be registered on the window rather than the
  element.  Ian, do you expect

    <!DOCTYPE html>
    <body><script>
    document.body.onload = function() { };
    var desc = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "onload");
    alert(desc.get.call(document.body));
    </script>

  to alert null?  That's what I expect currently, footgun-ness aside.
Comment 11 Boris Zbarsky 2011-06-07 04:59:55 UTC
> Some of the aren't compatible

That seems like the sort of footgun issue we're talking about here.  Why shouldn't the command API be usable for <track>?  If there's a good reason, why does it not apply to random other HTML elements?
Comment 12 Cameron McCormack 2011-06-07 23:14:47 UTC
(In reply to comment #11)
> That seems like the sort of footgun issue we're talking about here.  Why
> shouldn't the command API be usable for <track>?  If there's a good reason, why
> does it not apply to random other HTML elements?

At a guess, I would say that the command API properties on HTMLElement exist to reflect the command-ness of elements that intrinsically define commands, such as <button>, <a href>, etc.  <command> lets authors define a custom command that doesn't correspond to a visible element.  The properties are defined to return ""/false on elements that don't define a command, including <track>.

So I guess the properties were put on HTMLElement because that's the common ancestor of the different elements that define commands.
Comment 13 Boris Zbarsky 2011-06-07 23:18:33 UTC
And I argue that if that's the case that's a spec design bug: it's adding lots of useless properties to most HTML elements.
Comment 14 Brendan Eich 2011-06-07 23:43:01 UTC
Some languages and systems with inheritance require you to say "override" or otherwise be explicit when shadowing. Would that suffice to save feet?

/be
Comment 15 Boris Zbarsky 2011-06-07 23:44:58 UTC
Are there good situations where you'd really want to override with incompatible behavior?
Comment 16 Brendan Eich 2011-06-07 23:47:42 UTC
Behavior is unspecified by types in such systems, and definitely in WebIDL. Can't write checks that WebIDL can't cash.

Why is behavior an issue here? Bad behavior can happen lots of ways. We don't try to stop it by outlawing expressiveness along any given axis.

/be
Comment 17 Allen Wirfs-Brock 2011-06-07 23:57:24 UTC
(In reply to comment #15)
> Are there good situations where you'd really want to override with incompatible
> behavior?

It's a pretty common situation to start with a class that defines mutable instances and then discover that you need to make a variation with immutable instances.  In a perfect would you would refactor and make the mutable class inherit from the immutable class.  But if you aren't allowed to do that refactoring (eg, you don't control the framework) you may expediently make the immutable version a sublass of the mutable version and over-ride all the mutation method to throw an error or perhaps silently do nothing.  Either of these is probably an incompatible behavior from the perspective of the original class specification.
Comment 18 Allen Wirfs-Brock 2011-06-08 00:11:21 UTC
(In reply to comment #16)
> Behavior is unspecified by types in such systems, and definitely in WebIDL.
> Can't write checks that WebIDL can't cash.
> 
> Why is behavior an issue here? Bad behavior can happen lots of ways. We don't
> try to stop it by outlawing expressiveness along any given axis.
> 
> /be

I think there were two actual issues at the beginning of this thread. First,if a super-interface says some attribute (property in JS terms) is readonly can an interface derived from it make that same attribute read/write.  The answer should be yes.  Adding write behavior is a specialization which is valid subtyping behavior.  (this seems like a WebIDL question that should be independent of language bindings)

The second issue is how does this map to JS if the attributes correspond to JS accessor properties as JS can't define an accessor set function without also defining its get function. This is presumably an issue for the WebIDL ECMAScript binding.  My suggest is that the answer is that an implementation of the derived writable interface must also implement the required inherited read behavior.  It can do this either by making the get side of the accessor delegate to the over-ridden get implementation or by providing a new get-side implementation that does the required.  It really seems more like an implementation decision rather than something that needs to be specified in the Es binding.
Comment 19 Cameron McCormack 2011-06-08 00:31:24 UTC
(In reply to comment #18)
> I think there were two actual issues at the beginning of this thread. First,if
> a super-interface says some attribute (property in JS terms) is readonly can an
> interface derived from it make that same attribute read/write.  The answer
> should be yes.  Adding write behavior is a specialization which is valid
> subtyping behavior.  (this seems like a WebIDL question that should be
> independent of language bindings)

I agree this should be allowed.

> The second issue is how does this map to JS if the attributes correspond to JS
> accessor properties as JS can't define an accessor set function without also
> defining its get function. This is presumably an issue for the WebIDL
> ECMAScript binding.  My suggest is that the answer is that an implementation of
> the derived writable interface must also implement the required inherited read
> behavior.  It can do this either by making the get side of the accessor
> delegate to the over-ridden get implementation or by providing a new get-side
> implementation that does the required.  It really seems more like an
> implementation decision rather than something that needs to be specified in the
> Es binding.

Whether the implementation has an independent implementation of the get behaviour or whether it defers to the super-interface's getter does sound like an implementation decision.  But one thing that is visible to scripts is whether the actual getter on the two properties' descriptors are the same Function object or not.  Web IDL doesn't say currently whether these Function objects need to be distinct objects or not.

The more general issue, whether overriding with different behaviour should be allowed by Web IDL or not, I'm still unsure about.  The problem is with *incompatible* behaviour, right?  Different behaviour is OK, as long as it is consistent with the promises made by the definition of the super-interface.  The difference between "different" and "incompatible" behaviour isn't one we can check for in the IDL.  If we think that "different but compatible" behaviour will never come up when designing Web APIs, then we can get a small win by disallowing overriding in general (apart from the readonly-becoming-writable issue).  OTOH, we could just file bugs on the specifications that specify incompatible behaviour on sub-interfaces as we find them...
Comment 20 Allen Wirfs-Brock 2011-06-08 01:06:07 UTC
(In reply to comment #19)

> 
> Whether the implementation has an independent implementation of the get
> behaviour or whether it defers to the super-interface's getter does sound like
> an implementation decision.  But one thing that is visible to scripts is
> whether the actual getter on the two properties' descriptors are the same
> Function object or not.  Web IDL doesn't say currently whether these Function
> objects need to be distinct objects or not.

In general, do you every say where you have the same or different function objects.  For example, if two different kinds of objects a and b both implement the method foo specified by interface Bar do you require that a.foo === b.foo? What about on the same object at different points in time (could an implementation start out with a placeholder version of method and then replace it upon first invocation?)

From an implementation perspective this would probably be best left unspecified.  But if you feel you must specify something then it should be that that every function occurrence is different (it's easy to make to uses of the same function appear different (wrapper one).  It's harder to make to different functions appear the same).

> 
> The more general issue, whether overriding with different behaviour should be
> allowed by Web IDL or not, I'm still unsure about. The problem is with
> *incompatible* behaviour, right?  Different behaviour is OK, as long as it is
> consistent with the promises made by the definition of the super-interface. 
> The difference between "different" and "incompatible" behaviour isn't one we
> can check for in the IDL.  If we think that "different but compatible"
> behaviour will never come up when designing Web APIs, then we can get a small
> win by disallowing overriding in general (apart from the
> readonly-becoming-writable issue).  

Can WebIDL really make any promises about what happens after user code starts changing things?  WebIDL can define the initial state of the Web interface objects but if an implementation allows user code to changing or replacing methods of these object then nothing can really be guaranteed after that point. Since browser implementations already allow this (and I don't think anybody is seriously proposing disallowing it) it seem pointless to try to forbid it now.


>      OTOH, we could just file bugs on the
> specifications that specify incompatible behaviour on sub-interfaces as we find
> them...

This seem like the right approach.  Don't write buggy,internally inconsistent specifications and when you find one fix it.  Nothing you say in a meta-specification is going to stop people from making mistakes or creating poor designs.
Comment 21 Cameron McCormack 2011-06-08 02:35:54 UTC
(In reply to comment #20)
> In general, do you every say where you have the same or different function
> objects.  For example, if two different kinds of objects a and b both implement
> the method foo specified by interface Bar do you require that a.foo === b.foo?

No.

> What about on the same object at different points in time (could an
> implementation start out with a placeholder version of method and then replace
> it upon first invocation?)

No, the document only gives requirements on what objects should look like at startup.

> From an implementation perspective this would probably be best left
> unspecified.  But if you feel you must specify something then it should be that
> that every function occurrence is different (it's easy to make to uses of the
> same function appear different (wrapper one).  It's harder to make to different
> functions appear the same).

That sounds reasonable.  I think you are right though that this likely doesn't warrant specifying.

> > The more general issue, whether overriding with different behaviour should be
> > allowed by Web IDL or not, I'm still unsure about. The problem is with
> > *incompatible* behaviour, right?  Different behaviour is OK, as long as it is
> > consistent with the promises made by the definition of the super-interface. 
> > The difference between "different" and "incompatible" behaviour isn't one we
> > can check for in the IDL.  If we think that "different but compatible"
> > behaviour will never come up when designing Web APIs, then we can get a small
> > win by disallowing overriding in general (apart from the
> > readonly-becoming-writable issue).  
> 
> Can WebIDL really make any promises about what happens after user code starts
> changing things?

It can make promises about the behaviour of certain Function objects when they are called.

> WebIDL can define the initial state of the Web interface
> objects but if an implementation allows user code to changing or replacing
> methods of these object then nothing can really be guaranteed after that
> point.

Guaranteeing nothing seems a bit much.  I think there is plenty you can guarantee.  If you have

  interface Node {
    readonly attribute Node? parentNode;
  };

and script does

  var f = Object.getOwnPropertyDescriptor(Node.prototype, "parentNode").get;
  Object.defineProperty(Node.prototype, "parentNode", { get: function() { } });

then it's not "all bets off"; the guarantee that calling 'f' on a Node object returns the Node's parent should still hold.  The spec doesn't make guarantees on what `myNode.parentNode` will do explicitly.

> Since browser implementations already allow this (and I don't think anybody is
> seriously proposing disallowing it) it seem pointless to try to forbid it now.

Allow user script to modify prototype objects such that sub-interfaces have incompatible behaviour, do you mean?  They can of course, but I'm not sure that helps determine whether we want to allow or disallow specifications from doing it.

> >      OTOH, we could just file bugs on the
> > specifications that specify incompatible behaviour on sub-interfaces as we find
> > them...
> 
> This seem like the right approach.  Don't write buggy,internally inconsistent
> specifications and when you find one fix it.  Nothing you say in a
> meta-specification is going to stop people from making mistakes or creating
> poor designs.

Although I did recently outlaw sequences from being used as the type of an attribute, since it has suboptimal behaviour when used in a natural way -- bug 12287 -- I'm inclined to agree with Allen in general here.  There are only a few instances of this in HTML5 at the moment.  If we consider them to be footguns, let's raise bugs on them (as Ms2ger has done).
Comment 22 Boris Zbarsky 2011-06-08 05:13:25 UTC
> you may expediently make the immutable version a sublass of the mutable version
> and over-ride all the mutation method to throw an error

That's not a workable solution for a web spec, because you can explicitly call the "superclass" methods on the "subclass" instance (just grab them off the higher-up-the-chain proto and use .call()).

> Adding write behavior is a specialization which is valid subtyping behavior.

I agree; I would be quite happy with explicit WebIDL syntax for this, as I said.

> The second issue is how does this map to JS

That's a solvable problem; it doesn't matter to me that much how exactly we solve it.

> The problem is with *incompatible* behaviour, right? 

_A_ problem is when two prototypes on the proto chain of an element, say, both define a property and the two property getters do different things when called on that element.  In particular it breaks grabbing a property off the higher-up prototype and then applying its getter to all things that have that proto on the proto chain... unless that operation somehow makes sense for this element which has some other getter definition lower down on its proto chain.

I'm not sure I can think of an example of "different but compatible" behavior that doesn't run into that problem.  Can you?
Comment 23 Allen Wirfs-Brock 2011-06-08 05:42:33 UTC
(In reply to comment #22)

> 
> I'm not sure I can think of an example of "different but compatible" behavior
> that doesn't run into that problem.  Can you?

The conventional way this would be defined is you can replace a method with another that does everything the original did plus some other stuff.  Presumably anybody who is dependent upon the original behavior doesn't care about the "other stuff".  Adding a logging wrapper is a simple example.

More generally, I don't think it is the job of these specs. to try to bullet proof against every crazy thing somebody might do via reflection or debugging APIs, or other "exploits".

If you take a any method and apply it do the wrong kind of object, crazy things may happen.  If everything is implemented in JavaScipt then at least memory safety will be guaranteed by the language. If part of the system is implemented outside of JavaScript then it is the responsibility of the host object implementation to maintain memory safety in those situations.  Beyond that I don't think you can say very much that will be actionable by implementations without straitjacketing JavaScript code in ways that may not be either practical or desirable.
Comment 24 Boris Zbarsky 2011-06-08 05:47:01 UTC
My main point is that it doesn't make sense to put a property on HTMLElement if that property doesn't actually "work" for all HTML elements.  In that situation, it should just go on more derived interfaces as needed.  That is, every single instance of overriding I see in the HTML spec right now, with the exception of readwrite attributes overriding readonly ones, looks like a spec bug to me.

Which raises the question of why we want to allow those sorts of spec bugs....
Comment 25 Cameron McCormack 2011-06-09 00:07:41 UTC
One example of the kind of thing I was thinking about was how objects stringify.  Now, this isn't directly applicable because this is done with "stringifiers" in Web IDL as opposed to writing a toString operation, and besides operations are different from attributes -- but I think it's an analagous situation.

To me, Allen's general pattern of derived things doing additional work (like logging) makes sense to allow.  So I think we want to "allow these sort of spec bugs" only if there could never be non-buggy reasons for shadowing.

All of this applies equally to operations too, right?

The examples from HTML5 are deliberate, as far as I know, and not accidental shadowing.  Maybe Ian can say why it's preferable to have these properties on HTMLElement rather than on the separate interfaces where they actually apply.
Comment 26 Cameron McCormack 2011-06-14 02:24:56 UTC
(In reply to comment #25)
> To me, Allen's general pattern of derived things doing additional work (like
> logging) makes sense to allow.  So I think we want to "allow these sort of spec
> bugs" only if there could never be non-buggy reasons for shadowing.

(I meant disallow rather than allow, of course.)
Comment 27 Ian 'Hixie' Hickson 2011-06-14 04:26:38 UTC
The command API _does_ work on every HTML element, because you can use tabindex="" to make any element into a Command for the purposes of the command API. There are certain elements where it isn't useful, e.g. it doesn't make sense really for <input type=range>, though it does make sense for <input type=button>, but like most of the global features, it makes sense most of the time.

So e.g. HTMLTrackElement.label vs the command API label is a minor issue (you wouldn't sanely use <track> as a command, though I guess there might be some contrived situations in which you could expose its commandy behaviour if you tried and especially if you didn't care too much about whether your document was valid), but if we cared we could just make label="" be the label of the command if it's a <track> element, like we do with <option>. I haven't done that so far because it isn't ever going to be done by someone sane. Some of the other ones, e.g. disabled on <textarea> and its cousin on the command API, or label on <menu>, are less easy to deal with. Maybe better would be to have certain elements on which you cannot specify tabindex="", though so far global attributes haven't had such constraints defined (e.g. you can use hidden="" on <style> even though that would make no sense, or indeed can use tabindex="" on elements like <source> or <meta> or even <option> where it really doesn't make sense). That's orthogonal to what the DOM APIs do, though. If you want the global attributes to be less global, please file a separate bug.

My intent with shadowing these at the IDL level was that only the most derived one would exist. This stuff was written before we considered (or at least before I was aware of us considering) actually having stuff on non-leaf interfaces exposed on non-leaf interface objects. It's not a big deal that they both be there though, it'll just be one of those bits of trivia that is used in programming contests...

I'd be fine with making shadowing illegal so long as we introduced a feature whereby one could explicitly override something, as seen in various programming languages, e.g. from comment 0:

  interface Bar : Foo {
   attribute DOMString quux; override;
  }

That would avoid us making unintentional mistakes. Having said that, I'm not aware of us ever having made such a mistake.
Comment 28 Boris Zbarsky 2011-06-17 02:54:49 UTC
> Maybe better would be to have certain elements on which you cannot specify
> tabindex=""

Or maybe better would be to not use generic names for the command API that then lead to collisions?  It's not like you can prevent people tabbing to <textarea> anyway!

> It's not a big deal that they both be there though

It is, though, since the spec needs to define behavior for the "superclass" functions/getters/setters being applied to the "subclass" and currently it may or my not do so in sane ways due to the assumption that such things can't happen.

> Having said that, I'm not aware of us ever having made such a mistake.

Given your comments about <textarea>, I'm not convinced at all.
Comment 29 Cameron McCormack 2011-06-17 03:01:58 UTC
(In reply to comment #28)
> > It's not a big deal that they both be there though
> 
> It is, though, since the spec needs to define behavior for the "superclass"
> functions/getters/setters being applied to the "subclass" and currently it may
> or my not do so in sane ways due to the assumption that such things can't
> happen.

I've been assuming that the superclass version of the function would always keep working (or at least that the specification defines it so that it does).  So you could still do

  // maybe this alerts "a"
  alert(Superclass.prototype.theFunction.call(theObject));

  // and this alerts "b"
  theObject.theFunction();

If we are in the state that calling the superclass function would violate some invariants because the specification assumes that it cannot be called on the object, then that really would be a problem.  I don't think that's the case, though.
Comment 30 Ian 'Hixie' Hickson 2011-06-24 22:07:16 UTC
(In reply to comment #28)
> 
> Or maybe better would be to not use generic names for the command API that then
> lead to collisions?

The idea is specifically to reuse the attributes that already exist with the semantics we want, rather than introducing a whole new set of properties that replicate existing ones.


> It's not like you can prevent people tabbing to <textarea> anyway!

Tabbing to textarea isn't the problem. The only way textarea is a "problem" is that you can set an accesskey for it, which then makes it a command; you can then disable it, but the command won't be disabled because accesskey commands are never disabled, but the <textarea> itself will be disabled, so textarea.disabled will claim the command is disabled even though it isn't.

The problem here isn't that the attribute is shadowed, the problem is that the command API doesn't honour the <textarea disabled> state. The way to solve that is to make it honour that state. But that's a separate bug (please file it if you care about it).

Similarly with <track>, the problem is that it makes no sense for that to be a command, just like it makes no sense for it to be contenteditable="", tabindex=""ed, accesskey=""ed, or have many of the other global attributes applied to it.

If we care about fixing _that_, I can make the spec explicitly list all the elements on which these interactive attributes can be set. But that's a separate bug as well (please file it if you care about it).


(In reply to comment #29)
> 
> If we are in the state that calling the superclass function would violate some
> invariants because the specification assumes that it cannot be called on the
> object, then that really would be a problem.  I don't think that's the case,
> though.

I don't think it's the case either. However, I never intended for there to be two copies of these attributes. I'd like a way whereby I can just redefine the attribute on the subclass, e.g. to change it so that it is not readonly.
Comment 31 Boris Zbarsky 2011-06-25 02:43:19 UTC
> The problem here isn't that the attribute is shadowed, the problem is that the
> command API doesn't honour the <textarea disabled> state

Or maybe that a single boolean is being used to track two separate bits of state?

That is, .disabled on textarea does not have the same semantics as the command API .disabled...

> I'd like a way whereby I can just redefine the attribute on the subclass, e.g.
> to change it so that it is not readonly.

I agree we need a way for subclasses to add a setter to a superclass readonly attribute, for sure.
Comment 32 Garrett 2011-06-25 04:47:43 UTC
(In reply to comment #31)
> That is, .disabled on textarea does not have the same semantics as the command
> API .disabled...
> 
And most likely differs from MSIEs Element `disabled` property. 
http://msdn.microsoft.com/en-us/library/ms533732%28v=vs.85%29.aspx
Comment 33 Cameron McCormack 2011-06-26 22:39:33 UTC
(In reply to comment #31)
> > I'd like a way whereby I can just redefine the attribute on the subclass, e.g.
> > to change it so that it is not readonly.
> 
> I agree we need a way for subclasses to add a setter to a superclass readonly
> attribute, for sure.

I don't see any problem with allowing the SuperClass.prototype.quux to be a property with a getter only, and SubClass.prototype.quux to be a property with a getter and a setter, and both reflecting the same internal state.  That works with Web IDL as it is written today.  I don't see how allowing the derived interface to cause SuperClass.prototype.quux to grow a setter is any better.

Alternatively, just define quux on the ancestor interface to be writable in the first place, and define it to throw if its setter is called on an object that isn't derived from SubClass.
Comment 34 Cameron McCormack 2011-06-30 03:23:24 UTC
The more I think about having a derived interface affect something on the ancestor interface (making an accessor property grow a setter), the more weird it seems to me.  If we are to keep HTMLElement.prototype.disabled etc., I recommend either making the ancestor attribute writable in the first place, as Jonas suggests in comment 2, or simply adding a writable attribute on HTMLDerivedInterface as needed.
Comment 35 Boris Zbarsky 2011-06-30 03:34:27 UTC
> The more I think about having a derived interface affect something on the
> ancestor interface

No one proposed that.... the proposal was to have an IDL syntax for the derived interface declaring a setter on itself, not on the ancestor interface, while picking up the ancestor interface getter automatically.
Comment 36 Cameron McCormack 2011-06-30 03:45:45 UTC
(In reply to comment #35)
> No one proposed that.... the proposal was to have an IDL syntax for the derived
> interface declaring a setter on itself, not on the ancestor interface, while
> picking up the ancestor interface getter automatically.

Then I misread the earlier proposals, sorry.

As I mention, it's not too much trouble to state in prose that a derived interface's attribute's get behaviour is the same as the one on the ancestor interface.  But I can see that it would be advantageous to have that encoded in the IDL so that binding generators can implement that half of the writable property automatically, so... let me propose something.
Comment 37 Cameron McCormack 2011-06-30 04:42:14 UTC
OK, I've added syntax for this:

  interface Ancestor {
    readonly attribute DOMString whatever;
  };

  interface Derived : Ancestor {
    attribute DOMString whatever inherits getter;
  };

Object.getOwnPropertyDescriptor(Derived.protoype, "whatever").get will be a distinct object from Ancestor.prototype.whatever's, but they will have the same behaviour.  There is no need to define Derived::whatever's get behaviour in prose.

(I didn't use extended attributes for this since it's not really optional, language binding specific behaviour.)

http://dev.w3.org/cvsweb/2006/webapi/WebIDL/Overview.xml.diff?r1=1.328;r2=1.329;f=h
Comment 38 Ian 'Hixie' Hickson 2011-06-30 18:22:54 UTC
(In reply to comment #31)
> > The problem here isn't that the attribute is shadowed, the problem is that the
> > command API doesn't honour the <textarea disabled> state
> 
> Or maybe that a single boolean is being used to track two separate bits of
> state?

Well, there's no state at the command level for <textarea> here. An accesskey=""-created command is never disabled currently.


> That is, .disabled on textarea does not have the same semantics as the command
> API .disabled...

If these two having different semantics is a problem you care about, I can make them have the same semantics. Please file a separate bug for that.
Comment 39 gnA 2016-05-03 07:52:40 UTC
Created attachment 1641 [details]
being shadowed can u tell me the source
Comment 40 gnA 2016-05-03 07:54:59 UTC
Comment on attachment 1641 [details]
being shadowed can u tell me the source

Help me get rid of screen hacker