Bug 467291 - Reduce Addrefing while creating event target chain, r+sr=jst
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2797,25 +2797,27 @@ nsGenericElement::doPreHandleEvent(nsICo
return NS_OK;
}
}
}
}
}
}
- nsCOMPtr<nsIContent> parent = aContent->GetParent();
+ nsIContent* parent = aContent->GetParent();
+ // Event may need to be retargeted if aContent is the root of a native
+ // anonymous content subtree or event is dispatched somewhere inside XBL.
if (isAnonForEvents) {
// If a DOM event is explicitly dispatched using node.dispatchEvent(), then
// all the events are allowed even in the native anonymous content..
NS_ASSERTION(aVisitor.mEvent->eventStructType != NS_MUTATION_EVENT ||
aVisitor.mDOMEvent,
"Mutation event dispatched in native anonymous content!?!");
aVisitor.mEventTargetAtParent = parent;
- } else if (parent) {
+ } else if (parent && aVisitor.mOriginalTargetIsInAnon) {
nsCOMPtr<nsIContent> content(do_QueryInterface(aVisitor.mEvent->target));
if (content && content->GetBindingParent() == parent) {
aVisitor.mEventTargetAtParent = parent;
}
}
// check for an anonymous parent
// XXX XBL2/sXBL issue
--- a/content/events/public/nsEventDispatcher.h
+++ b/content/events/public/nsEventDispatcher.h
@@ -124,21 +124,23 @@ public:
nsCOMPtr<nsISupports> mItemData;
};
class nsEventChainPreVisitor : public nsEventChainVisitor {
public:
nsEventChainPreVisitor(nsPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent* aDOMEvent,
- nsEventStatus aEventStatus = nsEventStatus_eIgnore)
+ nsEventStatus aEventStatus,
+ PRBool aIsInAnon)
: nsEventChainVisitor(aPresContext, aEvent, aDOMEvent, aEventStatus),
mCanHandle(PR_TRUE), mForceContentDispatch(PR_FALSE),
- mRelatedTargetIsInAnon(PR_FALSE), mWantsWillHandleEvent(PR_FALSE),
- mParentTarget(nsnull), mEventTargetAtParent(nsnull) {}
+ mRelatedTargetIsInAnon(PR_FALSE), mOriginalTargetIsInAnon(aIsInAnon),
+ mWantsWillHandleEvent(PR_FALSE), mParentTarget(nsnull),
+ mEventTargetAtParent(nsnull) {}
void Reset() {
mItemFlags = 0;
mItemData = nsnull;
mCanHandle = PR_TRUE;
mForceContentDispatch = PR_FALSE;
mWantsWillHandleEvent = PR_FALSE;
mParentTarget = nsnull;
@@ -160,17 +162,22 @@ public:
*/
PRPackedBool mForceContentDispatch;
/**
* PR_TRUE if it is known that related target is or is a descendant of an
* element which is anonymous for events.
*/
PRPackedBool mRelatedTargetIsInAnon;
-
+
+ /**
+ * PR_TRUE if the original target of the event is inside anonymous content.
+ * This is set before calling PreHandleEvent on event targets.
+ */
+ PRPackedBool mOriginalTargetIsInAnon;
/**
* Whether or not nsPIDOMEventTarget::WillHandleEvent will be
* called. Default is PR_FALSE;
*/
PRPackedBool mWantsWillHandleEvent;
/**
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -454,23 +454,26 @@ nsEventDispatcher::Dispatch(nsISupports*
//
// Make sure that the event target points to the right object.
nsCOMPtr<nsPIDOMEventTarget> t = do_QueryInterface(aEvent->target);
NS_ENSURE_STATE(t);
aEvent->target = t->GetTargetForEventTargetChain();
NS_ENSURE_STATE(aEvent->target);
}
aEvent->originalTarget = aEvent->target;
+ nsCOMPtr<nsIContent> content = do_QueryInterface(aEvent->originalTarget);
+ PRBool isInAnon = (content && content->IsInAnonymousSubtree());
NS_MARK_EVENT_DISPATCH_STARTED(aEvent);
// Create visitor object and start event dispatching.
// PreHandleEvent for the original target.
nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
- nsEventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status);
+ nsEventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status,
+ isInAnon);
targetEtci->PreHandleEvent(preVisitor);
if (preVisitor.mCanHandle) {
// At least the original target can handle the event.
// Setting the retarget to the |target| simplifies retargeting code.
nsCOMPtr<nsPIDOMEventTarget> t = do_QueryInterface(aEvent->target);
targetEtci->SetNewTarget(t);
nsEventTargetChainItem* topEtci = targetEtci;