Re: DOM collections index out of bounds and JavaScript.

On 10/31/10, Cameron McCormack <cam@mcc.id.au> wrote:
> Garrett Smith:

[...]

>> The difference here is that the object that was passed in uses normal
>> ES syntax; it's pass by value (value of reference) not referenced by
>> the object. The effect is what you wanted, I think, and that is that
>> 1) the method that accepts the array makes a defensive copy of it and
>> 2) that the method (or getter) that returns the array always returns a
>> new copy of it.
>
> Yes, that’s the intent.
>

OK, glad we're on the same page. I think the wording of WebIDL should
be changed to reflect that because what it has now suggests passing a
copy. Instead, the method that accepts the object uses it for a copy
and discards it (this method can be trusted not to leak memory of the
object passed in).

>> But where is the array host object used?
>
> That’s for arrays – type T[] – not sequences.
>

Array host object is for arrays – type T[] –? Please explain more
about what that means.

>> That seems like the main issue to me. What are a Collection object's
>> indexed properties? Are they real object properties or is there a
>> proxy for [[Get]] and [[Has]]? Both behaviors can be seen in
>> implementations but it varies, depending on the implementation and on
>> the object.
>
> As currently defined, they are real properties.
>

OK, so no delegating to item, then.

And for each instance of implementation of a "collection" that use a
proxy, a bug should be filed against that implementation.

>> But where are proxies really needed? How important is it, for example,
>> for document.styleSheets[-1] to throw an "index out of bounds"
>> exception, or for document.childNodes(99999) to return null instead of
>> undefined?
>
> I think document.styleSheets[-1] returning null or throwing an exception
> is inconsistent with, say, regular ECMAScript arrays, so IMO that’s not
> something we should encourage.
>

You're right -- it's inconsistent with how property access works in
ES, but there's a conflict in existing DOM specs:

"Dereferencing with an integer index is equivalent to invoking the
item function with that index."

http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html

See the disparity? That means coll[ coll.length ] should be equivalent
to coll.item( coll.length ), which would result `null`. Why not just
allow `coll[ coll.length ]` to result `undefined`?

HTML 5 re-spec'd HTMLCollection in a way that requires indexed
property access to return `null` if the index is out of range.

http://www.w3.org/TR/html5/common-dom-interfaces.html#htmlcollection
| collection(index)
| Returns the item with index index from the collection.
| The items are sorted in tree order.
|
| Returns null if index is out of range.
^^^^^^^^^^^^^^

This requirement seems very strange to me. If `index` is out of range
for a call to `item`, then it returns null? The range for `index` is
unsigned long, that means that it is

 document.links[ 4294967295 ] // undefined
 document.links[ 4294967296 ] // null

Perhaps by "range," the author meant "a member of the collection". And
if that is what he meant, then why not spec that?

And then if we use that interpretation then there is the point of
contention about the property access resulting in `null` and not
`undefined` -- *that* is what we're discussing here, and you believe
that `undefined` would acceptable because it is follows native ES
semantics, requiring no proxy.

So property access should not be specified to delegate to item.

>> It seems that some implementations have gone out of the way to use
>> proxies to adhere to the spec to fulfill the odd cases above (albeit
>> inconsistently) while others have chosen to just use property access
>> to return undefined.
>
> I’m not sure that implementations are slavishly following the Web IDL
> spec just yet.
>

It is widely known and I've provided plenty of examples of this here
and on WHATWG mailing list that implementations do use proxies. Some
examples appear in "Adding ECMAScript 5 array extras to
HTMLCollection".

So the question is not "if" but "why": Why do implementations use
proxies? And if there is a reason for it, then why are they
inconsistent with other collections and other implementations? Is the
reason for that to support needed functionality? It seems that in some
cases, implementations try to adhere to DOM specs by making property
access delegate to `item`, but that nobody actually cares and that
resulting `undefined` would be equally satisfying to the needs of any
existing or proposed script.

>> How important are those cases? Do we have any bug reports for
>> implementations returning `undefined` instead of throwing/returning
>> null?
>
> I don’t know of bug reports.
>

Boris? Jonas? Travis? Hallvord? Anyone?

>> I get that the spec requires ob[n] to delegate to item, and so for
>> that a proxy is needed. But what type of situation is it really
>> necessary for obj[n] to delegate to item? Which Collections really
>> need a proxy to function as required by code?
>
> I’m not sure that proxies are required to make ob[n] delegate to item,

So where `x.item( -1 )` and `x( -1)` each throw an error, how do you
make x[ -1 ] do the same? You can't; not unless you use a proxy for
specialized [[Get]] access, which then forwards the call to `item`.
Some implementations do this for certain collections but others. It's
wildly inconsistent. If it mattered at all, wouldn't we be seeing bugs
on this and hearing implementors saying "no, it cannot happen" - ?

> as long as n is always the name of a property that exists on the object.
> That’s how the spec defines it at the moment: whenever there’s a
> “supported named property” (i.e., a value for n that is in range, as it
> were) then an accessor property must be defined on the object, where the
> getter calls item.
>

It seems you've done as Ian has and overloaded the term "range".
Instead, I think you mean "a value for n that is < length" or "in the
collection". And if I am right, I would rather that in the spec than
an overloading of the term "range".

> It’s the “define a property on the object at the right time” bit that
> could be tricky, though.
>

East for static collections; Constructing native ES arrays is roughly
the same process; why not make a method for internal use by
implementations based roughtly on that?
<http://ecma262-5.com/ELS5_HTML.htm#Section_15.4.2>

For live collections, it requires just writing precisely and
succinctly what implementations do. Entirely possible, but not for me;
not at this hour.

Garrett

Received on Tuesday, 2 November 2010 07:35:09 UTC