bug 1270916 - switch to use the new mutation event queue system r=davidb
authorTrevor Saunders <tbsaunde@tbsaunde.org>
Fri, 11 Nov 2016 00:23:27 -0500
changeset 322923 387d3acae9e99bdc140a65fd367ecbaa6238f3a3
parent 322922 43708cd293faa60fc2855a437602cb82d8bb9715
child 322925 c7bb0d181c07f106f710dbdd4b498eca8ffa81c5
push id84000
push usertsaunders@mozilla.com
push dateThu, 17 Nov 2016 04:39:30 +0000
treeherdermozilla-inbound@387d3acae9e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavidb
bugs1270916
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 1270916 - switch to use the new mutation event queue system r=davidb This puts events in the queue instead of the event tree, and then fires them based on the queue. Some tests need to be adjusted to make sure they check constraints on event order correctly.
accessible/base/EventTree.cpp
accessible/base/NotificationController.cpp
accessible/generic/Accessible.cpp
accessible/tests/mochitest/events/test_aria_menu.html
accessible/tests/mochitest/events/test_coalescence.html
accessible/tests/mochitest/events/test_mutation.html
accessible/tests/mochitest/treeupdate/test_ariaowns.html
accessible/tests/mochitest/treeupdate/test_bug1189277.html
accessible/tests/mochitest/treeupdate/test_whitespace.html
--- a/accessible/base/EventTree.cpp
+++ b/accessible/base/EventTree.cpp
@@ -58,50 +58,42 @@ void
 TreeMutation::AfterInsertion(Accessible* aChild)
 {
   MOZ_ASSERT(aChild->Parent() == mParent);
 
   if (static_cast<uint32_t>(aChild->mIndexInParent) < mStartIdx) {
     mStartIdx = aChild->mIndexInParent + 1;
   }
 
-  if (!mEventTree) {
-    mEventTree = Controller()->QueueMutation(mParent);
-    if (!mEventTree) {
-      mEventTree = kNoEventTree;
-    }
+  if (!mQueueEvents) {
+    return;
   }
 
-  if (mEventTree != kNoEventTree) {
-    RefPtr<AccShowEvent> ev = new AccShowEvent(aChild);
-    mEventTree->Mutated(ev);
-    Controller()->QueueNameChange(aChild);
-  }
+  RefPtr<AccShowEvent> ev = new AccShowEvent(aChild);
+  DebugOnly<bool> added = Controller()->QueueMutationEvent(ev);
+  MOZ_ASSERT(added);
+  aChild->SetShowEventTarget(true);
 }
 
 void
 TreeMutation::BeforeRemoval(Accessible* aChild, bool aNoShutdown)
 {
   MOZ_ASSERT(aChild->Parent() == mParent);
 
   if (static_cast<uint32_t>(aChild->mIndexInParent) < mStartIdx) {
     mStartIdx = aChild->mIndexInParent;
   }
 
-  if (!mEventTree) {
-    mEventTree = Controller()->QueueMutation(mParent);
-    if (!mEventTree) {
-      mEventTree = kNoEventTree;
-    }
+  if (!mQueueEvents) {
+    return;
   }
 
-  if (mEventTree != kNoEventTree) {
-    RefPtr<AccHideEvent> ev = new AccHideEvent(aChild, !aNoShutdown);
-    mEventTree->Mutated(ev);
-    Controller()->QueueNameChange(aChild);
+  RefPtr<AccHideEvent> ev = new AccHideEvent(aChild, !aNoShutdown);
+  if (Controller()->QueueMutationEvent(ev)) {
+    aChild->SetHideEventTarget(true);
   }
 }
 
 void
 TreeMutation::Done()
 {
   MOZ_ASSERT(mParent->mStateFlags & Accessible::eKidsMutating);
   mParent->mStateFlags &= ~Accessible::eKidsMutating;
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -797,19 +797,19 @@ NotificationController::WillRefresh(mozi
   }
   mRelocations.Clear();
 
   // If a generic notification occurs after this point then we may be allowed to
   // process it synchronously.  However we do not want to reenter if fireing
   // events causes script to run.
   mObservingState = eRefreshProcessing;
 
-  RefPtr<DocAccessible> deathGrip(mDocument);
-  mEventTree.Process(deathGrip);
-  deathGrip = nullptr;
+  CoalesceMutationEvents();
+  ProcessMutationEvents();
+  mEventGeneration = 0;
 
   // Now that we are done with them get rid of the events we fired.
   RefPtr<AccTreeMutationEvent> mutEvent = Move(mFirstMutationEvent);
   mLastMutationEvent = nullptr;
   mFirstMutationEvent = nullptr;
   while (mutEvent) {
     RefPtr<AccTreeMutationEvent> nextEvent = mutEvent->NextEvent();
     Accessible* target = mutEvent->GetAccessible();
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -2153,20 +2153,19 @@ Accessible::MoveChild(uint32_t aNewIndex
 {
   MOZ_ASSERT(aChild, "No child was given");
   MOZ_ASSERT(aChild->mParent == this, "A child from different subtree was given");
   MOZ_ASSERT(aChild->mIndexInParent != -1, "Unbound child was given");
   MOZ_ASSERT(static_cast<uint32_t>(aChild->mIndexInParent) != aNewIndex,
              "No move, same index");
   MOZ_ASSERT(aNewIndex <= mChildren.Length(), "Wrong new index was given");
 
-  EventTree* eventTree = mDoc->Controller()->QueueMutation(this);
-  if (eventTree) {
-    RefPtr<AccHideEvent> event = new AccHideEvent(aChild, false);
-    eventTree->Mutated(event);
+  RefPtr<AccHideEvent> hideEvent = new AccHideEvent(aChild, false);
+  if (mDoc->Controller()->QueueMutationEvent(hideEvent)) {
+    aChild->SetHideEventTarget(true);
   }
 
   mEmbeddedObjCollector = nullptr;
   mChildren.RemoveElementAt(aChild->mIndexInParent);
 
   uint32_t startIdx = aNewIndex, endIdx = aChild->mIndexInParent;
 
   // If the child is moved after its current position.
@@ -2188,21 +2187,20 @@ Accessible::MoveChild(uint32_t aNewIndex
   }
 
   for (uint32_t idx = startIdx; idx <= endIdx; idx++) {
     mChildren[idx]->mIndexInParent = idx;
     mChildren[idx]->mStateFlags |= eGroupInfoDirty;
     mChildren[idx]->mInt.mIndexOfEmbeddedChild = -1;
   }
 
-  if (eventTree) {
-    RefPtr<AccShowEvent> event = new AccShowEvent(aChild);
-    eventTree->Mutated(event);
-    mDoc->Controller()->QueueNameChange(aChild);
-  }
+  RefPtr<AccShowEvent> showEvent = new AccShowEvent(aChild);
+  DebugOnly<bool> added = mDoc->Controller()->QueueMutationEvent(showEvent);
+  MOZ_ASSERT(added);
+  aChild->SetShowEventTarget(true);
 }
 
 Accessible*
 Accessible::GetChildAt(uint32_t aIndex) const
 {
   Accessible* child = mChildren.SafeElementAt(aIndex, nullptr);
   if (!child)
     return nullptr;
--- a/accessible/tests/mochitest/events/test_aria_menu.html
+++ b/accessible/tests/mochitest/events/test_aria_menu.html
@@ -50,18 +50,18 @@
     function showMenu(aMenuID, aParentMenuID, aHow)
     {
       this.menuNode = getNode(aMenuID);
 
       // Because of aria-owns processing we may have menupopup start fired before
       // related show event.
       this.eventSeq = [
         new invokerChecker(EVENT_SHOW, this.menuNode),
-        new asyncInvokerChecker(EVENT_MENUPOPUP_START, this.menuNode),
-        new invokerChecker(EVENT_REORDER, getNode(aParentMenuID))
+        new invokerChecker(EVENT_REORDER, getNode(aParentMenuID)),
+        new invokerChecker(EVENT_MENUPOPUP_START, this.menuNode)
       ];
 
       this.invoke = function showMenu_invoke()
       {
         if (aHow == kViaDisplayStyle)
           this.menuNode.style.display = "block";
         else
           this.menuNode.style.visibility = "visible";
--- a/accessible/tests/mochitest/events/test_coalescence.html
+++ b/accessible/tests/mochitest/events/test_coalescence.html
@@ -414,18 +414,18 @@
     function test5()
     {
       this.o = getAccessible("t5_o");
       this.ofc = this.o.firstChild;
       this.b = getAccessible("t5_b");
       this.lb = getAccessible("t5_lb");
 
       this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, this.b),
         new invokerChecker(EVENT_HIDE, this.o),
-        new invokerChecker(EVENT_HIDE, this.b),
         new invokerChecker(EVENT_REORDER, "t5"),
         new unexpectedInvokerChecker(EVENT_HIDE, this.ofc),
         new unexpectedInvokerChecker(EVENT_REORDER, this.o),
         new unexpectedInvokerChecker(EVENT_REORDER, this.lb)
       ];
 
       this.invoke = function test5_invoke()
       {
@@ -534,18 +534,18 @@
      * The hide event should be delivered before the paired show event.
      */
     function test8()
     {
       this.eventSeq = [
         new invokerChecker(EVENT_HIDE, getNode('t8_c1_child')),
         new invokerChecker(EVENT_HIDE, 't8_c2_moved'),
         new invokerChecker(EVENT_SHOW, 't8_c2_moved'),
+        new invokerChecker(EVENT_REORDER, 't8_c2'),
         new invokerChecker(EVENT_REORDER, 't8_c1'),
-        new invokerChecker(EVENT_REORDER, 't8_c2')
       ];
 
       this.invoke = function test8_invoke()
       {
         // Remove a node from 't8_c1' container to give the event tree a
         // desired structure (the 't8_c1' container node goes first in the event
         // tree)
         getNode('t8_c1_child').remove();
@@ -573,23 +573,23 @@
      *
      * The hide events for 't9_c2_moved' and 't9_c3_moved' should be delivered
      * before the show event for 't9_c2_moved'.
      */
     function test9()
     {
       this.eventSeq = [
         new invokerChecker(EVENT_HIDE, getNode('t9_c1_child')),
+        new invokerChecker(EVENT_HIDE, getNode('t9_c2_child')),
         new invokerChecker(EVENT_HIDE, 't9_c3_moved'),
         new invokerChecker(EVENT_HIDE, 't9_c2_moved'),
         new invokerChecker(EVENT_SHOW, 't9_c2_moved'),
+        new invokerChecker(EVENT_REORDER, 't9_c3'),
+        new invokerChecker(EVENT_REORDER, 't9_c2'),
         new invokerChecker(EVENT_REORDER, 't9_c1'),
-        new invokerChecker(EVENT_HIDE, getNode('t9_c2_child')),
-        new invokerChecker(EVENT_REORDER, 't9_c2'),
-        new invokerChecker(EVENT_REORDER, 't9_c3'),
         new unexpectedInvokerChecker(EVENT_SHOW, 't9_c3_moved')
       ];
 
       this.invoke = function test9_invoke()
       {
         // Remove child nodes from 't9_c1' and 't9_c2' containers to give
         // the event tree a needed structure ('t9_c1' and 't9_c2' nodes go
         // first in the event tree),
@@ -619,22 +619,22 @@
      *
      * The hide events for 't10_c2_moved' and 't10_c3_moved' should be delivered
      * before the show event for 't10_c2_moved'.
      */
     function test10()
     {
       this.eventSeq = [
         new invokerChecker(EVENT_HIDE, getNode('t10_c1_child')),
+        new invokerChecker(EVENT_HIDE, getNode('t10_c2_child')),
         new invokerChecker(EVENT_HIDE, getNode('t10_c2_moved')),
         new invokerChecker(EVENT_HIDE, getNode('t10_c3_moved')),
         new invokerChecker(EVENT_SHOW, getNode('t10_c2_moved')),
+        new invokerChecker(EVENT_REORDER, 't10_c2'),
         new invokerChecker(EVENT_REORDER, 't10_c1'),
-        new invokerChecker(EVENT_HIDE, getNode('t10_c2_child')),
-        new invokerChecker(EVENT_REORDER, 't10_c2'),
         new invokerChecker(EVENT_REORDER, 't10_c3')
       ];
 
       this.invoke = function test10_invoke()
       {
         // Remove child nodes from 't10_c1' and 't10_c2' containers to give
         // the event tree a needed structure ('t10_c1' and 't10_c2' nodes go first
         // in the event tree),
@@ -654,19 +654,21 @@
      * Move a node by aria-owns from right to left in the tree, and then
      * move its parent too by aria-owns. No hide event should be fired for
      * original node.
      */
     function test11()
     {
       this.eventSeq = [
         new invokerChecker(EVENT_HIDE, getNode('t11_c1_child')),
-        new invokerChecker(EVENT_SHOW, 't11_c2_child'),
         new invokerChecker(EVENT_HIDE, getNode('t11_c2')),
-        new invokerChecker(EVENT_SHOW, 't11_c2'),
+        new orderChecker(),
+        new asyncInvokerChecker(EVENT_SHOW, 't11_c2_child'),
+        new asyncInvokerChecker(EVENT_SHOW, 't11_c2'),
+        new orderChecker(),
         new invokerChecker(EVENT_REORDER, 't11'),
         new unexpectedInvokerChecker(EVENT_HIDE, 't11_c2_child'),
         new unexpectedInvokerChecker(EVENT_REORDER, 't11_c1'),
         new unexpectedInvokerChecker(EVENT_REORDER, 't11_c2'),
         new unexpectedInvokerChecker(EVENT_REORDER, 't11_c3')
       ];
 
       this.invoke = function test11_invoke()
@@ -684,17 +686,17 @@
       this.getID = function test11_getID() {
         return "Move a node by aria-owns to left within the tree";
       };
     }
 
     ////////////////////////////////////////////////////////////////////////////
     // Do tests.
 
-    //gA11yEventDumpToConsole = true; // debug stuff
+    gA11yEventDumpToConsole = true; // debug stuff
     //enableLogging("eventTree");
 
     var gQueue = null;
     function doTests()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new removeChildNParent("option1", "select1"));
--- a/accessible/tests/mochitest/events/test_mutation.html
+++ b/accessible/tests/mochitest/events/test_mutation.html
@@ -336,18 +336,18 @@
       }
     }
 
     function insertReferredElm(aContainerID)
     {
       this.containerNode = getNode(aContainerID);
 
       this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, function(aNode) { return aNode.firstChild; }, this.containerNode),
         new invokerChecker(EVENT_SHOW, function(aNode) { return aNode.lastChild; }, this.containerNode),
-        new invokerChecker(EVENT_SHOW, function(aNode) { return aNode.firstChild; }, this.containerNode),
         new invokerChecker(EVENT_REORDER, this.containerNode)
       ];
 
       this.invoke = function insertReferredElm_invoke()
       {
         this.containerNode.innerHTML =
           "<span id='insertReferredElms_span'></span><input aria-labelledby='insertReferredElms_span'>";
       }
--- a/accessible/tests/mochitest/treeupdate/test_ariaowns.html
+++ b/accessible/tests/mochitest/treeupdate/test_ariaowns.html
@@ -22,21 +22,21 @@
     ////////////////////////////////////////////////////////////////////////////
     // Invokers
     ////////////////////////////////////////////////////////////////////////////
 
     function changeARIAOwns()
     {
       this.eventSeq = [
         new invokerChecker(EVENT_HIDE, getNode("t1_button")),
-        new invokerChecker(EVENT_SHOW, getNode("t1_button")),
-        new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
         // no hide for t1_subdiv because it is contained by hidden t1_checkbox
         new invokerChecker(EVENT_HIDE, getNode("t1_checkbox")),
         new invokerChecker(EVENT_SHOW, getNode("t1_checkbox")),
+        new invokerChecker(EVENT_SHOW, getNode("t1_button")),
+        new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
         new invokerChecker(EVENT_REORDER, getNode("t1_container"))
       ];
 
       this.invoke = function setARIAOwns_invoke()
       {
         // children are swapped by ARIA owns
         var tree =
           { SECTION: [
@@ -68,20 +68,22 @@
       {
         return "Change @aria-owns attribute";
       }
     }
 
     function removeARIAOwns()
     {
       this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode("t1_button")),
         new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
-        new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
-        new invokerChecker(EVENT_HIDE, getNode("t1_button")),
-        new invokerChecker(EVENT_SHOW, getNode("t1_button")),
+        new orderChecker(),
+        new asyncInvokerChecker(EVENT_SHOW, getNode("t1_button")),
+        new asyncInvokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
+        new orderChecker(),
         new invokerChecker(EVENT_REORDER, getNode("t1_container")),
         new unexpectedInvokerChecker(EVENT_REORDER, getNode("t1_checkbox"))
       ];
 
       this.invoke = function removeARIAOwns_invoke()
       {
         getNode("t1_container").removeAttribute("aria-owns");
       }
@@ -103,18 +105,18 @@
       {
         return "Remove @aria-owns attribute";
       }
     }
 
     function setARIAOwns()
     {
       this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode("t1_button")),
         new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
-        new invokerChecker(EVENT_HIDE, getNode("t1_button")),
         new invokerChecker(EVENT_SHOW, getNode("t1_button")),
         new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
         new invokerChecker(EVENT_REORDER, getNode("t1_container"))
       ];
 
       this.invoke = function setARIAOwns_invoke()
       {
         getNode("t1_container").
@@ -442,16 +444,19 @@
       }
     }
 
     function rearrangeARIAOwns(aContainer, aAttr, aIdList, aRoleList)
     {
       this.eventSeq = [];
       for (var id of aIdList) {
         this.eventSeq.push(new invokerChecker(EVENT_HIDE, getNode(id)));
+      }
+
+      for (var id of aIdList) {
         this.eventSeq.push(new invokerChecker(EVENT_SHOW, getNode(id)));
       }
       this.eventSeq.push(new invokerChecker(EVENT_REORDER, getNode(aContainer)));
 
       this.invoke = function rearrangeARIAOwns_invoke()
       {
         getNode(aContainer).setAttribute("aria-owns", aAttr);
       }
--- a/accessible/tests/mochitest/treeupdate/test_bug1189277.html
+++ b/accessible/tests/mochitest/treeupdate/test_bug1189277.html
@@ -16,19 +16,19 @@
           src="../events.js"></script>
 
   <script type="application/javascript">
     function runTest()
     {
       this.containerNode = getNode("outerDiv");
 
       this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode("child")),
         new invokerChecker(EVENT_HIDE, getNode("childDoc")),
         new invokerChecker(EVENT_SHOW, "newChildDoc"),
-        new invokerChecker(EVENT_HIDE, getNode("child")),
         new invokerChecker(EVENT_REORDER, this.containerNode)
       ];
 
       this.invoke = function runTest_invoke()
       {
         this.containerNode.removeChild(getNode("child"));
 
         var docContainer = getNode("docContainer");
@@ -42,17 +42,17 @@
 
       this.getID = function runTest_getID()
       {
         return "check show events are not incorrectly coalesced";
       }
     }
 
     //enableLogging("tree");
-    //gA11yEventDumpToConsole = true;
+    gA11yEventDumpToConsole = true;
     var gQueue = null;
     function doTest()
     {
       gQueue = new eventQueue();
       gQueue.push(new runTest());
       gQueue.invoke(); // SimpleTest.finish();
     }
 
--- a/accessible/tests/mochitest/treeupdate/test_whitespace.html
+++ b/accessible/tests/mochitest/treeupdate/test_whitespace.html
@@ -96,18 +96,19 @@
     {
       this.containerNode = getNode("container2");
       this.topNode = this.containerNode.parentNode;
       this.textNode = this.containerNode.nextSibling;
       this.imgNode = document.createElement("img");
       this.imgNode.setAttribute("src", "../moz.png");
 
       this.eventSeq = [
-        new invokerChecker(EVENT_SHOW, getAccessible, this.imgNode),
-        new invokerChecker(EVENT_SHOW, getAccessible, this.textNode),
+        new asyncInvokerChecker(EVENT_SHOW, getAccessible, this.textNode),
+        new asyncInvokerChecker(EVENT_SHOW, getAccessible, this.imgNode),
+        new orderChecker(),
         new invokerChecker(EVENT_REORDER, this.topNode)
       ];
 
       this.invoke = function insertImg_invoke()
       {
         var tree =
           { SECTION: [
             { LINK: [] },