Index: third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js |
index 4d73253eb1738d38f2174fe9bd3f5f08490ae3dc..67690771db4e607bb19502d08f2aaa849bf79ecd 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js |
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js |
@@ -1,20 +1,29 @@ |
// Copyright 2016 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
- |
/** |
- * @constructor |
- * @param {!WebInspector.CSSModel} cssModel |
- * @param {!WebInspector.DOMNode} node |
- * @param {?CSSAgent.CSSStyle} inlinePayload |
- * @param {?CSSAgent.CSSStyle} attributesPayload |
- * @param {!Array.<!CSSAgent.RuleMatch>} matchedPayload |
- * @param {!Array.<!CSSAgent.PseudoElementMatches>} pseudoPayload |
- * @param {!Array.<!CSSAgent.InheritedStyleEntry>} inheritedPayload |
- * @param {!Array.<!CSSAgent.CSSKeyframesRule>} animationsPayload |
+ * @unrestricted |
*/ |
-WebInspector.CSSMatchedStyles = function(cssModel, node, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload, animationsPayload) |
-{ |
+WebInspector.CSSMatchedStyles = class { |
+ /** |
+ * @param {!WebInspector.CSSModel} cssModel |
+ * @param {!WebInspector.DOMNode} node |
+ * @param {?CSSAgent.CSSStyle} inlinePayload |
+ * @param {?CSSAgent.CSSStyle} attributesPayload |
+ * @param {!Array.<!CSSAgent.RuleMatch>} matchedPayload |
+ * @param {!Array.<!CSSAgent.PseudoElementMatches>} pseudoPayload |
+ * @param {!Array.<!CSSAgent.InheritedStyleEntry>} inheritedPayload |
+ * @param {!Array.<!CSSAgent.CSSKeyframesRule>} animationsPayload |
+ */ |
+ constructor( |
+ cssModel, |
+ node, |
+ inlinePayload, |
+ attributesPayload, |
+ matchedPayload, |
+ pseudoPayload, |
+ inheritedPayload, |
+ animationsPayload) { |
this._cssModel = cssModel; |
this._node = node; |
this._nodeStyles = []; |
@@ -27,85 +36,89 @@ WebInspector.CSSMatchedStyles = function(cssModel, node, inlinePayload, attribut |
/** |
* @this {WebInspector.CSSMatchedStyles} |
*/ |
- function addAttributesStyle() |
- { |
- if (!attributesPayload) |
- return; |
- var style = new WebInspector.CSSStyleDeclaration(cssModel, null, attributesPayload, WebInspector.CSSStyleDeclaration.Type.Attributes); |
- this._nodeForStyle.set(style, this._node); |
- this._nodeStyles.push(style); |
+ function addAttributesStyle() { |
+ if (!attributesPayload) |
+ return; |
+ var style = new WebInspector.CSSStyleDeclaration( |
+ cssModel, null, attributesPayload, WebInspector.CSSStyleDeclaration.Type.Attributes); |
+ this._nodeForStyle.set(style, this._node); |
+ this._nodeStyles.push(style); |
} |
// Inline style has the greatest specificity. |
if (inlinePayload && this._node.nodeType() === Node.ELEMENT_NODE) { |
- var style = new WebInspector.CSSStyleDeclaration(cssModel, null, inlinePayload, WebInspector.CSSStyleDeclaration.Type.Inline); |
- this._nodeForStyle.set(style, this._node); |
- this._nodeStyles.push(style); |
+ var style = new WebInspector.CSSStyleDeclaration( |
+ cssModel, null, inlinePayload, WebInspector.CSSStyleDeclaration.Type.Inline); |
+ this._nodeForStyle.set(style, this._node); |
+ this._nodeStyles.push(style); |
} |
// Add rules in reverse order to match the cascade order. |
var addedAttributesStyle; |
for (var i = matchedPayload.length - 1; i >= 0; --i) { |
- var rule = new WebInspector.CSSStyleRule(cssModel, matchedPayload[i].rule); |
- if ((rule.isInjected() || rule.isUserAgent()) && !addedAttributesStyle) { |
- // Show element's Style Attributes after all author rules. |
- addedAttributesStyle = true; |
- addAttributesStyle.call(this); |
- } |
- this._nodeForStyle.set(rule.style, this._node); |
- this._nodeStyles.push(rule.style); |
- addMatchingSelectors.call(this, this._node, rule, matchedPayload[i].matchingSelectors); |
+ var rule = new WebInspector.CSSStyleRule(cssModel, matchedPayload[i].rule); |
+ if ((rule.isInjected() || rule.isUserAgent()) && !addedAttributesStyle) { |
+ // Show element's Style Attributes after all author rules. |
+ addedAttributesStyle = true; |
+ addAttributesStyle.call(this); |
+ } |
+ this._nodeForStyle.set(rule.style, this._node); |
+ this._nodeStyles.push(rule.style); |
+ addMatchingSelectors.call(this, this._node, rule, matchedPayload[i].matchingSelectors); |
} |
if (!addedAttributesStyle) |
- addAttributesStyle.call(this); |
+ addAttributesStyle.call(this); |
// Walk the node structure and identify styles with inherited properties. |
var parentNode = this._node.parentNode; |
for (var i = 0; parentNode && inheritedPayload && i < inheritedPayload.length; ++i) { |
- var entryPayload = inheritedPayload[i]; |
- var inheritedInlineStyle = entryPayload.inlineStyle ? new WebInspector.CSSStyleDeclaration(cssModel, null, entryPayload.inlineStyle, WebInspector.CSSStyleDeclaration.Type.Inline) : null; |
- if (inheritedInlineStyle && this._containsInherited(inheritedInlineStyle)) { |
- this._nodeForStyle.set(inheritedInlineStyle, parentNode); |
- this._nodeStyles.push(inheritedInlineStyle); |
- this._inheritedStyles.add(inheritedInlineStyle); |
- } |
- |
- var inheritedMatchedCSSRules = entryPayload.matchedCSSRules || []; |
- for (var j = inheritedMatchedCSSRules.length - 1; j >= 0; --j) { |
- var inheritedRule = new WebInspector.CSSStyleRule(cssModel, inheritedMatchedCSSRules[j].rule); |
- addMatchingSelectors.call(this, parentNode, inheritedRule, inheritedMatchedCSSRules[j].matchingSelectors); |
- if (!this._containsInherited(inheritedRule.style)) |
- continue; |
- this._nodeForStyle.set(inheritedRule.style, parentNode); |
- this._nodeStyles.push(inheritedRule.style); |
- this._inheritedStyles.add(inheritedRule.style); |
- } |
- parentNode = parentNode.parentNode; |
+ var entryPayload = inheritedPayload[i]; |
+ var inheritedInlineStyle = entryPayload.inlineStyle ? |
+ new WebInspector.CSSStyleDeclaration( |
+ cssModel, null, entryPayload.inlineStyle, WebInspector.CSSStyleDeclaration.Type.Inline) : |
+ null; |
+ if (inheritedInlineStyle && this._containsInherited(inheritedInlineStyle)) { |
+ this._nodeForStyle.set(inheritedInlineStyle, parentNode); |
+ this._nodeStyles.push(inheritedInlineStyle); |
+ this._inheritedStyles.add(inheritedInlineStyle); |
+ } |
+ |
+ var inheritedMatchedCSSRules = entryPayload.matchedCSSRules || []; |
+ for (var j = inheritedMatchedCSSRules.length - 1; j >= 0; --j) { |
+ var inheritedRule = new WebInspector.CSSStyleRule(cssModel, inheritedMatchedCSSRules[j].rule); |
+ addMatchingSelectors.call(this, parentNode, inheritedRule, inheritedMatchedCSSRules[j].matchingSelectors); |
+ if (!this._containsInherited(inheritedRule.style)) |
+ continue; |
+ this._nodeForStyle.set(inheritedRule.style, parentNode); |
+ this._nodeStyles.push(inheritedRule.style); |
+ this._inheritedStyles.add(inheritedRule.style); |
+ } |
+ parentNode = parentNode.parentNode; |
} |
// Set up pseudo styles map. |
this._pseudoStyles = new Map(); |
if (pseudoPayload) { |
- for (var i = 0; i < pseudoPayload.length; ++i) { |
- var entryPayload = pseudoPayload[i]; |
- // PseudoElement nodes are not created unless "content" css property is set. |
- var pseudoElement = this._node.pseudoElements().get(entryPayload.pseudoType) || null; |
- var pseudoStyles = []; |
- var rules = entryPayload.matches || []; |
- for (var j = rules.length - 1; j >= 0; --j) { |
- var pseudoRule = new WebInspector.CSSStyleRule(cssModel, rules[j].rule); |
- pseudoStyles.push(pseudoRule.style); |
- this._nodeForStyle.set(pseudoRule.style, pseudoElement); |
- if (pseudoElement) |
- addMatchingSelectors.call(this, pseudoElement, pseudoRule, rules[j].matchingSelectors); |
- } |
- this._pseudoStyles.set(entryPayload.pseudoType, pseudoStyles); |
+ for (var i = 0; i < pseudoPayload.length; ++i) { |
+ var entryPayload = pseudoPayload[i]; |
+ // PseudoElement nodes are not created unless "content" css property is set. |
+ var pseudoElement = this._node.pseudoElements().get(entryPayload.pseudoType) || null; |
+ var pseudoStyles = []; |
+ var rules = entryPayload.matches || []; |
+ for (var j = rules.length - 1; j >= 0; --j) { |
+ var pseudoRule = new WebInspector.CSSStyleRule(cssModel, rules[j].rule); |
+ pseudoStyles.push(pseudoRule.style); |
+ this._nodeForStyle.set(pseudoRule.style, pseudoElement); |
+ if (pseudoElement) |
+ addMatchingSelectors.call(this, pseudoElement, pseudoRule, rules[j].matchingSelectors); |
} |
+ this._pseudoStyles.set(entryPayload.pseudoType, pseudoStyles); |
+ } |
} |
if (animationsPayload) |
- this._keyframes = animationsPayload.map(rule => new WebInspector.CSSKeyframesRule(cssModel, rule)); |
+ this._keyframes = animationsPayload.map(rule => new WebInspector.CSSKeyframesRule(cssModel, rule)); |
this.resetActiveProperties(); |
@@ -115,330 +128,311 @@ WebInspector.CSSMatchedStyles = function(cssModel, node, inlinePayload, attribut |
* @param {!Array<number>} matchingSelectorIndices |
* @this {WebInspector.CSSMatchedStyles} |
*/ |
- function addMatchingSelectors(node, rule, matchingSelectorIndices) |
- { |
- for (var matchingSelectorIndex of matchingSelectorIndices) { |
- var selector = rule.selectors[matchingSelectorIndex]; |
- this._setSelectorMatches(node, selector.text, true); |
- } |
+ function addMatchingSelectors(node, rule, matchingSelectorIndices) { |
+ for (var matchingSelectorIndex of matchingSelectorIndices) { |
+ var selector = rule.selectors[matchingSelectorIndex]; |
+ this._setSelectorMatches(node, selector.text, true); |
+ } |
} |
-}; |
- |
-WebInspector.CSSMatchedStyles.prototype = { |
- /** |
- * @return {!WebInspector.DOMNode} |
- */ |
- node: function() |
- { |
- return this._node; |
- }, |
- |
- /** |
- * @return {!WebInspector.CSSModel} |
- */ |
- cssModel: function() |
- { |
- return this._cssModel; |
- }, |
- |
- /** |
- * @param {!WebInspector.CSSStyleRule} rule |
- * @return {boolean} |
- */ |
- hasMatchingSelectors: function(rule) |
- { |
- var matchingSelectors = this.matchingSelectors(rule); |
- return matchingSelectors.length > 0 && this.mediaMatches(rule.style); |
- }, |
- |
- /** |
- * @param {!WebInspector.CSSStyleRule} rule |
- * @return {!Array<number>} |
- */ |
- matchingSelectors: function(rule) |
- { |
- var node = this.nodeForStyle(rule.style); |
- if (!node) |
- return []; |
- var map = this._matchingSelectors.get(node.id); |
- if (!map) |
- return []; |
- var result = []; |
- for (var i = 0; i < rule.selectors.length; ++i) { |
- if (map.get(rule.selectors[i].text)) |
- result.push(i); |
- } |
- return result; |
- }, |
- |
- /** |
- * @param {!WebInspector.CSSStyleRule} rule |
- * @return {!Promise} |
- */ |
- recomputeMatchingSelectors: function(rule) |
- { |
- var node = this.nodeForStyle(rule.style); |
- if (!node) |
- return Promise.resolve(); |
- var promises = []; |
- for (var selector of rule.selectors) |
- promises.push(querySelector.call(this, node, selector.text)); |
- return Promise.all(promises); |
- |
- /** |
- * @param {!WebInspector.DOMNode} node |
- * @param {string} selectorText |
- * @return {!Promise} |
- * @this {WebInspector.CSSMatchedStyles} |
- */ |
- function querySelector(node, selectorText) |
- { |
- var ownerDocument = node.ownerDocument || null; |
- // We assume that "matching" property does not ever change during the |
- // MatchedStyleResult's lifetime. |
- var map = this._matchingSelectors.get(node.id); |
- if ((map && map.has(selectorText)) || !ownerDocument) |
- return Promise.resolve(); |
- |
- var resolve; |
- var promise = new Promise(fulfill => resolve = fulfill); |
- this._node.domModel().querySelectorAll(ownerDocument.id, selectorText, onQueryComplete.bind(this, node, selectorText, resolve)); |
- return promise; |
- } |
- |
- /** |
- * @param {!WebInspector.DOMNode} node |
- * @param {string} selectorText |
- * @param {function()} callback |
- * @param {!Array.<!DOMAgent.NodeId>=} matchingNodeIds |
- * @this {WebInspector.CSSMatchedStyles} |
- */ |
- function onQueryComplete(node, selectorText, callback, matchingNodeIds) |
- { |
- if (matchingNodeIds) |
- this._setSelectorMatches(node, selectorText, matchingNodeIds.indexOf(node.id) !== -1); |
- callback(); |
- } |
- }, |
+ } |
+ |
+ /** |
+ * @return {!WebInspector.DOMNode} |
+ */ |
+ node() { |
+ return this._node; |
+ } |
+ |
+ /** |
+ * @return {!WebInspector.CSSModel} |
+ */ |
+ cssModel() { |
+ return this._cssModel; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleRule} rule |
+ * @return {boolean} |
+ */ |
+ hasMatchingSelectors(rule) { |
+ var matchingSelectors = this.matchingSelectors(rule); |
+ return matchingSelectors.length > 0 && this.mediaMatches(rule.style); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleRule} rule |
+ * @return {!Array<number>} |
+ */ |
+ matchingSelectors(rule) { |
+ var node = this.nodeForStyle(rule.style); |
+ if (!node) |
+ return []; |
+ var map = this._matchingSelectors.get(node.id); |
+ if (!map) |
+ return []; |
+ var result = []; |
+ for (var i = 0; i < rule.selectors.length; ++i) { |
+ if (map.get(rule.selectors[i].text)) |
+ result.push(i); |
+ } |
+ return result; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleRule} rule |
+ * @return {!Promise} |
+ */ |
+ recomputeMatchingSelectors(rule) { |
+ var node = this.nodeForStyle(rule.style); |
+ if (!node) |
+ return Promise.resolve(); |
+ var promises = []; |
+ for (var selector of rule.selectors) |
+ promises.push(querySelector.call(this, node, selector.text)); |
+ return Promise.all(promises); |
/** |
- * @param {!WebInspector.CSSStyleRule} rule |
* @param {!WebInspector.DOMNode} node |
+ * @param {string} selectorText |
* @return {!Promise} |
+ * @this {WebInspector.CSSMatchedStyles} |
*/ |
- addNewRule: function(rule, node) |
- { |
- this._nodeForStyle.set(rule.style, node); |
- return this.recomputeMatchingSelectors(rule); |
- }, |
+ function querySelector(node, selectorText) { |
+ var ownerDocument = node.ownerDocument || null; |
+ // We assume that "matching" property does not ever change during the |
+ // MatchedStyleResult's lifetime. |
+ var map = this._matchingSelectors.get(node.id); |
+ if ((map && map.has(selectorText)) || !ownerDocument) |
+ return Promise.resolve(); |
+ |
+ var resolve; |
+ var promise = new Promise(fulfill => resolve = fulfill); |
+ this._node.domModel().querySelectorAll( |
+ ownerDocument.id, selectorText, onQueryComplete.bind(this, node, selectorText, resolve)); |
+ return promise; |
+ } |
/** |
* @param {!WebInspector.DOMNode} node |
* @param {string} selectorText |
- * @param {boolean} value |
+ * @param {function()} callback |
+ * @param {!Array.<!DOMAgent.NodeId>=} matchingNodeIds |
+ * @this {WebInspector.CSSMatchedStyles} |
*/ |
- _setSelectorMatches: function(node, selectorText, value) |
- { |
- var map = this._matchingSelectors.get(node.id); |
- if (!map) { |
- map = new Map(); |
- this._matchingSelectors.set(node.id, map); |
+ function onQueryComplete(node, selectorText, callback, matchingNodeIds) { |
+ if (matchingNodeIds) |
+ this._setSelectorMatches(node, selectorText, matchingNodeIds.indexOf(node.id) !== -1); |
+ callback(); |
+ } |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleRule} rule |
+ * @param {!WebInspector.DOMNode} node |
+ * @return {!Promise} |
+ */ |
+ addNewRule(rule, node) { |
+ this._nodeForStyle.set(rule.style, node); |
+ return this.recomputeMatchingSelectors(rule); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DOMNode} node |
+ * @param {string} selectorText |
+ * @param {boolean} value |
+ */ |
+ _setSelectorMatches(node, selectorText, value) { |
+ var map = this._matchingSelectors.get(node.id); |
+ if (!map) { |
+ map = new Map(); |
+ this._matchingSelectors.set(node.id, map); |
+ } |
+ map.set(selectorText, value); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleDeclaration} style |
+ * @return {boolean} |
+ */ |
+ mediaMatches(style) { |
+ var media = style.parentRule ? style.parentRule.media : []; |
+ for (var i = 0; media && i < media.length; ++i) { |
+ if (!media[i].active()) |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ /** |
+ * @return {!Array<!WebInspector.CSSStyleDeclaration>} |
+ */ |
+ nodeStyles() { |
+ return this._nodeStyles; |
+ } |
+ |
+ /** |
+ * @return {!Array.<!WebInspector.CSSKeyframesRule>} |
+ */ |
+ keyframes() { |
+ return this._keyframes; |
+ } |
+ |
+ /** |
+ * @return {!Map.<!DOMAgent.PseudoType, !Array<!WebInspector.CSSStyleDeclaration>>} |
+ */ |
+ pseudoStyles() { |
+ return this._pseudoStyles; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleDeclaration} style |
+ * @return {boolean} |
+ */ |
+ _containsInherited(style) { |
+ var properties = style.allProperties; |
+ for (var i = 0; i < properties.length; ++i) { |
+ var property = properties[i]; |
+ // Does this style contain non-overridden inherited property? |
+ if (property.activeInStyle() && WebInspector.cssMetadata().isPropertyInherited(property.name)) |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleDeclaration} style |
+ * @return {?WebInspector.DOMNode} |
+ */ |
+ nodeForStyle(style) { |
+ return this._nodeForStyle.get(style) || null; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleDeclaration} style |
+ * @return {boolean} |
+ */ |
+ isInherited(style) { |
+ return this._inheritedStyles.has(style); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.CSSProperty} property |
+ * @return {?WebInspector.CSSMatchedStyles.PropertyState} |
+ */ |
+ propertyState(property) { |
+ if (this._propertiesState.size === 0) { |
+ this._computeActiveProperties(this._nodeStyles, this._propertiesState); |
+ for (var pseudoElementStyles of this._pseudoStyles.valuesArray()) |
+ this._computeActiveProperties(pseudoElementStyles, this._propertiesState); |
+ } |
+ return this._propertiesState.get(property) || null; |
+ } |
+ |
+ resetActiveProperties() { |
+ /** @type {!Map<!WebInspector.CSSProperty, !WebInspector.CSSMatchedStyles.PropertyState>} */ |
+ this._propertiesState = new Map(); |
+ } |
+ |
+ /** |
+ * @param {!Array<!WebInspector.CSSStyleDeclaration>} styles |
+ * @param {!Map<!WebInspector.CSSProperty, !WebInspector.CSSMatchedStyles.PropertyState>} result |
+ */ |
+ _computeActiveProperties(styles, result) { |
+ /** @type {!Set.<string>} */ |
+ var foundImportantProperties = new Set(); |
+ /** @type {!Map.<string, !Map<string, !WebInspector.CSSProperty>>} */ |
+ var propertyToEffectiveRule = new Map(); |
+ /** @type {!Map.<string, !WebInspector.DOMNode>} */ |
+ var inheritedPropertyToNode = new Map(); |
+ /** @type {!Set<string>} */ |
+ var allUsedProperties = new Set(); |
+ for (var i = 0; i < styles.length; ++i) { |
+ var style = styles[i]; |
+ var rule = style.parentRule; |
+ // Compute cascade for CSSStyleRules only. |
+ if (rule && !(rule instanceof WebInspector.CSSStyleRule)) |
+ continue; |
+ if (rule && !this.hasMatchingSelectors(rule)) |
+ continue; |
+ |
+ /** @type {!Map<string, !WebInspector.CSSProperty>} */ |
+ var styleActiveProperties = new Map(); |
+ var allProperties = style.allProperties; |
+ for (var j = 0; j < allProperties.length; ++j) { |
+ var property = allProperties[j]; |
+ |
+ // Do not pick non-inherited properties from inherited styles. |
+ var inherited = this.isInherited(style); |
+ if (inherited && !WebInspector.cssMetadata().isPropertyInherited(property.name)) |
+ continue; |
+ |
+ if (!property.activeInStyle()) { |
+ result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
+ continue; |
} |
- map.set(selectorText, value); |
- }, |
- /** |
- * @param {!WebInspector.CSSStyleDeclaration} style |
- * @return {boolean} |
- */ |
- mediaMatches: function(style) |
- { |
- var media = style.parentRule ? style.parentRule.media : []; |
- for (var i = 0; media && i < media.length; ++i) { |
- if (!media[i].active()) |
- return false; |
+ var canonicalName = WebInspector.cssMetadata().canonicalPropertyName(property.name); |
+ if (foundImportantProperties.has(canonicalName)) { |
+ result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
+ continue; |
} |
- return true; |
- }, |
- |
- /** |
- * @return {!Array<!WebInspector.CSSStyleDeclaration>} |
- */ |
- nodeStyles: function() |
- { |
- return this._nodeStyles; |
- }, |
- |
- /** |
- * @return {!Array.<!WebInspector.CSSKeyframesRule>} |
- */ |
- keyframes: function() |
- { |
- return this._keyframes; |
- }, |
- /** |
- * @return {!Map.<!DOMAgent.PseudoType, !Array<!WebInspector.CSSStyleDeclaration>>} |
- */ |
- pseudoStyles: function() |
- { |
- return this._pseudoStyles; |
- }, |
- |
- /** |
- * @param {!WebInspector.CSSStyleDeclaration} style |
- * @return {boolean} |
- */ |
- _containsInherited: function(style) |
- { |
- var properties = style.allProperties; |
- for (var i = 0; i < properties.length; ++i) { |
- var property = properties[i]; |
- // Does this style contain non-overridden inherited property? |
- if (property.activeInStyle() && WebInspector.cssMetadata().isPropertyInherited(property.name)) |
- return true; |
+ if (!property.important && allUsedProperties.has(canonicalName)) { |
+ result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
+ continue; |
} |
- return false; |
- }, |
- |
- /** |
- * @param {!WebInspector.CSSStyleDeclaration} style |
- * @return {?WebInspector.DOMNode} |
- */ |
- nodeForStyle: function(style) |
- { |
- return this._nodeForStyle.get(style) || null; |
- }, |
- /** |
- * @param {!WebInspector.CSSStyleDeclaration} style |
- * @return {boolean} |
- */ |
- isInherited: function(style) |
- { |
- return this._inheritedStyles.has(style); |
- }, |
- |
- /** |
- * @param {!WebInspector.CSSProperty} property |
- * @return {?WebInspector.CSSMatchedStyles.PropertyState} |
- */ |
- propertyState: function(property) |
- { |
- if (this._propertiesState.size === 0) { |
- this._computeActiveProperties(this._nodeStyles, this._propertiesState); |
- for (var pseudoElementStyles of this._pseudoStyles.valuesArray()) |
- this._computeActiveProperties(pseudoElementStyles, this._propertiesState); |
+ var isKnownProperty = propertyToEffectiveRule.has(canonicalName); |
+ var inheritedFromNode = inherited ? this.nodeForStyle(style) : null; |
+ if (!isKnownProperty && inheritedFromNode && !inheritedPropertyToNode.has(canonicalName)) |
+ inheritedPropertyToNode.set(canonicalName, inheritedFromNode); |
+ |
+ if (property.important) { |
+ if (inherited && isKnownProperty && inheritedFromNode !== inheritedPropertyToNode.get(canonicalName)) { |
+ result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
+ continue; |
+ } |
+ |
+ foundImportantProperties.add(canonicalName); |
+ if (isKnownProperty) { |
+ var overloaded = /** @type {!WebInspector.CSSProperty} */ ( |
+ propertyToEffectiveRule.get(canonicalName).get(canonicalName)); |
+ result.set(overloaded, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
+ propertyToEffectiveRule.get(canonicalName).delete(canonicalName); |
+ } |
} |
- return this._propertiesState.get(property) || null; |
- }, |
- |
- resetActiveProperties: function() |
- { |
- /** @type {!Map<!WebInspector.CSSProperty, !WebInspector.CSSMatchedStyles.PropertyState>} */ |
- this._propertiesState = new Map(); |
- }, |
- /** |
- * @param {!Array<!WebInspector.CSSStyleDeclaration>} styles |
- * @param {!Map<!WebInspector.CSSProperty, !WebInspector.CSSMatchedStyles.PropertyState>} result |
- */ |
- _computeActiveProperties: function(styles, result) |
- { |
- /** @type {!Set.<string>} */ |
- var foundImportantProperties = new Set(); |
- /** @type {!Map.<string, !Map<string, !WebInspector.CSSProperty>>} */ |
- var propertyToEffectiveRule = new Map(); |
- /** @type {!Map.<string, !WebInspector.DOMNode>} */ |
- var inheritedPropertyToNode = new Map(); |
- /** @type {!Set<string>} */ |
- var allUsedProperties = new Set(); |
- for (var i = 0; i < styles.length; ++i) { |
- var style = styles[i]; |
- var rule = style.parentRule; |
- // Compute cascade for CSSStyleRules only. |
- if (rule && !(rule instanceof WebInspector.CSSStyleRule)) |
- continue; |
- if (rule && !this.hasMatchingSelectors(rule)) |
- continue; |
- |
- /** @type {!Map<string, !WebInspector.CSSProperty>} */ |
- var styleActiveProperties = new Map(); |
- var allProperties = style.allProperties; |
- for (var j = 0; j < allProperties.length; ++j) { |
- var property = allProperties[j]; |
- |
- // Do not pick non-inherited properties from inherited styles. |
- var inherited = this.isInherited(style); |
- if (inherited && !WebInspector.cssMetadata().isPropertyInherited(property.name)) |
- continue; |
- |
- if (!property.activeInStyle()) { |
- result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
- continue; |
- } |
- |
- var canonicalName = WebInspector.cssMetadata().canonicalPropertyName(property.name); |
- if (foundImportantProperties.has(canonicalName)) { |
- result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
- continue; |
- } |
- |
- if (!property.important && allUsedProperties.has(canonicalName)) { |
- result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
- continue; |
- } |
- |
- var isKnownProperty = propertyToEffectiveRule.has(canonicalName); |
- var inheritedFromNode = inherited ? this.nodeForStyle(style) : null; |
- if (!isKnownProperty && inheritedFromNode && !inheritedPropertyToNode.has(canonicalName)) |
- inheritedPropertyToNode.set(canonicalName, inheritedFromNode); |
- |
- if (property.important) { |
- if (inherited && isKnownProperty && inheritedFromNode !== inheritedPropertyToNode.get(canonicalName)) { |
- result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
- continue; |
- } |
- |
- foundImportantProperties.add(canonicalName); |
- if (isKnownProperty) { |
- var overloaded = /** @type {!WebInspector.CSSProperty} */(propertyToEffectiveRule.get(canonicalName).get(canonicalName)); |
- result.set(overloaded, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
- propertyToEffectiveRule.get(canonicalName).delete(canonicalName); |
- } |
- } |
- |
- styleActiveProperties.set(canonicalName, property); |
- allUsedProperties.add(canonicalName); |
- propertyToEffectiveRule.set(canonicalName, styleActiveProperties); |
- result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Active); |
- } |
- |
- // If every longhand of the shorthand is not active, then the shorthand is not active too. |
- for (var property of style.leadingProperties()) { |
- var canonicalName = WebInspector.cssMetadata().canonicalPropertyName(property.name); |
- if (!styleActiveProperties.has(canonicalName)) |
- continue; |
- var longhands = style.longhandProperties(property.name); |
- if (!longhands.length) |
- continue; |
- var notUsed = true; |
- for (var longhand of longhands) { |
- var longhandCanonicalName = WebInspector.cssMetadata().canonicalPropertyName(longhand.name); |
- notUsed = notUsed && !styleActiveProperties.has(longhandCanonicalName); |
- } |
- if (!notUsed) |
- continue; |
- styleActiveProperties.delete(canonicalName); |
- allUsedProperties.delete(canonicalName); |
- result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
- } |
+ styleActiveProperties.set(canonicalName, property); |
+ allUsedProperties.add(canonicalName); |
+ propertyToEffectiveRule.set(canonicalName, styleActiveProperties); |
+ result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Active); |
+ } |
+ |
+ // If every longhand of the shorthand is not active, then the shorthand is not active too. |
+ for (var property of style.leadingProperties()) { |
+ var canonicalName = WebInspector.cssMetadata().canonicalPropertyName(property.name); |
+ if (!styleActiveProperties.has(canonicalName)) |
+ continue; |
+ var longhands = style.longhandProperties(property.name); |
+ if (!longhands.length) |
+ continue; |
+ var notUsed = true; |
+ for (var longhand of longhands) { |
+ var longhandCanonicalName = WebInspector.cssMetadata().canonicalPropertyName(longhand.name); |
+ notUsed = notUsed && !styleActiveProperties.has(longhandCanonicalName); |
} |
+ if (!notUsed) |
+ continue; |
+ styleActiveProperties.delete(canonicalName); |
+ allUsedProperties.delete(canonicalName); |
+ result.set(property, WebInspector.CSSMatchedStyles.PropertyState.Overloaded); |
+ } |
} |
+ } |
}; |
/** @enum {string} */ |
WebInspector.CSSMatchedStyles.PropertyState = { |
- Active: "Active", |
- Overloaded: "Overloaded" |
+ Active: 'Active', |
+ Overloaded: 'Overloaded' |
}; |