| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview A tree walker over the automation tree. | 6 * @fileoverview A tree walker over the automation tree. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 goog.provide('AutomationTreeWalker'); | 9 goog.provide('AutomationTreeWalker'); |
| 10 goog.provide('AutomationTreeWalkerPhase'); | 10 goog.provide('AutomationTreeWalkerPhase'); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 /** Walker is on a descendant of initial node. */ | 25 /** Walker is on a descendant of initial node. */ |
| 26 DESCENDANT: 'descendant', | 26 DESCENDANT: 'descendant', |
| 27 /** Walker is on a node not covered by any other phase. */ | 27 /** Walker is on a node not covered by any other phase. */ |
| 28 OTHER: 'other' | 28 OTHER: 'other' |
| 29 }; | 29 }; |
| 30 | 30 |
| 31 /** | 31 /** |
| 32 * @typedef {{leaf: (AutomationPredicate.Unary|undefined), | 32 * @typedef {{leaf: (AutomationPredicate.Unary|undefined), |
| 33 * root: (AutomationPredicate.Unary|undefined), | 33 * root: (AutomationPredicate.Unary|undefined), |
| 34 * visit: (AutomationPredicate.Unary|undefined), | 34 * visit: (AutomationPredicate.Unary|undefined), |
| 35 * skipInitialAncestry: (boolean|undefined), |
| 35 * skipInitialSubtree: (boolean|undefined)}} | 36 * skipInitialSubtree: (boolean|undefined)}} |
| 36 */ | 37 */ |
| 37 var AutomationTreeWalkerRestriction; | 38 var AutomationTreeWalkerRestriction; |
| 38 | 39 |
| 39 /** | 40 /** |
| 40 * An AutomationTreeWalker provides an incremental pre order traversal of the | 41 * An AutomationTreeWalker provides an incremental pre order traversal of the |
| 41 * automation tree starting at a particular node. | 42 * automation tree starting at a particular node. |
| 42 * | 43 * |
| 43 * Given a flat list of nodes in pre order, the walker moves forward or backward | 44 * Given a flat list of nodes in pre order, the walker moves forward or backward |
| 44 * a node at a time on each call of |next|. | 45 * a node at a time on each call of |next|. |
| 45 * | 46 * |
| 46 * A caller can visit a subset of this list by supplying restricting | 47 * A caller can visit a subset of this list by supplying restricting |
| 47 * predicates. There are three such restricting predicates allowed: | 48 * predicates. There are three such restricting predicates allowed: |
| 48 * visit: this predicate determines if a given node should be returned when | 49 * visit: this predicate determines if a given node should be returned when |
| 49 * moving to a node in the flattened pre-order list. If not, this walker will | 50 * moving to a node in the flattened pre-order list. If not, this walker will |
| 50 * continue to the next (directed) node in the list, looking for a predicate | 51 * continue to the next (directed) node in the list, looking for a predicate |
| 51 * match. | 52 * match. |
| 52 * root: this predicate determines if a node should end upward movement in the | 53 * root: this predicate determines if a node should end upward movement in the |
| 53 * tree. | 54 * tree. |
| 54 * leaf: this predicate determines if a node should end downward movement in the | 55 * leaf: this predicate determines if a node should end downward movement in the |
| 55 * tree. | 56 * tree. |
| 56 * | 57 * |
| 58 * |skipInitialAncestry| skips visiting ancestor nodes of the start node for |
| 59 * multiple invokations of next when moving backward. |
| 60 * |
| 57 * Finally, a boolean, |skipInitialSubtree|, makes the first invocation of | 61 * Finally, a boolean, |skipInitialSubtree|, makes the first invocation of |
| 58 * |next| skip the initial node's subtree when finding a match. This is useful | 62 * |next| skip the initial node's subtree when finding a match. This is useful |
| 59 * to establish a known initial state when the initial node may not match any of | 63 * to establish a known initial state when the initial node may not match any of |
| 60 * the given predicates. | 64 * the given predicates. |
| 61 * | 65 * |
| 62 * Given the above definitions, if supplied with a root and leaf predicate that | 66 * Given the above definitions, if supplied with a root and leaf predicate that |
| 63 * always returns false, and a visit predicate that always returns true, the | 67 * always returns false, and a visit predicate that always returns true, the |
| 64 * walker would visit all nodes in pre order. If a caller does not supply a | 68 * walker would visit all nodes in pre order. If a caller does not supply a |
| 65 * particular predicate, it will default to these "identity" predicates. | 69 * particular predicate, it will default to these "identity" predicates. |
| 66 * | 70 * |
| (...skipping 13 matching lines...) Expand all Loading... |
| 80 /** @const {!chrome.automation.AutomationNode} @private */ | 84 /** @const {!chrome.automation.AutomationNode} @private */ |
| 81 this.initialNode_ = node; | 85 this.initialNode_ = node; |
| 82 /** | 86 /** |
| 83 * Deepest common ancestor of initialNode and node. Valid only when moving | 87 * Deepest common ancestor of initialNode and node. Valid only when moving |
| 84 * backward. | 88 * backward. |
| 85 * @type {chrome.automation.AutomationNode} @private | 89 * @type {chrome.automation.AutomationNode} @private |
| 86 */ | 90 */ |
| 87 this.backwardAncestor_ = node.parent; | 91 this.backwardAncestor_ = node.parent; |
| 88 var restrictions = opt_restrictions || {}; | 92 var restrictions = opt_restrictions || {}; |
| 89 | 93 |
| 90 this.visitPred_ = | 94 this.visitPred_ = function(node) { |
| 91 restrictions.visit ? restrictions.visit : function() { return true; }; | 95 if (this.skipInitialAncestry_ && |
| 96 this.phase_ == AutomationTreeWalkerPhase.ANCESTOR) |
| 97 return false; |
| 98 |
| 99 if (this.skipInitialSubtree_ && |
| 100 this.phase != AutomationTreeWalkerPhase.ANCESTOR && |
| 101 this.phase != AutomationTreeWalkerPhase.OTHER) |
| 102 return false; |
| 103 |
| 104 if (restrictions.visit) |
| 105 return restrictions.visit(node); |
| 106 |
| 107 return true; |
| 108 }; |
| 92 /** @type {AutomationPredicate.Unary} @private */ | 109 /** @type {AutomationPredicate.Unary} @private */ |
| 93 this.leafPred_ = restrictions.leaf ? restrictions.leaf : | 110 this.leafPred_ = restrictions.leaf ? restrictions.leaf : |
| 94 AutomationTreeWalker.falsePredicate_; | 111 AutomationTreeWalker.falsePredicate_; |
| 95 /** @type {AutomationPredicate.Unary} @private */ | 112 /** @type {AutomationPredicate.Unary} @private */ |
| 96 this.rootPred_ = restrictions.root ? restrictions.root : | 113 this.rootPred_ = restrictions.root ? restrictions.root : |
| 97 AutomationTreeWalker.falsePredicate_; | 114 AutomationTreeWalker.falsePredicate_; |
| 98 /** @const {boolean} @private */ | 115 /** @const {boolean} @private */ |
| 116 this.skipInitialAncestry_ = restrictions.skipInitialAncestry || false; |
| 117 /** @const {boolean} @private */ |
| 99 this.skipInitialSubtree_ = restrictions.skipInitialSubtree || false; | 118 this.skipInitialSubtree_ = restrictions.skipInitialSubtree || false; |
| 100 }; | 119 }; |
| 101 | 120 |
| 102 /** | 121 /** |
| 103 * @param {!chrome.automation.AutomationNode} node | 122 * @param {!chrome.automation.AutomationNode} node |
| 104 * @return {boolean} | 123 * @return {boolean} |
| 105 * @private | 124 * @private |
| 106 */ | 125 */ |
| 107 AutomationTreeWalker.falsePredicate_ = function(node) { | 126 AutomationTreeWalker.falsePredicate_ = function(node) { |
| 108 return false; | 127 return false; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 }, | 161 }, |
| 143 | 162 |
| 144 /** | 163 /** |
| 145 * @param {!chrome.automation.AutomationNode} node | 164 * @param {!chrome.automation.AutomationNode} node |
| 146 * @private | 165 * @private |
| 147 */ | 166 */ |
| 148 forward_: function(node) { | 167 forward_: function(node) { |
| 149 if (!this.leafPred_(node) && node.firstChild) { | 168 if (!this.leafPred_(node) && node.firstChild) { |
| 150 if (this.phase_ == AutomationTreeWalkerPhase.INITIAL) | 169 if (this.phase_ == AutomationTreeWalkerPhase.INITIAL) |
| 151 this.phase_ = AutomationTreeWalkerPhase.DESCENDANT; | 170 this.phase_ = AutomationTreeWalkerPhase.DESCENDANT; |
| 171 |
| 152 if (!this.skipInitialSubtree_ || | 172 if (!this.skipInitialSubtree_ || |
| 153 this.phase != AutomationTreeWalkerPhase.DESCENDANT) { | 173 this.phase != AutomationTreeWalkerPhase.DESCENDANT) { |
| 154 this.node_ = node.firstChild; | 174 this.node_ = node.firstChild; |
| 155 return; | 175 return; |
| 156 } | 176 } |
| 157 } | 177 } |
| 158 | 178 |
| 159 var searchNode = node; | 179 var searchNode = node; |
| 160 while (searchNode) { | 180 while (searchNode) { |
| 161 // We have crossed out of the initial node's subtree. | 181 // We have crossed out of the initial node's subtree. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 189 this.node_ = node; | 209 this.node_ = node; |
| 190 return; | 210 return; |
| 191 } | 211 } |
| 192 if (node.parent && this.backwardAncestor_ == node.parent) { | 212 if (node.parent && this.backwardAncestor_ == node.parent) { |
| 193 this.phase_ = AutomationTreeWalkerPhase.ANCESTOR; | 213 this.phase_ = AutomationTreeWalkerPhase.ANCESTOR; |
| 194 this.backwardAncestor_ = node.parent.parent; | 214 this.backwardAncestor_ = node.parent.parent; |
| 195 } | 215 } |
| 196 this.node_ = node.parent; | 216 this.node_ = node.parent; |
| 197 } | 217 } |
| 198 }; | 218 }; |
| OLD | NEW |