Bug 1255009 - insert children into the tree on content insertion instead the recaching, r=yzen
authorAlexander Surkov <surkov.alexander@gmail.com>
Fri, 11 Mar 2016 11:35:35 -0500
changeset 288292 4916251eb38968263c69c633fee264d129570768
parent 288291 d80794ec133731287eeadff04797d4cd93641509
child 288293 a8b7c33f5687a244a3abffb7b02b7c2ca231b7f8
push id30079
push userryanvm@gmail.com
push dateSat, 12 Mar 2016 20:24:19 +0000
treeherdermozilla-central@d1d47ba19ce9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyzen
bugs1255009
milestone48.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 1255009 - insert children into the tree on content insertion instead the recaching, r=yzen
accessible/generic/Accessible.cpp
accessible/generic/Accessible.h
accessible/generic/DocAccessible.cpp
accessible/tests/mochitest/actions/test_general.xul
accessible/tests/mochitest/actions/test_link.html
accessible/tests/mochitest/bounds/test_zoom.html
accessible/tests/mochitest/editabletext/editabletext.js
accessible/tests/mochitest/editabletext/test_1.html
accessible/tests/mochitest/events/test_coalescence.html
accessible/tests/mochitest/events/test_mutation.html
accessible/tests/mochitest/textcaret/test_browserui.xul
accessible/tests/mochitest/tree/test_dockids.html
accessible/tests/mochitest/tree/test_tabbrowser.xul
accessible/tests/mochitest/tree/test_txtctrl.xul
accessible/tests/mochitest/treeupdate/test_ariadialog.html
accessible/tests/mochitest/treeupdate/test_ariaowns.html
accessible/tests/mochitest/treeupdate/test_contextmenu.xul
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -11,16 +11,17 @@
 #include "AccGroupInfo.h"
 #include "AccIterator.h"
 #include "nsAccUtils.h"
 #include "nsAccessibilityService.h"
 #include "ApplicationAccessible.h"
 #include "nsEventShell.h"
 #include "nsTextEquivUtils.h"
 #include "DocAccessibleChild.h"
+#include "Logging.h"
 #include "Relation.h"
 #include "Role.h"
 #include "RootAccessible.h"
 #include "States.h"
 #include "StyleInfo.h"
 #include "TableAccessible.h"
 #include "TableCellAccessible.h"
 #include "TreeWalker.h"
@@ -1954,17 +1955,28 @@ Accessible::NativeName(nsString& aName)
 // Accessible protected
 void
 Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent)
 {
   NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
 
   if (mParent) {
     if (mParent != aParent) {
-      NS_ERROR("Adopting child!");
+#ifdef A11Y_LOG
+      if (logging::IsEnabled(logging::eTree)) {
+        logging::MsgBegin("TREE", "BindToParent: stealing accessible");
+        logging::AccessibleInfo("old parent", mParent);
+        logging::AccessibleInfo("new parent", aParent);
+        logging::AccessibleInfo("child", this);
+        logging::MsgEnd();
+      }
+#endif
+      // XXX: legalize adoption. As long as we don't invalidate the children,
+      // the accessibles start to steal them.
+
       mParent->InvalidateChildrenGroupInfo();
       mParent->RemoveChild(this);
     } else {
       NS_ERROR("Binding to the same parent!");
       return;
     }
   }
 
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -389,16 +389,24 @@ public:
   virtual void InvalidateChildren();
 
   /**
    * Append/insert/remove a child. Return true if operation was successful.
    */
   bool AppendChild(Accessible* aChild)
     { return InsertChildAt(mChildren.Length(), aChild); }
   virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild);
+
+  bool InsertAfter(Accessible* aNewChild, Accessible* aRefChild)
+  {
+    MOZ_ASSERT(aNewChild, "No new child to insert");
+    return InsertChildAt(aRefChild ? aRefChild->IndexInParent() + 1 : 0,
+                         aNewChild);
+  }
+
   virtual bool RemoveChild(Accessible* aChild);
 
   /**
    * Reallocates the child withing its parent.
    */
   void MoveChild(uint32_t aNewIndex, Accessible* aChild);
 
   //////////////////////////////////////////////////////////////////////////////
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1665,55 +1665,197 @@ DocAccessible::UpdateAccessibleOnAttrCha
     RecreateAccessible(aElement);
 
     return true;
   }
 
   return false;
 }
 
