Spec for [Global] does not seem to be quite web-compatible, and none of the UAs are really compatible with each other

The current specification for [Global] says that all IDL attributes are 
defined on the object itself, not its proto, to prevent accidental 
shadowing of things by vars in situations like this:

   var performance = window.mozPerformance ||
                     window.webkitPerforamnce ||
                     window.oPerforamnce ||
                     window.msPerformance ||
                     window.performance;

However when we tried implementing this in Gecko, we encountered a 
problem with the Dell website due to the use of the following pattern 
(spread over multiple JS files, actually, but I'm condensing it for 
clarity):

   var onload;
   (function() {
     onload = { foo: "bar"; };
     doSomething(onload);
   })();

Some instances of this pattern have a "var onload" inside the function, 
but some do not, and it's the latter that are problematic.

In the current Gecko implementation, the "onload" property lives on 
Window.prototype, so the global var declaration shadows it and 
everything works.  But if we follow the current spec and move the 
property to the global object directly, then the var does nothing (since 
the property is already defined), and the assignment invokes the setter 
for the property.  The property is marked as only accepting 
EventHandler, which is a callback type that treats non-callables as 
null.  The upshot is that doSomething is called with null as the 
argument instead of the actual object it expects.

I tested what other UAs do with this situation, and it goes like this:

Chrome: Seems to put on* properties on Window.prototype, even though 
other Window properties (e.g. "performance") go directly on the global 
object.  It's not clear to me how Chrome decides where to place which 
properties; I would love an explanation of how that's decided.

Safari: Puts the "onload" property directly on the global, but allows 
assigning _any_ object to it (and in fact to all event handler 
properties), not just callables, which makes the above code work.

Opera (Presto-based): Has the same behavior as current Gecko: just puts 
the IDL properties on Window.prototype.

IE9 and IE11: Puts the IDL properties on Window.prototype like 
Gecko/Presto _and_ allows assigning arbitrary non-callable objects like 
Safari.

The obvious question here is what the spec should say.

Do we want to move some but not all of the global's properties back to 
the proto chain?  If so, which ones?  Should it be a whitelist (i.e. 
annotate the properties that go on the proto) or a blacklist (annotate 
the properties that go on the object)?  Or should we just give up 
putting things on the object directly and simply spec on Window that all 
UAs must support all prefixed variants of the properties that need to be 
supported with prefixes to avoid the var problem described at the 
beginning of this mail?

Any other bright ideas?

-Boris

Received on Sunday, 22 December 2013 06:34:01 UTC