Re: ACTION-70: Define the scope chain of onFoo events reference issue-1

Maciej Stachowiak wrote:
> Hi everyone,
> 
> This action item was assigned to me while I wasn't present, so I'm not 
> sure what it means. I could imagine the following possible things 
> intended to be covered:
> 
> 1) Define scope chain for event listeners attached via HTML event 
> attributes, e.g. <img onclick="handleClick(event)">.
> 2) Define `this' binding behavior for #1.
> 3) Define scope chain for events attached via HTML DOM properties, e.g. 
> myImage.onclick = handleClick
> 4) Define `this' binding behavior for #3.
> 5) Define scope chain for events attached via addEventListener().
> 6) Define `this' binding for #5 (already done).
> 7) Define scope chain for event listeners attached via SVG 1.1 event 
> attributes, e.g. <image onclick="handleClick(event)">.
> 8) Define `this' binding behavior for #1.
> 
> I do not feel like I have the relevant expertise to answer 7 and 8, but 
> I can try to do some research if it is desirable to define those.

Ideally I would hope that we can define 7 and 8 to be as similar to 1 
and 2 as possible, to reduce author confusion and make CDF more sane.

> Here's brief outlines of the behavior I would propose. I have not tested 
> thoroughly or written any of this up in formal language, so please let 
> me know which ones need testing and formal language.
> 
> 1) The attribute text is coverted to a function as if it were the result 
> of the following expression evaluated in global scope, where ELT is the 
> DOM object representing the element:
> 
> (function() { with(ELT) { return function(event) {  ...contents of 
> attribute here... } } })()

There is need for additional code in here to deal with the return value, 
i.e. that returning false should call .preventDefault. Other then that I 
agree with this.

However we should probably also define the scope chain for elements. 
This should clearly ideally have lived in another spec, but I guess 
we're stuck with having it in events for now?

> The behavior is then as if resulting function F were added with 
> addEventListener(event, F, false).
> 
> The upshot of this is that a function is made with ELT at the head of 
> its [[Scope]] internal property, and "event" is bound to the event in 
> the function body.
> 
> I think describing this in terms of the language beats trying to write 
> prose about the [[Scope]] property though.
> 
> Also this is subtly incompatible with Win IE, since I believe it has 
> only window.event, not an actual event parameter to attribute handlers.

As far as events go I think compatibility with IE is a lost cause. So 
i'm not too worried here.

> Also, some event listener properties on the <body> element actually 
> create event listeners on the window object, not the body, and so do not 
> include the body in their scope chain.

I just verified this in mozilla. Adding on* attributes to the <body> or 
the <html> tag will make both |this| and the scope chain start on the 
window object.

> 2) See above - no special considerations for "this" beyond the effect of 
> addEventListener of a function.
> 
> 3) Event handler DOM properties have a function value. Getting the 
> property retrieves any event listener function previously set using the 
> property or corresponding markup attribute. Setting the property removes 
> any previous event listener set via that property or the corresponding 
> attribute, and adds the newly set function as if with addEventListener. 
> There is no change made to the scope chain of a function set this way.

You mean that if you call
element.onclick = handler;

then the scope chain of |handler| is determined by what scope chain the 
function had when it was created, right. Saying "no change" could be 
interpreted as if its the same as when the handler is defined inside the 
attribute.

> The slightly odd implication of this is that you can retrieve an event 
> listener created via attribute and attach it to another element, and its 
> scope chain continues to include the original element, not the new element.
> 
> 4) See above - no special considerations for "this" beyond the effect of 
> addEventListener of a function.

I think we should explicitly say that |this| will get the same binding 
as when a function is provided to addEventListener.

> 5) addEventListener does not alter any function parameters passed to it. 
> In particular it does not alter the scope chain.
> 
> 6) I already came up with language for this. In brief my proposal was to 
> define this as equivalent to adding an EventListener created by the 
> expression { handleEvent: function(event) { 
> F.applyTo(event.currentTarget, [event]); } } where F is the function.

I would prefer if we used "call" rather then "apply" to make it clear 
that only one parameter is passed. It would also make it cheaper for 
someone implementing this literally.

> The upshot of this is that the event's current target will be the "this" 
> object for any function event listener. But if you add an object with a 
> handleEvent method, then its handleEvent method is invoked as normal, 
> with the EventListener as the "this" object. Here again I think it is 
> better to explain the behavior in terms of ECMAScript expressions than 
> to try to explain in terms of ECMA-262 spec-internal concepts. It is 
> more obvious how to test this way, and is more likely to be compatible 
> with future revisions of ECMA-262.

Sounds good to me.

/ Jonas

Received on Tuesday, 14 March 2006 00:45:53 UTC