Bug 877124 - [AccessFu] Trust explicitly associated names of the current pivot and its children. r=eeejay
authorYura Zenevich <yura.zenevich@gmail.com>
Mon, 10 Jun 2013 13:31:17 -0700
changeset 134557 39664fe37dd30a47369a687872be37bf7c483487
parent 134556 d3c0ebcaf1375261117530656f62dfa9a30810f5
child 134558 d79910d9e251d19669dbc8fb0a5f31b8d8b2d6ed
push id29268
push usereisaacson@mozilla.com
push dateMon, 10 Jun 2013 20:31:29 +0000
treeherdermozilla-inbound@d79910d9e251 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerseeejay
bugs877124
milestone24.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 877124 - [AccessFu] Trust explicitly associated names of the current pivot and its children. r=eeejay
accessible/src/jsat/Utils.jsm
accessible/src/jsat/UtteranceGenerator.jsm
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -378,54 +378,51 @@ PivotContext.prototype = {
     }
 
     return this._newAncestry;
   },
 
   /*
    * Traverse the accessible's subtree in pre or post order.
    * It only includes the accessible's visible chidren.
+   * Note: needSubtree is a function argument that can be used to determine
+   * whether aAccessible's subtree is required.
    */
-  _traverse: function _traverse(aAccessible, preorder) {
-    let list = [];
+  _traverse: function _traverse(aAccessible, aPreorder, aStop) {
+    if (aStop && aStop(aAccessible)) {
+      return;
+    }
     let child = aAccessible.firstChild;
     while (child) {
       let state = {};
       child.getState(state, {});
       if (!(state.value & Ci.nsIAccessibleStates.STATE_INVISIBLE)) {
-        let traversed = _traverse(child, preorder);
-        // Prepend or append a child, based on traverse order.
-        traversed[preorder ? "unshift" : "push"](child);
-        list.push.apply(list, traversed);
+        if (aPreorder) {
+          yield child;
+          [yield node for (node of this._traverse(child, aPreorder, aStop))];
+        } else {
+          [yield node for (node of this._traverse(child, aPreorder, aStop))];
+          yield child;
+        }
       }
       child = child.nextSibling;
     }
-    return list;
   },
 
   /*
-   * This is a flattened list of the accessible's subtree in preorder.
+   * A subtree generator function, used to generate a flattened
+   * list of the accessible's subtree in pre or post order.
    * It only includes the accessible's visible chidren.
+   * @param {boolean} aPreorder A flag for traversal order. If true, traverse
+   * in preorder; if false, traverse in postorder.
+   * @param {function} aStop An optional function, indicating whether subtree
+   * traversal should stop.
    */
-  get subtreePreorder() {
-    if (!this._subtreePreOrder)
-      this._subtreePreOrder = this._traverse(this._accessible, true);
-
-    return this._subtreePreOrder;
-  },
-
-  /*
-   * This is a flattened list of the accessible's subtree in postorder.
-   * It only includes the accessible's visible chidren.
-   */
-  get subtreePostorder() {
-    if (!this._subtreePostOrder)
-      this._subtreePostOrder = this._traverse(this._accessible, false);
-
-    return this._subtreePostOrder;
+  subtreeGenerator: function subtreeGenerator(aPreorder, aStop) {
+    return this._traverse(this._accessible, aPreorder, aStop);
   },
 
   get bounds() {
     if (!this._bounds) {
       let objX = {}, objY = {}, objW = {}, objH = {};
 
       this._accessible.getBounds(objX, objY, objW, objH);
 
--- a/accessible/src/jsat/UtteranceGenerator.jsm
+++ b/accessible/src/jsat/UtteranceGenerator.jsm
@@ -70,34 +70,34 @@ this.UtteranceGenerator = {
    *    starting from the accessible's ancestry or accessible's subtree.
    */
   genForContext: function genForContext(aContext) {
     let utterance = [];
     let addUtterance = function addUtterance(aAccessible) {
       utterance.push.apply(utterance,
         UtteranceGenerator.genForObject(aAccessible));
     };
-    let roleString = Utils.AccRetrieval.getStringRole(aContext.accessible.role);
-    let nameRule = this.roleRuleMap[roleString] || 0;
+    let ignoreSubtree = function ignoreSubtree(aAccessible) {
+      let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
+      let nameRule = UtteranceGenerator.roleRuleMap[roleString] || 0;
+      // Ignore subtree if the name is explicit and the role's name rule is the
+      // NAME_FROM_SUBTREE_RULE.
+      return (nameRule & NAME_FROM_SUBTREE_RULE) &&
+        (Utils.getAttributes(aAccessible)['explicit-name'] === 'true');
+    };
     let utteranceOrder = gUtteranceOrder.value || UTTERANCE_DESC_FIRST;
-    // Include subtree if the name is not explicit or the role's name rule is
-    // not the NAME_FROM_SUBTREE_RULE.
-    let includeSubtree = (Utils.getAttributes(aContext.accessible)[
-      'explicit-name'] !== 'true') || !(nameRule & NAME_FROM_SUBTREE_RULE);
 
     if (utteranceOrder === UTTERANCE_DESC_FIRST) {
       aContext.newAncestry.forEach(addUtterance);
       addUtterance(aContext.accessible);
-      if (includeSubtree) {
-        aContext.subtreePreorder.forEach(addUtterance);
-      }
+      [addUtterance(node) for
+        (node of aContext.subtreeGenerator(true, ignoreSubtree))];
     } else {
-      if (includeSubtree) {
-        aContext.subtreePostorder.forEach(addUtterance);
-      }
+      [addUtterance(node) for
+        (node of aContext.subtreeGenerator(false, ignoreSubtree))];
       addUtterance(aContext.accessible);
       aContext.newAncestry.reverse().forEach(addUtterance);
     }
 
     // Clean up the white space.
     let trimmed;
     utterance = [trimmed for (word of utterance) if (trimmed = word.trim())];