- From: Cameron McCormack <cam@mcc.id.au>
- Date: Fri, 10 Aug 2012 13:36:06 +1000
- To: "public-script-coord@w3.org" <public-script-coord@w3.org>
Kyle Huey mailed to public-webapps about a problem we have with unprefixing IndexedDB: http://lists.w3.org/Archives/Public/public-webapps/2012JulSep/0392.html The summary is: 1. IndexedDB defines: interface IDBEnvironment { readonly attribute IDBFactory indexedDB; }; Window implements IDBEnvironment; 2. People are trying to fall back to prefixed versions of IndexedDB by writing code like (hooray prefixes): var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB; 3. Web IDL says that the "indexedDB" property for the IDL attribute should live on Window.prototype. 4. Recent versions of the ECMAScript spec say that the var declaration first will create a property on the global object (i.e. window) with the value undefined, before performing the assignment. 5. This means that the "window.indexedDB" part of the expression on the RHS evaluates to undefined. 6. This means that we cannot remove our unprefixed version of IndexedDB at the same time as adding the prefixed version (which we want to do), because then the "indexedDB" variable will just be undefined. 7. Older versions of the ECMAScript spec did not say to create the shadowing variable, so only implementations that follow that change AND have implemented Web IDL's attributes-on-prototypes get tripped up by this. 8. But the same problem would exist with operations, where properties have always existed on the prototype. For example if you wrote: var requestAnimationFrame = window.requestAnimationFrame || window.mozAnimationFrame || ...; you have the same problem. So what do we do about this, if we accept that this is a problem? 1. We could change the ECMAScript spec to not do this shadowing thing. 2. We could change Web IDL to place all properties for IDL attributes and operation on Window (and interfaces it inherits from or has mixed in to) as own properties on window itself, rather than on the prototype, AND give them all [Replaceable]-like semantics, where if you assign some value that doesn't make sense for an attribute you overwrite it and lose its special behaviour. That would cause the var declaration, according to the ES spec, not to create a new property with value undefined. But, it would make it harder to monkeypatch, say, EventTarget.prototype.addEventListener, since window isn't really inheriting it from EventTarget.prototype any more but having its own copy of it. 3. We could change Web IDL so that window's [[DefineOwnProperty]] refuses to create the shadowing undefined property if the property name matches one of the IDL attributes/operations on Window (or its ancestors, etc.) That effectively works around the ES spec shadowing requirement for var statements without needing to "willfully violate" it. With options (2) and (3), we are assuming that existing scripts do not rely on for example: <script> var open; assert(open === undefined); </script> Boris thinks that this assumption is safe, but evidence to the contrary would be useful if someone has it. Another thing to be careful of is: <script> function open() { } assert(open != Window.prototype.open); </script> which I think scripts are doing (they want to call their own "open"). With (2) this keeps working, since the own property "open" on window exists (which means the var statement doesn't try to overwrite it with undefined) and the property is writable (so the assignment of the Function object works). With (3) this also keeps working, since the [[DefineOwnProperty]] on window for "open" would be ignored, and the assignment of the Function object shadows the property from the prototype. The upshot of (3) is that for IDL attributes like "onclick", doing var onclick = function() { ... }; will be just like assigning to window.onclick. Whether that's desired, I'm not sure. Input on what to do here, especially from TC39 folks, is very welcome.
Received on Friday, 10 August 2012 03:36:44 UTC