Chromium Code Reviews| 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 |