Opened 10 years ago
Closed 10 years ago
#14304 closed bug (notabug)
Event in mouseenter handler is mutable (may change in deferred handler)
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | low | Milestone: | None |
Component: | event | Version: | 2.0.3 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
When using setTimeout()
or _.throttle()
(from Underscore.js) in mouseenter
event handler in Chrome, then you might note that some properties of event object may change after timeout (e.g. event.type
or event.delegateTarget
- look at https://github.com/jquery/jquery/blob/master/src/event.js#L363 - it seems that jQuery reuses the same event object in event simulation).
Example at jsfiddle: http://jsfiddle.net/Qtkuh/
Move mouse into Result
area, and you will note that deferred handler receives event with changed field type
.
The fact that event object is mutable (or reused) isn't stated in documentation. This leads to hardly reproducible and understandable errors when someone tries to create asynchronous event handlers (any error in asynchronous code is hard to find).
Change History (4)
comment:1 Changed 10 years ago by
Component: | unfiled → event |
---|---|
Priority: | undecided → low |
Status: | new → open |
Version: | 1.9.1 → 2.0.3 |
comment:2 Changed 10 years ago by
I've already mentioned one problem spot, where delegateTarget
(used in my deferred handler) is changed: https://github.com/jquery/jquery/blob/master/src/event.js#L363
At this line delegateTarget
is overwritten when synchronous processing of mouseenter
event is done (right before mouseover
event).
comment:3 Changed 10 years ago by
Changes in delegateTarget
, like currentTarget
, are to be expected over the course of event propagation (see http://api.jquery.com/event.delegateTarget/). type
mutation is potentially a much more sticky issue, but it seems to me like we're already following the most reasonable course of action by reverting it after propagation has completed.
comment:4 Changed 10 years ago by
Resolution: | → notabug |
---|---|
Status: | open → closed |
Agreed. If you want a snapshot of the event as it appeared in the handler, you'll need to bear the overhead of a full copy. Be careful because the event may have cyclical references.
This has been true for many versions now, perhaps as far back as jQuery 1.4. I suspect the reason it has never been reported is that using the native IE
event
object outside the handler chain (for example in asetTimeout
) throws errors in IE 6-8. The object is automatically destroyed at the end of the event delivery cycle, leaving an invalid reference inside jQuery's Event object. Plugins like hoverIntent copy the information they need rather than trying to save a reference to the entire event object, which circumvents both that problem and the one you've described here.It's much too costly to create a new object and copy over all the properties in these potentially high-frequency events, which is why the existing object is re-used. However, it seems like we could save and restore the properties we change, and I thought it already did this (at least for
type
).I'll mark this open for investigation; if you'd like to look at the code to find the problem spots it would be greatly appreciated!