indexed properties on NodeLists and HTMLCollections

Web IDL currently has an extended attribute [OverrideBuiltins], which
controls whether indexed and named properties get resolved in preference
to properties that already exist on the object (usually, properties from
the prototype); indexed properties being the array index like properties
exposed on objects like NodeLists and HTMLCollections.

I did some testing recently
http://people.mozilla.org/~cmccormack/tests/nodelist-indexed-override.html
and it seems that all of Firefox/Safari/Chrome/IE/Opera always treat
indexed properties as “overriding builtins”, so it looks like we should
just specify that and have [OverrideBuiltins] control just named
properties.  (Web compatibility means some objects with named properties
do need to be [OverrideBuiltins], and some not.)

Where it gets tricky is when the author puts array index like properties
on the object itself, and then causes indexed properties to want to
exist.  What Web IDL says to do at the moment is (paraphrasing):

  At the moment that a new indexed property should start existing (e.g.
  by adding a node to the document), the implementation should try to
  use Object.defineProperty to place a property on the object.  If that
  fails (e.g. because there was an existing non-configurable property on
  the object), then the indexed property just doesn’t get created.  If
  there was an existing configurable property, it gets replaced.

What Firefox does now is similar to this, except with some strangeness
due to the fact that these indexed properties are created lazily (the
strangeness being a bug).  To make Firefox follow the spec would likely
cause an unacceptable performance regression.  Currently objects like
NodeLists and HTMLCollections don’t track changes made to the document
and update their contents eagerly, and instead they just set a dirty
flag and recompute things later on when script requests it.  This is
incompatible with the need to check, at the time the property should
really start existing, what conflicting properties already exist on the
object.

It is also arguably confusing to authors if sometimes indexed properties
aren’t exposed on the object.

What Chrome/Safari do is to do property resolution for indexed
properties first before even looking at the underlying object, even if
the underlying properties are non-configurable.  It also means that
author defined properties on the object itself reappear once the indexed
property disappear (e.g. because you removed a node for the document).
This breaks the “host objects shouldn’t cause non-configurable
properties to appear configurable later on” rule.  I think you could
argue that it is conceptually cleaner than what Web IDL currently
requires, certainly easier for authors to understand (edge case though
it is – the same situation for named properties is less of an edge case,
I’d say).

This behaviour is, IIRC, what Web IDL used to require a while ago, when
it had explicit [[Get]] and [[Put]] definitions for host objects
implementing interfaces.

In the future, once Proxies are in a spec and everyone’s implementing
them, I think we should speccing indexed property behaviour Web IDL
directly in terms of them.  We’re not at that point yet, though.  In the
meantime, we need to specify something that will be compatible with
going in that direction.

What is currently specified is not implemented completely by anyone, and
looks to have poor performance characteristics, but at least doesn’t
fall afoul of host object rules and could be implemented in a native SS
DOM.  What Chrome/Safari do, to me, seems more understandable for
authors, but breaks ES semantics a little.

What should we do?

-- 
Cameron McCormack ≝ http://mcc.id.au/

Received on Tuesday, 3 May 2011 05:25:08 UTC