Bug 1261377 - "With current child caching reorganization, NVDA is no longer able to render some content". r=mzehe
authoralexander <surkov.alexander>
Fri, 01 Apr 2016 09:39:00 +0200
changeset 347730 954444d01cd10f263850121c87c706ca65682cd3
parent 347729 e02a9b1b4931191f2fccc397e75ae8c28ef47460
child 347731 725a9dc9e9bf0dedbbfabe8481b28eaad329ac46
push id14653
push userolivier@olivieryiptong.com
push dateTue, 05 Apr 2016 19:21:01 +0000
reviewersmzehe
bugs1261377
milestone48.0a1
Bug 1261377 - "With current child caching reorganization, NVDA is no longer able to render some content". r=mzehe
accessible/generic/HyperTextAccessible.cpp
accessible/generic/HyperTextAccessible.h
accessible/tests/mochitest/text/a11y.ini
accessible/tests/mochitest/text/test_dynamic.html
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -1901,16 +1901,26 @@ HyperTextAccessible::RemoveChild(Accessi
   int32_t childIndex = aAccessible->IndexInParent();
   int32_t count = mOffsets.Length() - childIndex;
   if (count > 0)
     mOffsets.RemoveElementsAt(childIndex, count);
 
   return Accessible::RemoveChild(aAccessible);
 }
 
+bool
+HyperTextAccessible::InsertChildAt(uint32_t aIndex, Accessible* aChild)
+{
+  int32_t count = mOffsets.Length() - aIndex;
+  if (count > 0 ) {
+    mOffsets.RemoveElementsAt(aIndex, count);
+  }
+  return Accessible::InsertChildAt(aIndex, aChild);
+}
+
 Relation
 HyperTextAccessible::RelationByType(RelationType aType)
 {
   Relation rel = Accessible::RelationByType(aType);
 
   switch (aType) {
     case RelationType::NODE_CHILD_OF:
       if (HasOwnContent() && mContent->IsMathMLElement()) {
--- a/accessible/generic/HyperTextAccessible.h
+++ b/accessible/generic/HyperTextAccessible.h
@@ -57,16 +57,17 @@ public:
   virtual nsIAtom* LandmarkRole() const override;
   virtual int32_t GetLevelInternal() override;
   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() override;
   virtual mozilla::a11y::role NativeRole() override;
   virtual uint64_t NativeState() override;
 
   virtual void Shutdown() override;
   virtual bool RemoveChild(Accessible* aAccessible) override;
+  virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild) override;
   virtual Relation RelationByType(RelationType aType) override;
 
   // HyperTextAccessible (static helper method)
 
   // Convert content offset to rendered text offset
   nsresult ContentToRenderedOffset(nsIFrame *aFrame, int32_t aContentOffset,
                                    uint32_t *aRenderedOffset) const;
 
--- a/accessible/tests/mochitest/text/a11y.ini
+++ b/accessible/tests/mochitest/text/a11y.ini
@@ -1,15 +1,16 @@
 [DEFAULT]
 support-files = doc.html
   !/accessible/tests/mochitest/*.js
 
 [test_atcaretoffset.html]
 [test_charboundary.html]
 [test_doc.html]
+[test_dynamic.html]
 [test_general.xul]
 [test_gettext.html]
 [test_hypertext.html]
 [test_lineboundary.html]
 [test_passwords.html]
 [test_selection.html]
 [test_wordboundary.html]
 [test_words.html]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/text/test_dynamic.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>nsIAccessibleText getText related function tests for tree mutations</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../text.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+    function insertBefore(aId, aEl, aTextBefore, aTextAfter, aStartIdx, aEndIdx)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, aId)
+      ];
+
+      this.invoke = function insertBefore_invoke()
+      {
+        testText(aId, 0, -1, aTextBefore);
+        getNode(aId).insertBefore(aEl, getNode(aId).firstChild);
+      }
+
+      this.finalCheck = function insertBefore_finalCheck()
+      {
+        testText(aId, aStartIdx, aEndIdx, aTextAfter);
+      }
+
+      this.getID = function insertTextBefore_getID() {
+        return "insert " + prettyName(aEl) + " before";
+      }
+    }
+
+    function insertTextBefore(aId, aTextBefore, aText)
+    {
+      var el = document.createTextNode(aText);
+      this.__proto__ = new insertBefore(aId, el, aTextBefore,
+                                        aText + aTextBefore, 0, -1)
+    }
+
+    function insertImgBefore(aId, aTextBefore)
+    {
+      var el = document.createElement("img");
+      el.setAttribute("src", "../moz.png");
+      el.setAttribute("alt", "mozilla");
+
+      this.__proto__ = new insertBefore(aId, el, aTextBefore,
+                                        kEmbedChar + aTextBefore, 0, -1)
+    }
+
+    function insertTextBefore2(aId)
+    {
+      var el = document.createTextNode("hehe");
+      this.__proto__ = new insertBefore(aId, el, "ho", "ho", 4, -1)
+    }
+
+    var gQueue = null;
+    function doTest()
+    {
+      gQueue = new eventQueue();
+      gQueue.push(new insertTextBefore("c1", "ho", "ha"));
+      gQueue.push(new insertImgBefore("c1", "haho"));
+      gQueue.push(new insertImgBefore("c2", kEmbedChar));
+      gQueue.push(new insertTextBefore2("c3"));
+      gQueue.invoke(); // will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="c1">ho</div>
+  <div id="c2"><img src="../moz.png" alt="mozilla"></div>
+  <div id="c3">ho</div>
+</body>
+</html>