bug 1346439 - fixup linked list manipulation in CoalesceMutationEvents() r=davidb
authorTrevor Saunders <tbsaunde@tbsaunde.org>
Thu, 16 Mar 2017 13:59:59 -0400
changeset 500825 023faad1dc96fba84125e3ace46dfa0e1019b30e
parent 500824 7ceee02e947617160e58b44122ea016cea95ac0c
child 500826 1143fd4a40f5c1d4fd08a0680d986070c2e9b6e1
push id49816
push userbmo:tchiovoloni@mozilla.com
push dateFri, 17 Mar 2017 20:44:02 +0000
reviewersdavidb
bugs1346439
milestone55.0a1
bug 1346439 - fixup linked list manipulation in CoalesceMutationEvents() r=davidb Its possible to coalesce away events such that the first two events in the queue are reorder events where the second reorder can be coalesced with the first. In that case there's no point in shuffling the list before removing the second reorder event.
accessible/base/NotificationController.cpp
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -324,30 +324,37 @@ NotificationController::CoalesceMutation
           AccReorderEvent* reorder = downcast_accEvent(mMutationMap.GetEvent(parent, EventMap::ReorderEvent));
 
           // We want to make sure that a reorder event comes after any show or
           // hide events targeted at the children of its target.  We keep the
           // invariant that event generation goes up as you are farther in the
           // queue, so we want to use the spot of the event with the higher
           // generation number, and keep that generation number.
           if (reorder && reorder->EventGeneration() < event->EventGeneration()) {
-            // There really should be a show or hide event before the first
-            // reorder event.
-            if (reorder->PrevEvent()) {
-              reorder->PrevEvent()->SetNextEvent(reorder->NextEvent());
-            } else {
-              mFirstMutationEvent = reorder->NextEvent();
+            reorder->SetEventGeneration(event->EventGeneration());
+
+            // It may be true that reorder was before event, and we coalesced
+            // away all the show / hide events between them.  In that case
+            // event is already immediately after reorder in the queue and we
+            // do not need to rearrange the list of events.
+            if (event != reorder->NextEvent()) {
+              // There really should be a show or hide event before the first
+              // reorder event.
+              if (reorder->PrevEvent()) {
+                reorder->PrevEvent()->SetNextEvent(reorder->NextEvent());
+              } else {
+                mFirstMutationEvent = reorder->NextEvent();
+              }
+
+              reorder->NextEvent()->SetPrevEvent(reorder->PrevEvent());
+              event->PrevEvent()->SetNextEvent(reorder);
+              reorder->SetPrevEvent(event->PrevEvent());
+              event->SetPrevEvent(reorder);
+              reorder->SetNextEvent(event);
             }
-
-            reorder->NextEvent()->SetPrevEvent(reorder->PrevEvent());
-            event->PrevEvent()->SetNextEvent(reorder);
-            reorder->SetPrevEvent(event->PrevEvent());
-            event->SetPrevEvent(reorder);
-            reorder->SetNextEvent(event);
-            reorder->SetEventGeneration(event->EventGeneration());
           }
           DropMutationEvent(event);
           break;
         }
 
         acc = parent;
       }
     } else if (eventType == nsIAccessibleEvent::EVENT_SHOW) {