- 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