Bug 1305458 Part8: Move dispatch XUL command from nsXULElement::GetEventTargetParent to PreHandleEvent. r=smaug
authorStone Shih <sshih@mozilla.com>
Fri, 21 Oct 2016 17:58:34 +0800
changeset 323079 1a75a459c545012a96fd540bd8715f67483c95b8
parent 323078 be4e001288d083d13940bc4bb5f114f890587946
child 323080 5fbc6dab40e39e676ce0a33472e3e0ccee1adb7f
push id30967
push userphilringnalda@gmail.com
push dateFri, 18 Nov 2016 03:21:38 +0000
treeherdermozilla-central@8e476f8bd52d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1305458
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1305458 Part8: Move dispatch XUL command from nsXULElement::GetEventTargetParent to PreHandleEvent. r=smaug MozReview-Commit-ID: QuJSgaaAH9
dom/xul/nsXULElement.cpp
dom/xul/nsXULElement.h
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -121,16 +121,18 @@ using namespace mozilla::dom;
 uint32_t             nsXULPrototypeAttribute::gNumElements;
 uint32_t             nsXULPrototypeAttribute::gNumAttributes;
 uint32_t             nsXULPrototypeAttribute::gNumCacheTests;
 uint32_t             nsXULPrototypeAttribute::gNumCacheHits;
 uint32_t             nsXULPrototypeAttribute::gNumCacheSets;
 uint32_t             nsXULPrototypeAttribute::gNumCacheFills;
 #endif
 
+#define NS_DISPATCH_XUL_COMMAND     (1 << 0)
+
 class nsXULElementTearoff final : public nsIFrameLoaderOwner
 {
   ~nsXULElementTearoff() {}
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsXULElementTearoff)
 
@@ -1274,17 +1276,17 @@ nsXULElement::IsEventStoppedFromAnonymou
     return (IsRootOfNativeAnonymousSubtree() &&
             IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::scrollcorner) &&
             (aMessage == eMouseClick || aMessage == eMouseDoubleClick ||
              aMessage == eXULCommand || aMessage == eContextMenu ||
              aMessage == eDragStart));
 }
 
 nsresult
-nsXULElement::DispatchXULCommand(const EventChainPreVisitor& aVisitor,
+nsXULElement::DispatchXULCommand(const EventChainVisitor& aVisitor,
                                  nsAutoString& aCommand)
 {
     // XXX sXBL/XBL2 issue! Owner or current document?
     nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetUncomposedDoc()));
     NS_ENSURE_STATE(domDoc);
     nsCOMPtr<nsIDOMElement> commandElt;
     domDoc->GetElementById(aCommand, getter_AddRefs(commandElt));
     nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
@@ -1345,23 +1347,39 @@ nsXULElement::GetEventTargetParent(Event
         nsAutoString command;
         if (xulEvent &&
             GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) &&
             !command.IsEmpty()) {
             // Stop building the event target chain for the original event.
             // We don't want it to propagate to any DOM nodes.
             aVisitor.mCanHandle = false;
             aVisitor.mAutomaticChromeDispatch = false;
-            return DispatchXULCommand(aVisitor, command);
+            // Dispatch XUL command in PreHandleEvent to prevent it breaks event
+            // target chain creation
+            aVisitor.mWantsPreHandleEvent = true;
+            aVisitor.mItemFlags |= NS_DISPATCH_XUL_COMMAND;
+            return NS_OK;
         }
     }
 
     return nsStyledElement::GetEventTargetParent(aVisitor);
 }
 
+nsresult
+nsXULElement::PreHandleEvent(EventChainVisitor& aVisitor)
+{
+    if (aVisitor.mItemFlags & NS_DISPATCH_XUL_COMMAND) {
+        nsAutoString command;
+        GetAttr(kNameSpaceID_None, nsGkAtoms::command, command);
+        MOZ_ASSERT(!command.IsEmpty());
+        return DispatchXULCommand(aVisitor, command);
+    }
+    return nsStyledElement::PreHandleEvent(aVisitor);
+}
+
 // XXX This _should_ be an implementation method, _not_ publicly exposed :-(
 NS_IMETHODIMP
 nsXULElement::GetResource(nsIRDFResource** aResource)
 {
     ErrorResult rv;
     *aResource = GetResource(rv).take();
     return rv.StealNSResult();
 }
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -352,17 +352,18 @@ public:
 
     // nsISupports
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement)
 
     // nsINode
     virtual nsresult GetEventTargetParent(
                        mozilla::EventChainPreVisitor& aVisitor) override;
-
+    virtual nsresult PreHandleEvent(
+                       mozilla::EventChainVisitor& aVisitor) override;
     // nsIContent
     virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                 nsIContent* aBindingParent,
                                 bool aCompileEventHandlers) override;
     virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
     virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
     virtual void DestroyContent() override;
 
@@ -699,13 +700,13 @@ protected:
     }
 
     virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
     void MaybeUpdatePrivateLifetime();
 
     bool IsEventStoppedFromAnonymousScrollbar(mozilla::EventMessage aMessage);
 
-    nsresult DispatchXULCommand(const mozilla::EventChainPreVisitor& aVisitor,
+    nsresult DispatchXULCommand(const mozilla::EventChainVisitor& aVisitor,
                                 nsAutoString& aCommand);
 };
 
 #endif // nsXULElement_h__