[whatwg] [dom] attributes collection not fully defined?

2013-05-29 Thread Michael Day

Hi,

In the definition of the Element.attributes collection here:

http://dom.spec.whatwg.org/#dom-element-attributes

It doesn't seem to describe the behaviour for setting direct properties 
of the attributes collection, and how they map to attributes.


For example, setting an attribute will create a property with the same 
name as the attribute:


div = document.createElement(div);
div.setAttribute(foo, bar);
alert(div.attributes.foo); // [Object Attr]

Except for read-only properties like length, which will not be shadowed 
by attributes:


div.setAttribute(length, 99);
alert(div.attributes.length); // 2

So far so good. Things get weird, though:

div.attributes.fruit = apple;
alert(div.attributes.fruit); // apple
div.setAttribute(fruit, orange);
alert(div.attributes.fruit); // [object Attr]
div.removeAttribute(fruit);
alert(div.attributes.fruit); // apple (!!!)

Firefox and Chrome seem to be inconsistent on this, but at least in some 
situations they will shadow the property with an attribute, then restore 
the original property when the attribute is removed.


You can have more fun by using Object.defineProperty to make the 
property read-only or unconfigurable, which Firefox and Chrome will 
again treat inconsistently.


The mind boggles. How are these pseudo-properties supposed to be 
implemented? What magic hook calls them to life?


The reason I ask is that jQuery = 1.9 uses div.attributes in its 
feature detection code, and it's causing us problems.


Best regards,

Michael

--
Prince: Print with CSS!
http://www.princexml.com


Re: [whatwg] [dom] attributes collection not fully defined?

2013-05-29 Thread Boris Zbarsky

On 5/29/13 11:08 PM, Michael Day wrote:

For example, setting an attribute will create a property with the same
name as the attribute:

 div = document.createElement(div);
 div.setAttribute(foo, bar);
 alert(div.attributes.foo); // [Object Attr]


The DOM spec as written right now does not support this.  This is a 
clear bug in the spec in that it's not web-compatible.  See 
https://www.w3.org/Bugs/Public/show_bug.cgi?id=21986



Except for read-only properties like length, which will not be shadowed
by attributes:

 div.setAttribute(length, 99);
 alert(div.attributes.length); // 2


This is the normal behavior for WebIDL things with a named getter.


 div.attributes.fruit = apple;
 alert(div.attributes.fruit); // apple
 div.setAttribute(fruit, orange);
 alert(div.attributes.fruit); // [object Attr]
 div.removeAttribute(fruit);
 alert(div.attributes.fruit); // apple (!!!)

Firefox and Chrome seem to be inconsistent on this, but at least in some
situations they will shadow the property with an attribute, then restore
the original property when the attribute is removed.


That is also the normal behavior for WebIDL things with a named getter.


The mind boggles. How are these pseudo-properties supposed to be
implemented? What magic hook calls them to life?


If Element.attributes were using a named getter, the behavior would be 
as defined in http://dev.w3.org/2006/webapi/WebIDL/#getownproperty and 
http://dev.w3.org/2006/webapi/WebIDL/#defineownproperty


Which is a bit dense but the short of it is:

1)  The interface defines some set of exposed names.
2)  Exposed names which would shadow something on the proto chain are
ignored at get time.
3)  Setting a property name that is not currently exposed creates a
property on the object.  If the name later becomes exposed, it will
shadow the value that was set.
4)  Setting a property name that is currently exposed does a Reject
(which means throw in strict mode, silently do nothing in
non-strict mode).  Unless there is a named setter, of course.

You can see all of this behavior in all sorts of other objects (e.g. in 
named access on an HTMLCollection)...


But again, the spec as currently written:

readonly attribute Attr[] attributes;

does not in fact define any named getter behavior and is simply wrong...

-Boris


Re: [whatwg] [dom] attributes collection not fully defined?

2013-05-29 Thread Michael Day

Hi Boris,

Thank you for the detailed explanation. Having the WebIDL named getter 
definition helps to simplify things.


This part still seems inconsistent with current browsers:


4)  Setting a property name that is currently exposed does a Reject
 (which means throw in strict mode, silently do nothing in
 non-strict mode).  Unless there is a named setter, of course.


If I set the property name which has already been used for an attribute, 
it still seems to store the value:


div.setAttribute(fruit, orange);
div.attributes.fruit = apple;
div.removeAttribute(fruit);
alert(div.attributes.fruit); // apple

except for a very strange bug in Firefox only, where if I *read* the 
value before removing it, the attribute doesn't go away later:


div.setAttribute(fruit, orange);
div.attributes.fruit = apple;
alert(div.attributes.fruit.value); // orange
div.removeAttribute(fruit);
alert(div.attributes.fruit); // [object Attr] ???

Just adding the extra alert in the middle changes the value after 
removing the attribute, so that the Attr object is still returned.


Anyway, doing nothing or throwing if the user tries to write to a 
property which is currently exposed seems like a much better option.


Best regards,

Michael

--
Prince: Print with CSS!
http://www.princexml.com


Re: [whatwg] [dom] attributes collection not fully defined?

2013-05-29 Thread Boris Zbarsky

On 5/30/13 12:06 AM, Michael Day wrote:

This part still seems inconsistent with current browsers:


4)  Setting a property name that is currently exposed does a Reject
 (which means throw in strict mode, silently do nothing in
 non-strict mode).  Unless there is a named setter, of course.


Behavior here  varies.  From object to object and from browser to 
browser, depending on whatever bizarre implementation details the 
browsers happen to be using to implement the properties appear and 
disappear thing.


In particular, not all browsers are using WebIDL bindings for all 
objects yet, not even close.



except for a very strange bug in Firefox only, where if I *read* the
value before removing it, the attribute doesn't go away later:


Yep, that's a result of how this object is currently implemented in 
release Firefox (not as a WebIDL object).  It's a WebIDL object in 
Firefox nightly and Aurora builds if you want to test the behavior there.


It looks like I slightly misread what the spec says about the setting 
case.  Looks like for objects that do not have [OverrideBuiltins] 
setting will create/set a new own property that causes the property name 
to be hidden.  So this testcase:


div.setAttribute(fruit, orange);
div.attributes.fruit = apple;
alert(div.attributes.fruit); // apple
div.removeAttribute(fruit);
alert(div.attributes.fruit); // apple

alerts apple in current trunk Firefox both times, for example.

-Boris


Re: [whatwg] [dom] attributes collection not fully defined?

2013-05-29 Thread Jonas Sicking
On Wed, May 29, 2013 at 8:34 PM, Boris Zbarsky bzbar...@mit.edu wrote:
  div.attributes.fruit = apple;
  alert(div.attributes.fruit); // apple
  div.setAttribute(fruit, orange);
  alert(div.attributes.fruit); // [object Attr]
  div.removeAttribute(fruit);
  alert(div.attributes.fruit); // apple (!!!)

 Firefox and Chrome seem to be inconsistent on this, but at least in some
 situations they will shadow the property with an attribute, then restore
 the original property when the attribute is removed.

 That is also the normal behavior for WebIDL things with a named getter.

And this is why we should make named getter/setters a thing of the
past. New specs are still being written which use these WebIDL
features and almost all of them end up with confusing behavior like
this.

/ Jonas


Re: [whatwg] [dom] attributes collection not fully defined?

2013-05-29 Thread Michael Day

And this is why we should make named getter/setters a thing of the
past. New specs are still being written which use these WebIDL
features and almost all of them end up with confusing behavior like
this.


+1 +1 +1 +1e100 :)

Michael

--
Prince: Print with CSS!
http://www.princexml.com