- From: Colin Snover <w3.org@zetafleet.com>
- Date: Wed, 12 Sep 2012 20:39:14 -0500
- To: public-script-coord@w3.org
Replies inline. On 2012-09-12 11:34, Boris Zbarsky wrote: > On 9/12/12 4:38 PM, Colin Snover wrote: >> As a JS author, it is important to me to be able to have a way to >> augment DOM event objects and/or override certain properties (which may >> be defined as readonly) in a time- and memory-efficient manner. > > In a browser that implements WebIDL as written, this can be > accomplished by simply defining properties on the event object, right? So, two things I guess. First, there seems to be an assumption here that I want to permanently alter the original event object. Sometimes this is OK, but sometimes it is not. I can think of several instances where I would prefer having a delegate object, mostly in cases where it was deemed important that the original object not be modified directly because it would be used again in the future (e.g. using the same platform Event object to fire unique but related fake events in order to provide abstraction over touch/pointer/mouse APIs to end-user code, if that description makes sense). As a general rule, I prefer not to touch platform objects directly when possible anyway. Second, if I am reading the spec correctly, [Unforgeable] means defineProperty *won’t* work in some cases. This flag may not be set on Event properties, but frankly, I don’t trust W3C WGs *or* browser vendors enough to assume that it won’t be used on some property that I need to replace in the future. At least if it is possible to use platform objects as prototypes I know there is one way to relatively efficiently escape this situation. >> Right now, most script libraries end up doing a shallow copy of >> properties >> from the native event object to a surrogate and then fix up the standard >> event methods (stopPropagation, etc.) to point back to the native >> object, which is quite inefficient, and can be especially bad for >> performance when dealing with high-volume events (touchmove, mousemove, >> etc.). Delegation via e.g. Object.create should be a more reasonable way >> to accomplish this > > I'm trying to understand why a separate object is needed at all. Is > this just working around the fact that some implementations put IDL > attributes directly on the object, not on the prototype? No, though it sounds like using defineProperty would break these implementations now. Do you know offhand who implements this way and if this does, indeed, break them? >> I strongly believe that browser vendors should be making every effort >> to make >> host/platform objects indistinguishable from native JavaScript objects >> as much as possible > > Let's stop and do a thought experiment. OK. > Say you implement the innerHTML getter that lives on > HTMLElement.prototype in JavaScript. Assume that your DOM is in fact > implemented as native JavaScript objects (so your DOM nodes are native > objects), but complies with the DOM specification. > > Now say a web page does: > > var elem = document.createElement("span"); > elem.innerHTML = "<i>Something</i>" > var obj = Object.create(elem); > Object.defineProperty(obj, "firstChild", { value: elem; }); > alert(obj.innerHTML); > > What should happen and why? Line 1 creates a new DOM object as elem and initialises it. Line 2 causes elem to create an internal DOM structure representing the provided string. Line 3 creates a new object using elem as its prototype. Line 4 sets the firstChild property of the object obj to elem. Line 5 calls elem’s innerHTML getter and alerts the result, which should be the same value provided in line 2, because Line 4 just defined a new property on obj (and firstChild is readonly, but even if it wasn’t, the firstChild setter would not be called because [[Put]] was not used). >> entertained, would be to fix the |this| value of platform object >> getter/setters to the platform object itself > My first thought for an alternative proposal, were one to be > > Which particular platform object? Note that the getters live on the > prototype, not on the platform object itself. In your previous example, the elem object. I realise that this is probably ugly from an implementation perspective but the current proposal is almost certainly worse from an authoring perspective. >> whilst still allowing >> read-only properties to be safely redefined on the delegate. > > Again, this can already be done with Object.defineProperty in UAs that > actually implement WebIDL. Well, it can’t, or else we wouldn’t be having this discussion. :) The editor’s draft currently says an error must be thrown if |this| is not a platform object, so it is possible to either redefine *on the platform object itself* (if it’s allowed by the interface), *or* it is possible to create a perfectly worthless delegate object where only accessing overridden properties works. It is not possible to create a delegate to a platform object and have things function in a somewhat sane manner. Cheers, -- Colin Snover http://zetafleet.com
Received on Thursday, 13 September 2012 01:39:53 UTC