| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 * @unrestricted | 5 * @unrestricted |
| 6 */ | 6 */ |
| 7 WebInspector.CSSMatchedStyles = class { | 7 SDK.CSSMatchedStyles = class { |
| 8 /** | 8 /** |
| 9 * @param {!WebInspector.CSSModel} cssModel | 9 * @param {!SDK.CSSModel} cssModel |
| 10 * @param {!WebInspector.DOMNode} node | 10 * @param {!SDK.DOMNode} node |
| 11 * @param {?Protocol.CSS.CSSStyle} inlinePayload | 11 * @param {?Protocol.CSS.CSSStyle} inlinePayload |
| 12 * @param {?Protocol.CSS.CSSStyle} attributesPayload | 12 * @param {?Protocol.CSS.CSSStyle} attributesPayload |
| 13 * @param {!Array.<!Protocol.CSS.RuleMatch>} matchedPayload | 13 * @param {!Array.<!Protocol.CSS.RuleMatch>} matchedPayload |
| 14 * @param {!Array.<!Protocol.CSS.PseudoElementMatches>} pseudoPayload | 14 * @param {!Array.<!Protocol.CSS.PseudoElementMatches>} pseudoPayload |
| 15 * @param {!Array.<!Protocol.CSS.InheritedStyleEntry>} inheritedPayload | 15 * @param {!Array.<!Protocol.CSS.InheritedStyleEntry>} inheritedPayload |
| 16 * @param {!Array.<!Protocol.CSS.CSSKeyframesRule>} animationsPayload | 16 * @param {!Array.<!Protocol.CSS.CSSKeyframesRule>} animationsPayload |
| 17 */ | 17 */ |
| 18 constructor( | 18 constructor( |
| 19 cssModel, | 19 cssModel, |
| 20 node, | 20 node, |
| 21 inlinePayload, | 21 inlinePayload, |
| 22 attributesPayload, | 22 attributesPayload, |
| 23 matchedPayload, | 23 matchedPayload, |
| 24 pseudoPayload, | 24 pseudoPayload, |
| 25 inheritedPayload, | 25 inheritedPayload, |
| 26 animationsPayload) { | 26 animationsPayload) { |
| 27 this._cssModel = cssModel; | 27 this._cssModel = cssModel; |
| 28 this._node = node; | 28 this._node = node; |
| 29 this._nodeStyles = []; | 29 this._nodeStyles = []; |
| 30 this._nodeForStyle = new Map(); | 30 this._nodeForStyle = new Map(); |
| 31 this._inheritedStyles = new Set(); | 31 this._inheritedStyles = new Set(); |
| 32 this._keyframes = []; | 32 this._keyframes = []; |
| 33 /** @type {!Map<!Protocol.DOM.NodeId, !Map<string, boolean>>} */ | 33 /** @type {!Map<!Protocol.DOM.NodeId, !Map<string, boolean>>} */ |
| 34 this._matchingSelectors = new Map(); | 34 this._matchingSelectors = new Map(); |
| 35 | 35 |
| 36 /** | 36 /** |
| 37 * @this {WebInspector.CSSMatchedStyles} | 37 * @this {SDK.CSSMatchedStyles} |
| 38 */ | 38 */ |
| 39 function addAttributesStyle() { | 39 function addAttributesStyle() { |
| 40 if (!attributesPayload) | 40 if (!attributesPayload) |
| 41 return; | 41 return; |
| 42 var style = new WebInspector.CSSStyleDeclaration( | 42 var style = new SDK.CSSStyleDeclaration( |
| 43 cssModel, null, attributesPayload, WebInspector.CSSStyleDeclaration.Ty
pe.Attributes); | 43 cssModel, null, attributesPayload, SDK.CSSStyleDeclaration.Type.Attrib
utes); |
| 44 this._nodeForStyle.set(style, this._node); | 44 this._nodeForStyle.set(style, this._node); |
| 45 this._nodeStyles.push(style); | 45 this._nodeStyles.push(style); |
| 46 } | 46 } |
| 47 | 47 |
| 48 // Inline style has the greatest specificity. | 48 // Inline style has the greatest specificity. |
| 49 if (inlinePayload && this._node.nodeType() === Node.ELEMENT_NODE) { | 49 if (inlinePayload && this._node.nodeType() === Node.ELEMENT_NODE) { |
| 50 var style = new WebInspector.CSSStyleDeclaration( | 50 var style = new SDK.CSSStyleDeclaration( |
| 51 cssModel, null, inlinePayload, WebInspector.CSSStyleDeclaration.Type.I
nline); | 51 cssModel, null, inlinePayload, SDK.CSSStyleDeclaration.Type.Inline); |
| 52 this._nodeForStyle.set(style, this._node); | 52 this._nodeForStyle.set(style, this._node); |
| 53 this._nodeStyles.push(style); | 53 this._nodeStyles.push(style); |
| 54 } | 54 } |
| 55 | 55 |
| 56 // Add rules in reverse order to match the cascade order. | 56 // Add rules in reverse order to match the cascade order. |
| 57 var addedAttributesStyle; | 57 var addedAttributesStyle; |
| 58 for (var i = matchedPayload.length - 1; i >= 0; --i) { | 58 for (var i = matchedPayload.length - 1; i >= 0; --i) { |
| 59 var rule = new WebInspector.CSSStyleRule(cssModel, matchedPayload[i].rule)
; | 59 var rule = new SDK.CSSStyleRule(cssModel, matchedPayload[i].rule); |
| 60 if ((rule.isInjected() || rule.isUserAgent()) && !addedAttributesStyle) { | 60 if ((rule.isInjected() || rule.isUserAgent()) && !addedAttributesStyle) { |
| 61 // Show element's Style Attributes after all author rules. | 61 // Show element's Style Attributes after all author rules. |
| 62 addedAttributesStyle = true; | 62 addedAttributesStyle = true; |
| 63 addAttributesStyle.call(this); | 63 addAttributesStyle.call(this); |
| 64 } | 64 } |
| 65 this._nodeForStyle.set(rule.style, this._node); | 65 this._nodeForStyle.set(rule.style, this._node); |
| 66 this._nodeStyles.push(rule.style); | 66 this._nodeStyles.push(rule.style); |
| 67 addMatchingSelectors.call(this, this._node, rule, matchedPayload[i].matchi
ngSelectors); | 67 addMatchingSelectors.call(this, this._node, rule, matchedPayload[i].matchi
ngSelectors); |
| 68 } | 68 } |
| 69 | 69 |
| 70 if (!addedAttributesStyle) | 70 if (!addedAttributesStyle) |
| 71 addAttributesStyle.call(this); | 71 addAttributesStyle.call(this); |
| 72 | 72 |
| 73 // Walk the node structure and identify styles with inherited properties. | 73 // Walk the node structure and identify styles with inherited properties. |
| 74 var parentNode = this._node.parentNode; | 74 var parentNode = this._node.parentNode; |
| 75 for (var i = 0; parentNode && inheritedPayload && i < inheritedPayload.lengt
h; ++i) { | 75 for (var i = 0; parentNode && inheritedPayload && i < inheritedPayload.lengt
h; ++i) { |
| 76 var entryPayload = inheritedPayload[i]; | 76 var entryPayload = inheritedPayload[i]; |
| 77 var inheritedInlineStyle = entryPayload.inlineStyle ? | 77 var inheritedInlineStyle = entryPayload.inlineStyle ? |
| 78 new WebInspector.CSSStyleDeclaration( | 78 new SDK.CSSStyleDeclaration( |
| 79 cssModel, null, entryPayload.inlineStyle, WebInspector.CSSStyleDec
laration.Type.Inline) : | 79 cssModel, null, entryPayload.inlineStyle, SDK.CSSStyleDeclaration.
Type.Inline) : |
| 80 null; | 80 null; |
| 81 if (inheritedInlineStyle && this._containsInherited(inheritedInlineStyle))
{ | 81 if (inheritedInlineStyle && this._containsInherited(inheritedInlineStyle))
{ |
| 82 this._nodeForStyle.set(inheritedInlineStyle, parentNode); | 82 this._nodeForStyle.set(inheritedInlineStyle, parentNode); |
| 83 this._nodeStyles.push(inheritedInlineStyle); | 83 this._nodeStyles.push(inheritedInlineStyle); |
| 84 this._inheritedStyles.add(inheritedInlineStyle); | 84 this._inheritedStyles.add(inheritedInlineStyle); |
| 85 } | 85 } |
| 86 | 86 |
| 87 var inheritedMatchedCSSRules = entryPayload.matchedCSSRules || []; | 87 var inheritedMatchedCSSRules = entryPayload.matchedCSSRules || []; |
| 88 for (var j = inheritedMatchedCSSRules.length - 1; j >= 0; --j) { | 88 for (var j = inheritedMatchedCSSRules.length - 1; j >= 0; --j) { |
| 89 var inheritedRule = new WebInspector.CSSStyleRule(cssModel, inheritedMat
chedCSSRules[j].rule); | 89 var inheritedRule = new SDK.CSSStyleRule(cssModel, inheritedMatchedCSSRu
les[j].rule); |
| 90 addMatchingSelectors.call(this, parentNode, inheritedRule, inheritedMatc
hedCSSRules[j].matchingSelectors); | 90 addMatchingSelectors.call(this, parentNode, inheritedRule, inheritedMatc
hedCSSRules[j].matchingSelectors); |
| 91 if (!this._containsInherited(inheritedRule.style)) | 91 if (!this._containsInherited(inheritedRule.style)) |
| 92 continue; | 92 continue; |
| 93 this._nodeForStyle.set(inheritedRule.style, parentNode); | 93 this._nodeForStyle.set(inheritedRule.style, parentNode); |
| 94 this._nodeStyles.push(inheritedRule.style); | 94 this._nodeStyles.push(inheritedRule.style); |
| 95 this._inheritedStyles.add(inheritedRule.style); | 95 this._inheritedStyles.add(inheritedRule.style); |
| 96 } | 96 } |
| 97 parentNode = parentNode.parentNode; | 97 parentNode = parentNode.parentNode; |
| 98 } | 98 } |
| 99 | 99 |
| 100 // Set up pseudo styles map. | 100 // Set up pseudo styles map. |
| 101 this._pseudoStyles = new Map(); | 101 this._pseudoStyles = new Map(); |
| 102 if (pseudoPayload) { | 102 if (pseudoPayload) { |
| 103 for (var i = 0; i < pseudoPayload.length; ++i) { | 103 for (var i = 0; i < pseudoPayload.length; ++i) { |
| 104 var entryPayload = pseudoPayload[i]; | 104 var entryPayload = pseudoPayload[i]; |
| 105 // PseudoElement nodes are not created unless "content" css property is
set. | 105 // PseudoElement nodes are not created unless "content" css property is
set. |
| 106 var pseudoElement = this._node.pseudoElements().get(entryPayload.pseudoT
ype) || null; | 106 var pseudoElement = this._node.pseudoElements().get(entryPayload.pseudoT
ype) || null; |
| 107 var pseudoStyles = []; | 107 var pseudoStyles = []; |
| 108 var rules = entryPayload.matches || []; | 108 var rules = entryPayload.matches || []; |
| 109 for (var j = rules.length - 1; j >= 0; --j) { | 109 for (var j = rules.length - 1; j >= 0; --j) { |
| 110 var pseudoRule = new WebInspector.CSSStyleRule(cssModel, rules[j].rule
); | 110 var pseudoRule = new SDK.CSSStyleRule(cssModel, rules[j].rule); |
| 111 pseudoStyles.push(pseudoRule.style); | 111 pseudoStyles.push(pseudoRule.style); |
| 112 this._nodeForStyle.set(pseudoRule.style, pseudoElement); | 112 this._nodeForStyle.set(pseudoRule.style, pseudoElement); |
| 113 if (pseudoElement) | 113 if (pseudoElement) |
| 114 addMatchingSelectors.call(this, pseudoElement, pseudoRule, rules[j].
matchingSelectors); | 114 addMatchingSelectors.call(this, pseudoElement, pseudoRule, rules[j].
matchingSelectors); |
| 115 } | 115 } |
| 116 this._pseudoStyles.set(entryPayload.pseudoType, pseudoStyles); | 116 this._pseudoStyles.set(entryPayload.pseudoType, pseudoStyles); |
| 117 } | 117 } |
| 118 } | 118 } |
| 119 | 119 |
| 120 if (animationsPayload) | 120 if (animationsPayload) |
| 121 this._keyframes = animationsPayload.map(rule => new WebInspector.CSSKeyfra
mesRule(cssModel, rule)); | 121 this._keyframes = animationsPayload.map(rule => new SDK.CSSKeyframesRule(c
ssModel, rule)); |
| 122 | 122 |
| 123 this.resetActiveProperties(); | 123 this.resetActiveProperties(); |
| 124 | 124 |
| 125 /** | 125 /** |
| 126 * @param {!WebInspector.DOMNode} node | 126 * @param {!SDK.DOMNode} node |
| 127 * @param {!WebInspector.CSSStyleRule} rule | 127 * @param {!SDK.CSSStyleRule} rule |
| 128 * @param {!Array<number>} matchingSelectorIndices | 128 * @param {!Array<number>} matchingSelectorIndices |
| 129 * @this {WebInspector.CSSMatchedStyles} | 129 * @this {SDK.CSSMatchedStyles} |
| 130 */ | 130 */ |
| 131 function addMatchingSelectors(node, rule, matchingSelectorIndices) { | 131 function addMatchingSelectors(node, rule, matchingSelectorIndices) { |
| 132 for (var matchingSelectorIndex of matchingSelectorIndices) { | 132 for (var matchingSelectorIndex of matchingSelectorIndices) { |
| 133 var selector = rule.selectors[matchingSelectorIndex]; | 133 var selector = rule.selectors[matchingSelectorIndex]; |
| 134 this._setSelectorMatches(node, selector.text, true); | 134 this._setSelectorMatches(node, selector.text, true); |
| 135 } | 135 } |
| 136 } | 136 } |
| 137 } | 137 } |
| 138 | 138 |
| 139 /** | 139 /** |
| 140 * @return {!WebInspector.DOMNode} | 140 * @return {!SDK.DOMNode} |
| 141 */ | 141 */ |
| 142 node() { | 142 node() { |
| 143 return this._node; | 143 return this._node; |
| 144 } | 144 } |
| 145 | 145 |
| 146 /** | 146 /** |
| 147 * @return {!WebInspector.CSSModel} | 147 * @return {!SDK.CSSModel} |
| 148 */ | 148 */ |
| 149 cssModel() { | 149 cssModel() { |
| 150 return this._cssModel; | 150 return this._cssModel; |
| 151 } | 151 } |
| 152 | 152 |
| 153 /** | 153 /** |
| 154 * @param {!WebInspector.CSSStyleRule} rule | 154 * @param {!SDK.CSSStyleRule} rule |
| 155 * @return {boolean} | 155 * @return {boolean} |
| 156 */ | 156 */ |
| 157 hasMatchingSelectors(rule) { | 157 hasMatchingSelectors(rule) { |
| 158 var matchingSelectors = this.matchingSelectors(rule); | 158 var matchingSelectors = this.matchingSelectors(rule); |
| 159 return matchingSelectors.length > 0 && this.mediaMatches(rule.style); | 159 return matchingSelectors.length > 0 && this.mediaMatches(rule.style); |
| 160 } | 160 } |
| 161 | 161 |
| 162 /** | 162 /** |
| 163 * @param {!WebInspector.CSSStyleRule} rule | 163 * @param {!SDK.CSSStyleRule} rule |
| 164 * @return {!Array<number>} | 164 * @return {!Array<number>} |
| 165 */ | 165 */ |
| 166 matchingSelectors(rule) { | 166 matchingSelectors(rule) { |
| 167 var node = this.nodeForStyle(rule.style); | 167 var node = this.nodeForStyle(rule.style); |
| 168 if (!node) | 168 if (!node) |
| 169 return []; | 169 return []; |
| 170 var map = this._matchingSelectors.get(node.id); | 170 var map = this._matchingSelectors.get(node.id); |
| 171 if (!map) | 171 if (!map) |
| 172 return []; | 172 return []; |
| 173 var result = []; | 173 var result = []; |
| 174 for (var i = 0; i < rule.selectors.length; ++i) { | 174 for (var i = 0; i < rule.selectors.length; ++i) { |
| 175 if (map.get(rule.selectors[i].text)) | 175 if (map.get(rule.selectors[i].text)) |
| 176 result.push(i); | 176 result.push(i); |
| 177 } | 177 } |
| 178 return result; | 178 return result; |
| 179 } | 179 } |
| 180 | 180 |
| 181 /** | 181 /** |
| 182 * @param {!WebInspector.CSSStyleRule} rule | 182 * @param {!SDK.CSSStyleRule} rule |
| 183 * @return {!Promise} | 183 * @return {!Promise} |
| 184 */ | 184 */ |
| 185 recomputeMatchingSelectors(rule) { | 185 recomputeMatchingSelectors(rule) { |
| 186 var node = this.nodeForStyle(rule.style); | 186 var node = this.nodeForStyle(rule.style); |
| 187 if (!node) | 187 if (!node) |
| 188 return Promise.resolve(); | 188 return Promise.resolve(); |
| 189 var promises = []; | 189 var promises = []; |
| 190 for (var selector of rule.selectors) | 190 for (var selector of rule.selectors) |
| 191 promises.push(querySelector.call(this, node, selector.text)); | 191 promises.push(querySelector.call(this, node, selector.text)); |
| 192 return Promise.all(promises); | 192 return Promise.all(promises); |
| 193 | 193 |
| 194 /** | 194 /** |
| 195 * @param {!WebInspector.DOMNode} node | 195 * @param {!SDK.DOMNode} node |
| 196 * @param {string} selectorText | 196 * @param {string} selectorText |
| 197 * @return {!Promise} | 197 * @return {!Promise} |
| 198 * @this {WebInspector.CSSMatchedStyles} | 198 * @this {SDK.CSSMatchedStyles} |
| 199 */ | 199 */ |
| 200 function querySelector(node, selectorText) { | 200 function querySelector(node, selectorText) { |
| 201 var ownerDocument = node.ownerDocument || null; | 201 var ownerDocument = node.ownerDocument || null; |
| 202 // We assume that "matching" property does not ever change during the | 202 // We assume that "matching" property does not ever change during the |
| 203 // MatchedStyleResult's lifetime. | 203 // MatchedStyleResult's lifetime. |
| 204 var map = this._matchingSelectors.get(node.id); | 204 var map = this._matchingSelectors.get(node.id); |
| 205 if ((map && map.has(selectorText)) || !ownerDocument) | 205 if ((map && map.has(selectorText)) || !ownerDocument) |
| 206 return Promise.resolve(); | 206 return Promise.resolve(); |
| 207 | 207 |
| 208 var resolve; | 208 var resolve; |
| 209 var promise = new Promise(fulfill => resolve = fulfill); | 209 var promise = new Promise(fulfill => resolve = fulfill); |
| 210 this._node.domModel().querySelectorAll( | 210 this._node.domModel().querySelectorAll( |
| 211 ownerDocument.id, selectorText, onQueryComplete.bind(this, node, selec
torText, resolve)); | 211 ownerDocument.id, selectorText, onQueryComplete.bind(this, node, selec
torText, resolve)); |
| 212 return promise; | 212 return promise; |
| 213 } | 213 } |
| 214 | 214 |
| 215 /** | 215 /** |
| 216 * @param {!WebInspector.DOMNode} node | 216 * @param {!SDK.DOMNode} node |
| 217 * @param {string} selectorText | 217 * @param {string} selectorText |
| 218 * @param {function()} callback | 218 * @param {function()} callback |
| 219 * @param {!Array.<!Protocol.DOM.NodeId>=} matchingNodeIds | 219 * @param {!Array.<!Protocol.DOM.NodeId>=} matchingNodeIds |
| 220 * @this {WebInspector.CSSMatchedStyles} | 220 * @this {SDK.CSSMatchedStyles} |
| 221 */ | 221 */ |
| 222 function onQueryComplete(node, selectorText, callback, matchingNodeIds) { | 222 function onQueryComplete(node, selectorText, callback, matchingNodeIds) { |
| 223 if (matchingNodeIds) | 223 if (matchingNodeIds) |
| 224 this._setSelectorMatches(node, selectorText, matchingNodeIds.indexOf(nod
e.id) !== -1); | 224 this._setSelectorMatches(node, selectorText, matchingNodeIds.indexOf(nod
e.id) !== -1); |
| 225 callback(); | 225 callback(); |
| 226 } | 226 } |
| 227 } | 227 } |
| 228 | 228 |
| 229 /** | 229 /** |
| 230 * @param {!WebInspector.CSSStyleRule} rule | 230 * @param {!SDK.CSSStyleRule} rule |
| 231 * @param {!WebInspector.DOMNode} node | 231 * @param {!SDK.DOMNode} node |
| 232 * @return {!Promise} | 232 * @return {!Promise} |
| 233 */ | 233 */ |
| 234 addNewRule(rule, node) { | 234 addNewRule(rule, node) { |
| 235 this._nodeForStyle.set(rule.style, node); | 235 this._nodeForStyle.set(rule.style, node); |
| 236 return this.recomputeMatchingSelectors(rule); | 236 return this.recomputeMatchingSelectors(rule); |
| 237 } | 237 } |
| 238 | 238 |
| 239 /** | 239 /** |
| 240 * @param {!WebInspector.DOMNode} node | 240 * @param {!SDK.DOMNode} node |
| 241 * @param {string} selectorText | 241 * @param {string} selectorText |
| 242 * @param {boolean} value | 242 * @param {boolean} value |
| 243 */ | 243 */ |
| 244 _setSelectorMatches(node, selectorText, value) { | 244 _setSelectorMatches(node, selectorText, value) { |
| 245 var map = this._matchingSelectors.get(node.id); | 245 var map = this._matchingSelectors.get(node.id); |
| 246 if (!map) { | 246 if (!map) { |
| 247 map = new Map(); | 247 map = new Map(); |
| 248 this._matchingSelectors.set(node.id, map); | 248 this._matchingSelectors.set(node.id, map); |
| 249 } | 249 } |
| 250 map.set(selectorText, value); | 250 map.set(selectorText, value); |
| 251 } | 251 } |
| 252 | 252 |
| 253 /** | 253 /** |
| 254 * @param {!WebInspector.CSSStyleDeclaration} style | 254 * @param {!SDK.CSSStyleDeclaration} style |
| 255 * @return {boolean} | 255 * @return {boolean} |
| 256 */ | 256 */ |
| 257 mediaMatches(style) { | 257 mediaMatches(style) { |
| 258 var media = style.parentRule ? style.parentRule.media : []; | 258 var media = style.parentRule ? style.parentRule.media : []; |
| 259 for (var i = 0; media && i < media.length; ++i) { | 259 for (var i = 0; media && i < media.length; ++i) { |
| 260 if (!media[i].active()) | 260 if (!media[i].active()) |
| 261 return false; | 261 return false; |
| 262 } | 262 } |
| 263 return true; | 263 return true; |
| 264 } | 264 } |
| 265 | 265 |
| 266 /** | 266 /** |
| 267 * @return {!Array<!WebInspector.CSSStyleDeclaration>} | 267 * @return {!Array<!SDK.CSSStyleDeclaration>} |
| 268 */ | 268 */ |
| 269 nodeStyles() { | 269 nodeStyles() { |
| 270 return this._nodeStyles; | 270 return this._nodeStyles; |
| 271 } | 271 } |
| 272 | 272 |
| 273 /** | 273 /** |
| 274 * @return {!Array.<!WebInspector.CSSKeyframesRule>} | 274 * @return {!Array.<!SDK.CSSKeyframesRule>} |
| 275 */ | 275 */ |
| 276 keyframes() { | 276 keyframes() { |
| 277 return this._keyframes; | 277 return this._keyframes; |
| 278 } | 278 } |
| 279 | 279 |
| 280 /** | 280 /** |
| 281 * @return {!Map.<!Protocol.DOM.PseudoType, !Array<!WebInspector.CSSStyleDecla
ration>>} | 281 * @return {!Map.<!Protocol.DOM.PseudoType, !Array<!SDK.CSSStyleDeclaration>>} |
| 282 */ | 282 */ |
| 283 pseudoStyles() { | 283 pseudoStyles() { |
| 284 return this._pseudoStyles; | 284 return this._pseudoStyles; |
| 285 } | 285 } |
| 286 | 286 |
| 287 /** | 287 /** |
| 288 * @param {!WebInspector.CSSStyleDeclaration} style | 288 * @param {!SDK.CSSStyleDeclaration} style |
| 289 * @return {boolean} | 289 * @return {boolean} |
| 290 */ | 290 */ |
| 291 _containsInherited(style) { | 291 _containsInherited(style) { |
| 292 var properties = style.allProperties; | 292 var properties = style.allProperties; |
| 293 for (var i = 0; i < properties.length; ++i) { | 293 for (var i = 0; i < properties.length; ++i) { |
| 294 var property = properties[i]; | 294 var property = properties[i]; |
| 295 // Does this style contain non-overridden inherited property? | 295 // Does this style contain non-overridden inherited property? |
| 296 if (property.activeInStyle() && WebInspector.cssMetadata().isPropertyInher
ited(property.name)) | 296 if (property.activeInStyle() && SDK.cssMetadata().isPropertyInherited(prop
erty.name)) |
| 297 return true; | 297 return true; |
| 298 } | 298 } |
| 299 return false; | 299 return false; |
| 300 } | 300 } |
| 301 | 301 |
| 302 /** | 302 /** |
| 303 * @param {!WebInspector.CSSStyleDeclaration} style | 303 * @param {!SDK.CSSStyleDeclaration} style |
| 304 * @return {?WebInspector.DOMNode} | 304 * @return {?SDK.DOMNode} |
| 305 */ | 305 */ |
| 306 nodeForStyle(style) { | 306 nodeForStyle(style) { |
| 307 return this._nodeForStyle.get(style) || null; | 307 return this._nodeForStyle.get(style) || null; |
| 308 } | 308 } |
| 309 | 309 |
| 310 /** | 310 /** |
| 311 * @param {!WebInspector.CSSStyleDeclaration} style | 311 * @param {!SDK.CSSStyleDeclaration} style |
| 312 * @return {boolean} | 312 * @return {boolean} |
| 313 */ | 313 */ |
| 314 isInherited(style) { | 314 isInherited(style) { |
| 315 return this._inheritedStyles.has(style); | 315 return this._inheritedStyles.has(style); |
| 316 } | 316 } |
| 317 | 317 |
| 318 /** | 318 /** |
| 319 * @param {!WebInspector.CSSProperty} property | 319 * @param {!SDK.CSSProperty} property |
| 320 * @return {?WebInspector.CSSMatchedStyles.PropertyState} | 320 * @return {?SDK.CSSMatchedStyles.PropertyState} |
| 321 */ | 321 */ |
| 322 propertyState(property) { | 322 propertyState(property) { |
| 323 if (this._propertiesState.size === 0) { | 323 if (this._propertiesState.size === 0) { |
| 324 this._computeActiveProperties(this._nodeStyles, this._propertiesState); | 324 this._computeActiveProperties(this._nodeStyles, this._propertiesState); |
| 325 for (var pseudoElementStyles of this._pseudoStyles.valuesArray()) | 325 for (var pseudoElementStyles of this._pseudoStyles.valuesArray()) |
| 326 this._computeActiveProperties(pseudoElementStyles, this._propertiesState
); | 326 this._computeActiveProperties(pseudoElementStyles, this._propertiesState
); |
| 327 } | 327 } |
| 328 return this._propertiesState.get(property) || null; | 328 return this._propertiesState.get(property) || null; |
| 329 } | 329 } |
| 330 | 330 |
| 331 resetActiveProperties() { | 331 resetActiveProperties() { |
| 332 /** @type {!Map<!WebInspector.CSSProperty, !WebInspector.CSSMatchedStyles.Pr
opertyState>} */ | 332 /** @type {!Map<!SDK.CSSProperty, !SDK.CSSMatchedStyles.PropertyState>} */ |
| 333 this._propertiesState = new Map(); | 333 this._propertiesState = new Map(); |
| 334 } | 334 } |
| 335 | 335 |
| 336 /** | 336 /** |
| 337 * @param {!Array<!WebInspector.CSSStyleDeclaration>} styles | 337 * @param {!Array<!SDK.CSSStyleDeclaration>} styles |
| 338 * @param {!Map<!WebInspector.CSSProperty, !WebInspector.CSSMatchedStyles.Prop
ertyState>} result | 338 * @param {!Map<!SDK.CSSProperty, !SDK.CSSMatchedStyles.PropertyState>} result |
| 339 */ | 339 */ |
| 340 _computeActiveProperties(styles, result) { | 340 _computeActiveProperties(styles, result) { |
| 341 /** @type {!Set.<string>} */ | 341 /** @type {!Set.<string>} */ |
| 342 var foundImportantProperties = new Set(); | 342 var foundImportantProperties = new Set(); |
| 343 /** @type {!Map.<string, !Map<string, !WebInspector.CSSProperty>>} */ | 343 /** @type {!Map.<string, !Map<string, !SDK.CSSProperty>>} */ |
| 344 var propertyToEffectiveRule = new Map(); | 344 var propertyToEffectiveRule = new Map(); |
| 345 /** @type {!Map.<string, !WebInspector.DOMNode>} */ | 345 /** @type {!Map.<string, !SDK.DOMNode>} */ |
| 346 var inheritedPropertyToNode = new Map(); | 346 var inheritedPropertyToNode = new Map(); |
| 347 /** @type {!Set<string>} */ | 347 /** @type {!Set<string>} */ |
| 348 var allUsedProperties = new Set(); | 348 var allUsedProperties = new Set(); |
| 349 for (var i = 0; i < styles.length; ++i) { | 349 for (var i = 0; i < styles.length; ++i) { |
| 350 var style = styles[i]; | 350 var style = styles[i]; |
| 351 var rule = style.parentRule; | 351 var rule = style.parentRule; |
| 352 // Compute cascade for CSSStyleRules only. | 352 // Compute cascade for CSSStyleRules only. |
| 353 if (rule && !(rule instanceof WebInspector.CSSStyleRule)) | 353 if (rule && !(rule instanceof SDK.CSSStyleRule)) |
| 354 continue; | 354 continue; |
| 355 if (rule && !this.hasMatchingSelectors(rule)) | 355 if (rule && !this.hasMatchingSelectors(rule)) |
| 356 continue; | 356 continue; |
| 357 | 357 |
| 358 /** @type {!Map<string, !WebInspector.CSSProperty>} */ | 358 /** @type {!Map<string, !SDK.CSSProperty>} */ |
| 359 var styleActiveProperties = new Map(); | 359 var styleActiveProperties = new Map(); |
| 360 var allProperties = style.allProperties; | 360 var allProperties = style.allProperties; |
| 361 for (var j = 0; j < allProperties.length; ++j) { | 361 for (var j = 0; j < allProperties.length; ++j) { |
| 362 var property = allProperties[j]; | 362 var property = allProperties[j]; |
| 363 | 363 |
| 364 // Do not pick non-inherited properties from inherited styles. | 364 // Do not pick non-inherited properties from inherited styles. |
| 365 var inherited = this.isInherited(style); | 365 var inherited = this.isInherited(style); |
| 366 if (inherited && !WebInspector.cssMetadata().isPropertyInherited(propert
y.name)) | 366 if (inherited && !SDK.cssMetadata().isPropertyInherited(property.name)) |
| 367 continue; | 367 continue; |
| 368 | 368 |
| 369 if (!property.activeInStyle()) { | 369 if (!property.activeInStyle()) { |
| 370 result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overl
oaded); | 370 result.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded); |
| 371 continue; | 371 continue; |
| 372 } | 372 } |
| 373 | 373 |
| 374 var canonicalName = WebInspector.cssMetadata().canonicalPropertyName(pro
perty.name); | 374 var canonicalName = SDK.cssMetadata().canonicalPropertyName(property.nam
e); |
| 375 if (foundImportantProperties.has(canonicalName)) { | 375 if (foundImportantProperties.has(canonicalName)) { |
| 376 result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overl
oaded); | 376 result.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded); |
| 377 continue; | 377 continue; |
| 378 } | 378 } |
| 379 | 379 |
| 380 if (!property.important && allUsedProperties.has(canonicalName)) { | 380 if (!property.important && allUsedProperties.has(canonicalName)) { |
| 381 result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overl
oaded); | 381 result.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded); |
| 382 continue; | 382 continue; |
| 383 } | 383 } |
| 384 | 384 |
| 385 var isKnownProperty = propertyToEffectiveRule.has(canonicalName); | 385 var isKnownProperty = propertyToEffectiveRule.has(canonicalName); |
| 386 var inheritedFromNode = inherited ? this.nodeForStyle(style) : null; | 386 var inheritedFromNode = inherited ? this.nodeForStyle(style) : null; |
| 387 if (!isKnownProperty && inheritedFromNode && !inheritedPropertyToNode.ha
s(canonicalName)) | 387 if (!isKnownProperty && inheritedFromNode && !inheritedPropertyToNode.ha
s(canonicalName)) |
| 388 inheritedPropertyToNode.set(canonicalName, inheritedFromNode); | 388 inheritedPropertyToNode.set(canonicalName, inheritedFromNode); |
| 389 | 389 |
| 390 if (property.important) { | 390 if (property.important) { |
| 391 if (inherited && isKnownProperty && inheritedFromNode !== inheritedPro
pertyToNode.get(canonicalName)) { | 391 if (inherited && isKnownProperty && inheritedFromNode !== inheritedPro
pertyToNode.get(canonicalName)) { |
| 392 result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Ove
rloaded); | 392 result.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded); |
| 393 continue; | 393 continue; |
| 394 } | 394 } |
| 395 | 395 |
| 396 foundImportantProperties.add(canonicalName); | 396 foundImportantProperties.add(canonicalName); |
| 397 if (isKnownProperty) { | 397 if (isKnownProperty) { |
| 398 var overloaded = /** @type {!WebInspector.CSSProperty} */ ( | 398 var overloaded = /** @type {!SDK.CSSProperty} */ ( |
| 399 propertyToEffectiveRule.get(canonicalName).get(canonicalName)); | 399 propertyToEffectiveRule.get(canonicalName).get(canonicalName)); |
| 400 result.set(overloaded, WebInspector.CSSMatchedStyles.PropertyState.O
verloaded); | 400 result.set(overloaded, SDK.CSSMatchedStyles.PropertyState.Overloaded
); |
| 401 propertyToEffectiveRule.get(canonicalName).delete(canonicalName); | 401 propertyToEffectiveRule.get(canonicalName).delete(canonicalName); |
| 402 } | 402 } |
| 403 } | 403 } |
| 404 | 404 |
| 405 styleActiveProperties.set(canonicalName, property); | 405 styleActiveProperties.set(canonicalName, property); |
| 406 allUsedProperties.add(canonicalName); | 406 allUsedProperties.add(canonicalName); |
| 407 propertyToEffectiveRule.set(canonicalName, styleActiveProperties); | 407 propertyToEffectiveRule.set(canonicalName, styleActiveProperties); |
| 408 result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Active)
; | 408 result.set(property, SDK.CSSMatchedStyles.PropertyState.Active); |
| 409 } | 409 } |
| 410 | 410 |
| 411 // If every longhand of the shorthand is not active, then the shorthand is
not active too. | 411 // If every longhand of the shorthand is not active, then the shorthand is
not active too. |
| 412 for (var property of style.leadingProperties()) { | 412 for (var property of style.leadingProperties()) { |
| 413 var canonicalName = WebInspector.cssMetadata().canonicalPropertyName(pro
perty.name); | 413 var canonicalName = SDK.cssMetadata().canonicalPropertyName(property.nam
e); |
| 414 if (!styleActiveProperties.has(canonicalName)) | 414 if (!styleActiveProperties.has(canonicalName)) |
| 415 continue; | 415 continue; |
| 416 var longhands = style.longhandProperties(property.name); | 416 var longhands = style.longhandProperties(property.name); |
| 417 if (!longhands.length) | 417 if (!longhands.length) |
| 418 continue; | 418 continue; |
| 419 var notUsed = true; | 419 var notUsed = true; |
| 420 for (var longhand of longhands) { | 420 for (var longhand of longhands) { |
| 421 var longhandCanonicalName = WebInspector.cssMetadata().canonicalProper
tyName(longhand.name); | 421 var longhandCanonicalName = SDK.cssMetadata().canonicalPropertyName(lo
nghand.name); |
| 422 notUsed = notUsed && !styleActiveProperties.has(longhandCanonicalName)
; | 422 notUsed = notUsed && !styleActiveProperties.has(longhandCanonicalName)
; |
| 423 } | 423 } |
| 424 if (!notUsed) | 424 if (!notUsed) |
| 425 continue; | 425 continue; |
| 426 styleActiveProperties.delete(canonicalName); | 426 styleActiveProperties.delete(canonicalName); |
| 427 allUsedProperties.delete(canonicalName); | 427 allUsedProperties.delete(canonicalName); |
| 428 result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloa
ded); | 428 result.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded); |
| 429 } | 429 } |
| 430 } | 430 } |
| 431 } | 431 } |
| 432 }; | 432 }; |
| 433 | 433 |
| 434 /** @enum {string} */ | 434 /** @enum {string} */ |
| 435 WebInspector.CSSMatchedStyles.PropertyState = { | 435 SDK.CSSMatchedStyles.PropertyState = { |
| 436 Active: 'Active', | 436 Active: 'Active', |
| 437 Overloaded: 'Overloaded' | 437 Overloaded: 'Overloaded' |
| 438 }; | 438 }; |
| OLD | NEW |