-void
-DocAccessible::ProcessContentInserted(Accessible* aContainer,
-                                      const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent)
+/**
+ * Content insertion helper.
+ */
+class InsertIterator final
 {
-  // Process insertions if the container accessible is still in tree.
-  if (!HasAccessible(aContainer->GetNode()))
-    return;
+public:
+  InsertIterator(Accessible* aContext,
+                 const nsTArray<nsCOMPtr<nsIContent> >* aNodes) :
+    mChild(nullptr), mChildBefore(nullptr), mWalker(aContext),
+    mStopNode(nullptr), mNodes(aNodes), mNodesIdx(0)
+  {
+    MOZ_ASSERT(aContext, "No context");
+    MOZ_ASSERT(aNodes, "No nodes to search for accessible elements");
+    MOZ_COUNT_CTOR(InsertIterator);
+  }
+  ~InsertIterator() { MOZ_COUNT_DTOR(InsertIterator); }
+
+  Accessible* Context() const { return mWalker.Context(); }
+  Accessible* Child() const { return mChild; }
+  Accessible* ChildBefore() const { return mChildBefore; }
+  DocAccessible* Document() const { return mWalker.Document(); }
+
+  /**
+   * Iterates to a next accessible within the inserted content.
+   */
+  bool Next();
 
-  for (uint32_t idx = 0; idx < aInsertedContent->Length(); idx++) {
+private:
+  Accessible* mChild;
+  Accessible* mChildBefore;
+  TreeWalker mWalker;
+  nsIContent* mStopNode;
+
+  const nsTArray<nsCOMPtr<nsIContent> >* mNodes;
+  uint32_t mNodesIdx;
+};
+
+bool
+InsertIterator::Next()
+{
+  if (mNodesIdx > 0) {
+    Accessible* nextChild = mWalker.Next(mStopNode);
+    if (nextChild) {
+      mChildBefore = mChild;
+      mChild = nextChild;
+      return true;
+    }
+  }
+
+  while (mNodesIdx < mNodes->Length()) {
+    // Ignore nodes that are not contained by the container anymore.
+
     // The container might be changed, for example, because of the subsequent
     // overlapping content insertion (i.e. other content was inserted between
     // this inserted content and its container or the content was reinserted
     // into different container of unrelated part of tree). To avoid a double
     // processing of the content insertion ignore this insertion notification.
-    // Note, the inserted content might be not in tree at all at this point what
-    // means there's no container. Ignore the insertion too.
-
-    Accessible* container =
-      GetContainerAccessible(aInsertedContent->ElementAt(idx));
-    if (container != aContainer)
+    // Note, the inserted content might be not in tree at all at this point
+    // what means there's no container. Ignore the insertion too.
+    nsIContent* prevNode = mNodes->SafeElementAt(mNodesIdx - 1);
+    nsIContent* node = mNodes->ElementAt(mNodesIdx++);
+    Accessible* container = Document()->GetContainerAccessible(node);
+    if (container != Context() || !container->IsAcceptableChild(node)) {
       continue;
-
-    if (container == this) {
-      // If new root content has been inserted then update it.
-      UpdateRootElIfNeeded();
-
-      // Continue to update the tree even if we don't have root content.
-      // For example, elements may be inserted under the document element while
-      // there is no HTML body element.
     }
 
-    // We have a DOM/layout change under the container accessible, and its tree
-    // might need an update. Since DOM/layout change of the element may affect
-    // on the accessibleness of adjacent elements (for example, insertion of
-    // extra HTML:body make the old body accessible) then we have to recache
-    // children of the container, and then fire show/hide events for a change.
-    UpdateTreeOnInsertion(container);
-    break;
+#ifdef A11Y_LOG
+    logging::TreeInfo("traversing an inserted node", logging::eVerbose,
+                      "container", container, "node", node);
+#endif
+
+    // If inserted nodes are siblings then just move the walker next.
+    if (prevNode && prevNode->GetNextSibling() == node) {
+      mStopNode = node;
+      Accessible* nextChild = mWalker.Next(mStopNode);
+      if (nextChild) {
+        mChildBefore = mChild;
+        mChild = nextChild;
+        return true;
+      }
+    }
+    else if (mWalker.Seek(node)) {
+      mStopNode = node;
+      mChildBefore = mWalker.Prev();
+      mChild = mWalker.Next(mStopNode);
+      if (mChild) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+void
+DocAccessible::ProcessContentInserted(Accessible* aContainer,
+                                      const nsTArray<nsCOMPtr<nsIContent> >* aNodes)
+{
+  // Process insertions if the container accessible is still in tree.
+  if (!HasAccessible(aContainer->GetNode()))
+    return;
+
+  // If new root content has been inserted then update it.
+  if (aContainer == this) {
+    UpdateRootElIfNeeded();
   }
+
+  uint32_t updateFlags = 0;
+  AutoTreeMutation mut(aContainer);
+  RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(aContainer);
+
+#ifdef A11Y_LOG
+  logging::TreeInfo("children before insertion", logging::eVerbose,
+                    aContainer);
+#endif
+
+  InsertIterator iter(aContainer, aNodes);
+  while (iter.Next()) {
+#ifdef A11Y_LOG
+    logging::TreeInfo("accessible is found", logging::eVerbose,
+                      "container", aContainer, "child", iter.Child(), nullptr);
+#endif
+
+    Accessible* parent = iter.Child()->Parent();
+    if (parent) {
+      if (parent != aContainer) {
+#ifdef A11Y_LOG
+        logging::TreeInfo("stealing accessible", 0,
+                          "old parent", parent, "new parent",
+                          aContainer, "child", iter.Child(), nullptr);
+#endif
+        MOZ_ASSERT_UNREACHABLE("stealing accessible");
+        continue;
+      }
+
+#ifdef A11Y_LOG
+      logging::TreeInfo("binding to same parent", logging::eVerbose,
+                        "parent", aContainer, "child", iter.Child(), nullptr);
+#endif
+      continue;
+    }
+
+    if (aContainer->InsertAfter(iter.Child(), iter.ChildBefore())) {
+#ifdef A11Y_LOG
+      logging::TreeInfo("accessible was accepted", 0,
+                        "container", aContainer, "child", iter.Child(), nullptr);
+#endif
+
+      updateFlags |= UpdateTreeInternal(iter.Child(), true, reorderEvent);
+      continue;
+    }
+
+    MOZ_ASSERT_UNREACHABLE("accessible was rejected");
+  }
+
+#ifdef A11Y_LOG
+  logging::TreeInfo("children after insertion", logging::eVerbose,
+                    aContainer);
+#endif
+
+  // Content insertion did not cause an accessible tree change.
+  if (updateFlags == eNoAccessible) {
+    return;
+  }
+
+  // Check to see if change occurred inside an alert, and fire an EVENT_ALERT
+  // if it did.
+  if (!(updateFlags & eAlertAccessible) &&
+      (aContainer->IsAlert() || aContainer->IsInsideAlert())) {
+    Accessible* ancestor = aContainer;
+    do {
+      if (ancestor->IsAlert()) {
+        FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, ancestor);
+        break;
+      }
+    }
+    while ((ancestor = ancestor->Parent()));
+  }
+
+  MaybeNotifyOfValueChange(aContainer);
+  FireDelayedEvent(reorderEvent);
 }
 
 void
 DocAccessible::UpdateTreeOnInsertion(Accessible* aContainer)
 {
   for (uint32_t idx = 0; idx < aContainer->ContentChildCount(); idx++) {
     Accessible* child = aContainer->ContentChildAt(idx);
     child->SetSurvivingInUpdate(true);
@@ -2251,9 +2393,8 @@ DocAccessible::IsLoadEventTarget() const
     // while there's no parent document yet).
     DocAccessible* parentDoc = ParentDocument();
     return parentDoc && parentDoc->HasLoadState(eCompletelyLoaded);
   }
 
   // It's content (not chrome) root document.
   return (treeItem->ItemType() == nsIDocShellTreeItem::typeContent);
 }
-
--- a/accessible/tests/mochitest/actions/test_general.xul
+++ b/accessible/tests/mochitest/actions/test_general.xul
@@ -16,16 +16,19 @@
           src="../common.js" />
   <script type="application/javascript"
           src="../events.js" />
   <script type="application/javascript"
           src="../actions.js" />
 
   <script type="application/javascript">
   <![CDATA[
+    //gA11yEventDumpToConsole = true;
+    //enableLogging("tree,verbose"); // debug
+
     if (navigator.platform.startsWith("Mac")) {
       SimpleTest.expectAssertions(0, 1);
     } else {
       SimpleTest.expectAssertions(0, 1);
     }
 
     function doTest()
     {
--- a/accessible/tests/mochitest/actions/test_link.html
+++ b/accessible/tests/mochitest/actions/test_link.html
@@ -50,17 +50,18 @@
 
       this.getID = function linkChecker_getID()
       {
         return "link '" + aID + "' states check ";
       }
     }
 
     //gA11yEventDumpID = "eventdump"; // debug stuff
-    gA11yEventDumpToConsole = true;
+    //gA11yEventDumpToConsole = true;
+    //enableLogging("tree");
 
     function doTest()
     {
       var actionsArray = [
         {
           ID: "link1",
           actionName: "jump",
           events: CLICK_EVENTS,
--- a/accessible/tests/mochitest/bounds/test_zoom.html
+++ b/accessible/tests/mochitest/bounds/test_zoom.html
@@ -18,16 +18,17 @@
           src="../events.js"></script>
   <script type="application/javascript"
           src="../layout.js"></script>
   <script type="application/javascript"
           src="../browser.js"></script>
 
   <script type="application/javascript">
     //gA11yEventDumpToConsole = true;
+    //enableLogging("tree,verbose");
     function doPreTest()
     {
       var tabDocument = currentTabDocument();
       var imgMap = tabDocument.getElementById("imgmap");
       waitForImageMap(imgMap, doTest);
     }
 
     function doTest()
--- a/accessible/tests/mochitest/editabletext/editabletext.js
+++ b/accessible/tests/mochitest/editabletext/editabletext.js
@@ -291,16 +291,18 @@ function editableTextTest(aID)
   {
     var et = this;
     var invoker = {
       eventSeq: [],
 
       invoke: aInvokeFunc,
       finalCheck: function finalCheck()
       {
+        //dumpTree(aID, `'${aID}' tree:`);
+
         aChecker.check();
         et.unwrapNextTest(); // replace dummy invoker on real invoker object.
       },
       getID: function getID() { return aInvokerID; }
     };
 
     if (aRemoveTriple) {
       var checker = new textChangeChecker(aID, aRemoveTriple[0],
--- a/accessible/tests/mochitest/editabletext/test_1.html
+++ b/accessible/tests/mochitest/editabletext/test_1.html
@@ -14,16 +14,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="editabletext.js"></script>
 
   <script type="application/javascript">
+    //gA11yEventDumpToConsole = true;
+    //enableLogging("tree,verbose"); // debug
 
     function addTestEditable(aID, aTestRun, aBeforeContent, aAfterContent)
     {
       var et = new editableTextTest(aID);
       var startOffset = aBeforeContent ? aBeforeContent.length : 0;
       // XXX afterContent currently is not used
 
       //////////////////////////////////////////////////////////////////////////
--- a/accessible/tests/mochitest/events/test_coalescence.html
+++ b/accessible/tests/mochitest/events/test_coalescence.html
@@ -323,16 +323,17 @@
       this.initSequence();
     }
 
     ////////////////////////////////////////////////////////////////////////////
     // Do tests.
 
     var gQueue = null;
     //gA11yEventDumpToConsole = true; // debug stuff
+    //enableLogging("tree");
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new removeChildNParent("option1", "select1"));
       gQueue.push(new removeParentNChild("option2", "select2"));
       gQueue.push(new hideChildNParent("option3", "select3"));
--- a/accessible/tests/mochitest/events/test_mutation.html
+++ b/accessible/tests/mochitest/events/test_mutation.html
@@ -409,21 +409,23 @@
       return children;
     }
 
     function getParent(aNode)
     {
       return aNode.parentNode;
     }
 
+    //gA11yEventDumpToConsole = true; // debug stuff
+    //enableLogging("tree,verbose");
+
     /**
      * Do tests.
      */
     var gQueue = null;
-    //gA11yEventDumpToConsole = true; // debug stuff
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       // Show/hide events by changing of display style of accessible DOM node
       // from 'inline' to 'none', 'none' to 'inline'.
       var id = "link1";
@@ -564,11 +566,10 @@
   </div>
   <div id="testContainer2"></div>
   <div id="testContainer3"></div>
 
   <div id="c4">
     <div style="visibility:hidden" id="c4_middle">
      <div style="visibility:visible" id="c4_child"></div>
    </div>
-  </div>
 </body>
 </html>
--- a/accessible/tests/mochitest/textcaret/test_browserui.xul
+++ b/accessible/tests/mochitest/textcaret/test_browserui.xul
@@ -23,18 +23,18 @@
           src="../browser.js"></script>
 
   <script type="application/javascript">
   <![CDATA[
 
     ////////////////////////////////////////////////////////////////////////////
     // Tests
 
-    //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true; // debug
+    //enableLogging("tree,verbose");
 
     var gQueue = null;
     function doTests()
     {
       gQueue = new eventQueue();
       gQueue.push(new setCaretOffset(urlbarInput(), -1, urlbarInput()));
       gQueue.push(new setCaretOffset(urlbarInput(), 0));
       gQueue.onFinish = function()
@@ -50,20 +50,18 @@
   ]]>
   </script>
 
   <vbox flex="1" style="overflow: auto;">
   <body xmlns="http://www.w3.org/1999/xhtml">
     <a target="_blank"
        href="https://bugzilla.mozilla.org/show_bug.cgi?id=723833"
        title="IAccessibleText::setCaretOffset on location or search bar causes focus to jump">
-      Mozilla Bug 723833
+      Bug 723833
     </a>
     <p id="display"></p>
     <div id="content" style="display: none">
     </div>
     <pre id="test">
     </pre>
   </body>
-
-  <vbox id="eventdump"></vbox>
   </vbox>
 </window>
--- a/accessible/tests/mochitest/tree/test_dockids.html
+++ b/accessible/tests/mochitest/tree/test_dockids.html
@@ -11,16 +11,18 @@
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
+  //gA11yEventDumpToConsole = true;
+  //enableLogging("tree,verbose");
   function doTest()
   {
     var tree =
      { DOCUMENT: [
        { TEXT_CONTAINER: [ // head
          { TEXT_CONTAINER: [ // link
            { STATICTEXT: [] }, // generated content
            { STATICTEXT: [] } // generated content
--- a/accessible/tests/mochitest/tree/test_tabbrowser.xul
+++ b/accessible/tests/mochitest/tree/test_tabbrowser.xul
@@ -196,16 +196,19 @@
       this.getID = function testTabHierarchy_getID()
       {
         return "hierarchy of tabs";
       }
     }
 
     ////////////////////////////////////////////////////////////////////////////
     // Test
+    //gA11yEventDumpToConsole = true;
+    //enableLogging("tree,verbose,stack");
+
     var gQueue = null;
     function doTest()
     {
       // Load documents into tabs and wait for docLoadComplete events caused by these
       // documents load before we start the test.
       gQueue = new eventQueue();
 
       gQueue.push(new testTabHierarchy());
--- a/accessible/tests/mochitest/tree/test_txtctrl.xul
+++ b/accessible/tests/mochitest/tree/test_txtctrl.xul
@@ -13,16 +13,19 @@
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
+    //gA11yEventDumpToConsole = true;
+    //enableLogging("tree,verbose"); // debug stuff
+
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     function doTest()
     {
       //////////////////////////////////////////////////////////////////////////
       // textboxes
 
@@ -155,16 +158,17 @@
           }
         );
         test_AutocompleteControl();
 
       } else {
         SimpleTest.ok(true, "Testing (New) Toolkit autocomplete widget.");
 
         // Dumb access to trigger popup lazy creation.
+        dump("Trigget popup lazy creation");
         waitForEvent(EVENT_REORDER, txc, test_AutocompleteControl);
         txc.popup;
 
         accTree.children.push(
           {
             role: ROLE_LIST,
             children: [
               {
--- a/accessible/tests/mochitest/treeupdate/test_ariadialog.html
+++ b/accessible/tests/mochitest/treeupdate/test_ariadialog.html
@@ -67,16 +67,17 @@
 
     //gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true;
 
     var gQueue = null;
 
     function doTest()
     {
+      //enableLogging("tree");
       gQueue = new eventQueue();
 
       // make the accessible an inaccessible
       gQueue.push(new showARIADialog("dialog"));
 
       gQueue.invoke(); // SimpleTest.finish() will be called in the end
     }
 
--- a/accessible/tests/mochitest/treeupdate/test_ariaowns.html
+++ b/accessible/tests/mochitest/treeupdate/test_ariaowns.html
@@ -189,18 +189,18 @@
       }
 
       this.finalCheck = function appendEl_finalCheck()
       {
         // children are invalidated, they includes aria-owns swapped kids and
         // newly inserted child.
         var tree =
           { SECTION: [
-              { CHECKBUTTON: [ ] },
-              { RADIOBUTTON: [ ] },
+              { CHECKBUTTON: [ ] }, // existing explicit, t1_checkbox
+              { RADIOBUTTON: [ ] }, // new explicit, t1_child3
               { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
               { SECTION: [ ] }, // ARIA owned, t1_subdiv
               { GROUPING: [ ] } // ARIA owned, t1_group
           ] };
         testAccessibleTree("t1_container", tree);
       }
 
       this.getID = function appendEl_getID()
@@ -223,18 +223,18 @@
         getNode("t1_span").parentNode.removeChild(getNode("t1_span"));
       }
 
       this.finalCheck = function removeEl_finalCheck()
       {
         // subdiv should go away
         var tree =
           { SECTION: [
-              { CHECKBUTTON: [ ] },
-              { RADIOBUTTON: [ ] },
+              { CHECKBUTTON: [ ] }, // explicit, t1_checkbox
+              { RADIOBUTTON: [ ] }, // explicit, t1_child3
               { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
               { GROUPING: [ ] } // ARIA owned, t1_group
           ] };
         testAccessibleTree("t1_container", tree);
       }
 
       this.getID = function removeEl_getID()
       {
--- a/accessible/tests/mochitest/treeupdate/test_contextmenu.xul
+++ b/accessible/tests/mochitest/treeupdate/test_contextmenu.xul
@@ -112,18 +112,18 @@
       }
 
       this.getID = function closeMenu_getID()
       {
         return "close menu " + prettyName(aID);
       }
     }
 
-    //gA11yEventDumpID = "eventdump";
     //gA11yEventDumpToConsole = true;
+    //enableLogging("tree,verbose");
 
     var gQueue = null;
     var gContextTree = {};
 
     // Linux and Windows menu trees discrepancy: bug 527646.
 
     /**
      * Return the context menu tree before submenus were open.
@@ -307,13 +307,11 @@
                 <menuitem id="item2.0.0" label="item2.0.0"/>
               </menupopup>
             </menu>
           </menupopup>
         </menu>
       </menupopup>
 
       <button context="context" id="button">btn</button>
-
-      <vbox id="eventdump" role="log"/>
     </vbox>
   </hbox>
 </window>