|
26 | 26 |
|
27 | 27 | _bootContent: function() {
|
28 | 28 | this._useContent = this._useContent ||
|
29 |
| - (this._template && this._template.content.querySelector('content')); |
| 29 | + Boolean(this._template && |
| 30 | + this._template.content.querySelector('content')); |
30 | 31 | },
|
31 | 32 |
|
32 | 33 | poolContent: function() {
|
|
40 | 41 | root.host = this;
|
41 | 42 | // initialize the `root` pointers: `root` is guarenteed to always be
|
42 | 43 | // available, and be either `this` or `this.contentRoot`. By contrast,
|
43 |
| - // `contentRoot` is only set if _useContent is true. |
| 44 | + // `contentRoot` is only set if _useContent is true. |
44 | 45 | this.contentRoot = root;
|
45 | 46 | this.root = root;
|
46 | 47 | // TODO(jmesserly): ad-hoc signal for `ShadowDOM-lite-enhanced` root
|
|
53 | 54 | if (!this.contentRoot) {
|
54 | 55 | throw Error('poolContent() must be called before distributeContent()');
|
55 | 56 | }
|
| 57 | + // NOTE: `contentRoot` is populated only for the first |
| 58 | + // distribution. After that dom should be in the composed tree and |
| 59 | + // distribution info should not be reset. |
56 | 60 | // reset distributions
|
57 |
| - this._resetLightTree(this.contentRoot); |
| 61 | + this._resetDistribution(this.contentRoot); |
58 | 62 | // compute which nodes should be distributed where
|
59 | 63 | // TODO(jmesserly): this is simplified because we assume a single
|
60 | 64 | // ShadowRoot per host and no `<shadow>`.
|
61 |
| - this._poolDistribution(this.contentRoot, this._poolPopulation()); |
| 65 | + this._distributePool(this.contentRoot, this._collectPool()); |
62 | 66 | // update the real DOM to be the composed tree
|
63 | 67 | this._composeTree(this);
|
64 | 68 | },
|
|
93 | 97 | // still prefixed. Alternatively we could just polyfill it somewhere.
|
94 | 98 | // Note that the arguments are reversed from what you might expect.
|
95 | 99 | elementMatches: function(selector, node) {
|
96 |
| - if (node === undefined) node = this; |
| 100 | + if (node === undefined) { |
| 101 | + node = this; |
| 102 | + } |
97 | 103 | return matchesSelector.call(node, selector);
|
98 | 104 | },
|
99 | 105 |
|
100 |
| - _poolPopulation: function() { |
| 106 | + // Many of the following methods are all conceptually static, but they are |
| 107 | + // included here as "protected" methods to allow overriding. |
| 108 | + |
| 109 | + _resetDistribution: function(node) { |
| 110 | + var children = getLightChildren(node); |
| 111 | + for (var i = 0; i < children.length; i++) { |
| 112 | + var child = children[i]; |
| 113 | + if (isInsertionPoint(child)) { |
| 114 | + child._distributedNodes = []; |
| 115 | + } else if (child._destinationInsertionPoints) { |
| 116 | + child._destinationInsertionPoints = undefined; |
| 117 | + } |
| 118 | + this._resetDistribution(child); |
| 119 | + } |
| 120 | + }, |
| 121 | + |
| 122 | + _collectPool: function() { |
101 | 123 | // Gather the pool of nodes that should be distributed. We will combine
|
102 | 124 | // these with the "content root" to arrive at the composed tree.
|
103 | 125 | var pool = [];
|
|
113 | 135 | return pool;
|
114 | 136 | },
|
115 | 137 |
|
116 |
| - // Many of the following methods are all conceptually static, but they are |
117 |
| - // included here as "protected" methods to allow overriding. |
118 |
| - |
119 |
| - _resetLightTree: function(node) { |
120 |
| - var children = getLightChildren(node); |
121 |
| - for (var i = 0; i < children.length; i++) { |
122 |
| - var child = children[i]; |
123 |
| - if (isInsertionPoint(child)) { |
124 |
| - child._distributedNodes = []; |
125 |
| - } else if (child._destinationInsertionPoints) { |
126 |
| - child._destinationInsertionPoints = undefined; |
127 |
| - } |
128 |
| - this._resetLightTree(child); |
129 |
| - } |
130 |
| - }, |
131 |
| - |
132 |
| - _poolDistribution: function(node, pool) { |
133 |
| - if (node.localName == 'content') { |
| 138 | + _distributePool: function(node, pool) { |
| 139 | + if (isInsertionPoint(node)) { |
134 | 140 | // distribute nodes from the pool that this selector matches
|
135 | 141 | var content = node;
|
136 | 142 | var anyDistributed = false;
|
137 | 143 | for (var i = 0; i < pool.length; i++) {
|
138 | 144 | var node = pool[i];
|
139 | 145 | // skip nodes that were already used
|
140 |
| - if (!node) continue; |
| 146 | + if (!node) { |
| 147 | + continue; |
| 148 | + } |
141 | 149 | // distribute this node if it matches
|
142 | 150 | if (this._matchesContentSelect(node, content)) {
|
143 | 151 | distributeNodeInto(node, content);
|
|
159 | 167 | // recursively distribute.
|
160 | 168 | var children = getLightChildren(node);
|
161 | 169 | for (var i = 0; i < children.length; i++) {
|
162 |
| - this._poolDistribution(children[i], pool); |
| 170 | + this._distributePool(children[i], pool); |
163 | 171 | }
|
164 | 172 | },
|
165 | 173 |
|
|
220 | 228 | _matchesContentSelect: function(node, contentElement) {
|
221 | 229 | var select = contentElement.getAttribute('select');
|
222 | 230 | // no selector matches all nodes (including text)
|
223 |
| - if (!select) return true; |
| 231 | + if (!select) { |
| 232 | + return true; |
| 233 | + } |
224 | 234 | select = select.trim();
|
225 | 235 | // same thing if it had only whitespace
|
226 |
| - if (!select) return true; |
| 236 | + if (!select) { |
| 237 | + return true; |
| 238 | + } |
227 | 239 | // selectors can only match Elements
|
228 |
| - if (!(node instanceof Element)) return false; |
| 240 | + if (!(node instanceof Element)) { |
| 241 | + return false; |
| 242 | + } |
229 | 243 | // only valid selectors can match:
|
230 | 244 | // TypeSelector
|
231 | 245 | // *
|
|
234 | 248 | // AttributeSelector
|
235 | 249 | // negation
|
236 | 250 | var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/;
|
237 |
| - if (!validSelectors.test(select)) return false; |
| 251 | + if (!validSelectors.test(select)) { |
| 252 | + return false; |
| 253 | + } |
| 254 | + // TODO(sorvell): This try..catch seems unfortunate and will nerf |
| 255 | + // performance, can we remove? |
238 | 256 | try {
|
239 | 257 | return this.elementMatches(select, node);
|
240 | 258 | } catch (ex) {
|
241 | 259 | // Invalid selector.
|
242 | 260 | return false;
|
243 | 261 | }
|
244 | 262 | }
|
245 |
| - |
246 | 263 | });
|
247 | 264 |
|
248 | 265 | function distributeNodeInto(child, insertionPoint) {
|
|
0 commit comments