Index: third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js |
index 6a4bddb33c0368ee9d19e78baa4e2aef6643e205..c26663288a8688d0239b4eba9c7aba73233ded41 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js |
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js |
@@ -140,7 +140,11 @@ WebInspector.CSSStyleModel.prototype = { |
if (error) |
return null; |
- return new WebInspector.CSSStyleModel.MatchedStyleResult(this, nodeId, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload); |
+ var node = this._domModel.nodeForId(nodeId); |
+ if (!node) |
+ return null; |
+ |
+ return new WebInspector.CSSStyleModel.MatchedStyleResult(this, node, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload); |
} |
return this._agent.getMatchedStylesForNode(nodeId, callback.bind(this)); |
@@ -2046,18 +2050,17 @@ WebInspector.CSSStyleModel.fromNode = function(node) |
/** |
* @constructor |
* @param {!WebInspector.CSSStyleModel} cssModel |
- * @param {!DOMAgent.NodeId} nodeId |
+ * @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 |
*/ |
-WebInspector.CSSStyleModel.MatchedStyleResult = function(cssModel, nodeId, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload) |
+WebInspector.CSSStyleModel.MatchedStyleResult = function(cssModel, node, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload) |
{ |
this._cssModel = cssModel; |
- this._node = this._cssModel._domModel.nodeForId(nodeId); |
- |
+ this._node = node; |
this._nodeStyles = []; |
this._nodeForStyle = new Map(); |
this._inheritedStyles = new Set(); |
@@ -2137,10 +2140,43 @@ WebInspector.CSSStyleModel.MatchedStyleResult = function(cssModel, nodeId, inlin |
this._pseudoStyles.set(entryPayload.pseudoType, pseudoStyles); |
} |
} |
+ |
+ this.resetActiveProperties(); |
} |
WebInspector.CSSStyleModel.MatchedStyleResult.prototype = { |
/** |
+ * @return {!WebInspector.DOMNode} |
+ */ |
+ node: function() |
+ { |
+ return this._node; |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleDeclaration} style |
+ * @return {boolean} |
+ */ |
+ hasMatchingSelectors: function(style) |
+ { |
+ return style.parentRule ? style.parentRule.matchingSelectors && style.parentRule.matchingSelectors.length > 0 && this.mediaMatches(style) : true; |
dgozman
2015/11/09 20:36:42
I'm surprised that CSSRule has matchingSelectors p
lushnikov
2015/11/09 21:42:57
Yes, I'm on my way there.
|
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleDeclaration} style |
+ * @return {boolean} |
+ */ |
+ mediaMatches: function(style) |
dgozman
2015/11/09 20:36:42
This method should be a part of CSSRule.
lushnikov
2015/11/09 21:42:57
Rule does not have any medias, MatchedStyles objec
dgozman
2015/11/09 21:48:29
But you get media from parentRule. Isn't that a CS
lushnikov
2015/11/09 21:54:01
This is a CSSRule, but it will not contain medias
dgozman
2015/11/09 22:03:36
Thanks for explanation.
lushnikov
2015/11/09 22:11:12
Well, it is used for both rendering in SSP and com
|
+ { |
+ 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: function() |
@@ -2188,9 +2224,128 @@ WebInspector.CSSStyleModel.MatchedStyleResult.prototype = { |
isInherited: function(style) |
{ |
return this._inheritedStyles.has(style); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSProperty} property |
+ * @return {?WebInspector.CSSStyleModel.MatchedStyleResult.PropertyState} |
+ */ |
+ propertyState: function(property) |
+ { |
+ if (this._propertiesState.size === 0) { |
dgozman
2015/11/09 20:36:42
Could it be that size is zero even after calculati
lushnikov
2015/11/09 21:42:57
You might recreate this situation if you'd like: y
|
+ 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: function() |
+ { |
+ /** @type {!Map<!WebInspector.CSSProperty, !WebInspector.CSSStyleModel.MatchedStyleResult.PropertyState>} */ |
+ this._propertiesState = new Map(); |
dgozman
2015/11/09 20:36:42
.clear()
lushnikov
2015/11/09 21:42:57
The resetActiveProperties() is used in the constru
|
+ }, |
+ |
+ /** |
+ * @param {!Array<!WebInspector.CSSStyleDeclaration>} styles |
+ * @param {!Map<!WebInspector.CSSProperty, !WebInspector.CSSStyleModel.MatchedStyleResult.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]; |
+ if (!this.hasMatchingSelectors(style)) |
+ 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.CSSStyleModel.MatchedStyleResult.PropertyState.Overloaded); |
+ continue; |
+ } |
+ |
+ var canonicalName = WebInspector.CSSMetadata.canonicalPropertyName(property.name); |
+ if (foundImportantProperties.has(canonicalName)) { |
+ result.set(property, WebInspector.CSSStyleModel.MatchedStyleResult.PropertyState.Overloaded); |
+ continue; |
+ } |
+ |
+ if (!property.important && allUsedProperties.has(canonicalName)) { |
+ result.set(property, WebInspector.CSSStyleModel.MatchedStyleResult.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.CSSStyleModel.MatchedStyleResult.PropertyState.Overloaded); |
+ continue; |
+ } |
+ |
+ foundImportantProperties.add(canonicalName); |
+ if (isKnownProperty) { |
+ var overloaded = /** @type {!WebInspector.CSSProperty} */(propertyToEffectiveRule.get(canonicalName).get(canonicalName)); |
+ result.set(overloaded, WebInspector.CSSStyleModel.MatchedStyleResult.PropertyState.Overloaded); |
+ propertyToEffectiveRule.get(canonicalName).delete(canonicalName); |
+ } |
+ } |
+ |
+ styleActiveProperties.set(canonicalName, property); |
+ allUsedProperties.add(canonicalName); |
+ propertyToEffectiveRule.set(canonicalName, styleActiveProperties); |
+ result.set(property, WebInspector.CSSStyleModel.MatchedStyleResult.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.CSSStyleModel.MatchedStyleResult.PropertyState.Overloaded); |
+ } |
+ } |
} |
} |
+/** @enum {string} */ |
+WebInspector.CSSStyleModel.MatchedStyleResult.PropertyState = { |
+ Active: "Active", |
+ Overloaded: "Overloaded" |
+} |
+ |
/** |
* @constructor |
* @param {?WebInspector.CSSStyleDeclaration} inlineStyle |