Re: HTMLCollection item() vs. namedItem() with [] syntax (detailed review of the DOM)

On Jul 9, 2007, at 2:50 AM, Simon Pieters wrote:

> (This is part of my detailed review of the Document Object Model  
> section.)
> For the HTMLCollection[1], the spec says:
>   In ECMAScript implementations, objects that implement the  
> HTMLCollection
>   interface must also have a [[Get]] method that, when invoked with a
>   property name that is a number, acts like the item() method would  
> when
>   invoked with that argument, and when invoked with a property name  
> that
>   is a string, acts like the namedItem() method would when invoked  
> with
>   that argument.
> ...and for HTMLFormControlsCollection and HTMLOptionsCollection, it  
> says:
>   In the ECMAScript DOM binding, objects implementing the
>   HTMLFormControlsCollection interface must support being dereferenced
>   using the square bracket notation, such that dereferencing with an
>   integer index is equivalent to invoking the item() method with that
>   index, and such that dereferencing with a string index is  
> equivalent to
>   invoking the namedItem() method with that index.
> Do these paragraphs mean the same thing? Why are they phrased  
> differently?

They are both subtly wrong because, logically, ECMAScript property  
names are always strings, and non-string arguments to the [] operator  
undergo an implicit toString conversion.

This is why for ECMAScript arrays, 0, 0.0, .0 and "0" all work as  
numeric subscripts for the built-in Array type, but "0.0" and ".0" do  

javascript:alert(["a"][0]) -> a
javascript:alert(["a"]["0"]) -> a
javascript:alert(["a"][0.0]) -> a
javascript:alert(["a"]["0.0"]) -> undefined
javascript:alert(["a"][.0]) -> a
javascript:alert(["a"][".0"]) -> undefined

The model here is that numeric values get converted to string and then  
string-compared with the appropriate string represetnation of an  
integer, so it does not matter how they are spelled. But strings  
undergo no conversion.

HTML collections should work in accordance with this if possible, the  
fact that they don't in Safari is a bug.

> In any case, they don't quite match reality.
> There are some points of non-interop here.
> When a string is used that looks like an integer in the base 8, or  
> looks like a number with decimals:
>   .elements["010"]
>   .elements["0.0"]
>   .elements["0."]
> ...then it is equivalent to .item() in Safari and IE7, and  
> equivalent to .namedItem() in Firefox and Opera.
> Another case is where the string starts with a dot, or looks like a  
> float with an exponent:
>   .elements[".0"]
>   .elements["0e0"]
> The above are equivalent to .item() in Safari and .namedItem() in  
> the others.
> We also have this case:
>   .elements["0.."]
> ...which is equivalent to .item(0) in IE and .namedItem("0..") in  
> the others. (What comes after the first dot doesn't matter.)
> Finally, when an array is used with more than one item:
>   .elements[["0","1"]]
> ...then IE uses the first item of the array whereas the others use  
> the array's .toString().
> Below is what IE7 seems to do, where "obj" is what you pass to the  
> [[Get]] method...
>  1. If obj is an array, let obj be the array's first item.

I don't think this is a special rule for arrays, that's just how it  
handles strings with a comma. I just tired  
javascript:alert(document.links["0,1"]) on a random page in IE and it  
gave me the first element of the links array.

>  2. If obj is an integer, a float or Infinity, then pass that  
> to .item()
>     and abort these steps.
>  3. If obj is a string, check whether the string matches the regex
>     /^(\d+)(\..*)?$/. If it does, pass $1 to .item() and abort these  
> steps.
>  4. Pass obj.toString() to .namedItem().

I think all of these steps are actually operating on strings, not  
general JavaScript values, so to correctly document what IE does you  
would have to reformulate purely in terms of strings.

> [1]
> -- 
> Simon Pieters
> Opera Software

Received on Monday, 9 July 2007 10:37:44 UTC