mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 834187 - [Computed view] Restore processing of namespaced type selectors e.g. :not(svg|a)
This commit is contained in:
parent
35af0f7e6f
commit
8f982b54a0
@ -125,8 +125,6 @@ CssLogic.prototype = {
|
|||||||
_matchedRules: null,
|
_matchedRules: null,
|
||||||
_matchedSelectors: null,
|
_matchedSelectors: null,
|
||||||
|
|
||||||
domUtils: Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset various properties
|
* Reset various properties
|
||||||
*/
|
*/
|
||||||
@ -470,8 +468,9 @@ CssLogic.prototype = {
|
|||||||
|
|
||||||
rule.selectors.forEach(function (aSelector) {
|
rule.selectors.forEach(function (aSelector) {
|
||||||
if (aSelector._matchId !== this._matchId &&
|
if (aSelector._matchId !== this._matchId &&
|
||||||
(aSelector.elementStyle ||
|
(aSelector.elementStyle ||
|
||||||
this._selectorMatchesElement(aSelector))) {
|
this.selectorMatchesElement(rule._domRule, aSelector.selectorIndex))) {
|
||||||
|
|
||||||
aSelector._matchId = this._matchId;
|
aSelector._matchId = this._matchId;
|
||||||
this._matchedSelectors.push([ aSelector, status ]);
|
this._matchedSelectors.push([ aSelector, status ]);
|
||||||
if (aCallback) {
|
if (aCallback) {
|
||||||
@ -489,15 +488,19 @@ CssLogic.prototype = {
|
|||||||
* parents.
|
* parents.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {string} aSelector the selector string you want to check.
|
* @param {DOMRule} domRule
|
||||||
* @return {boolean} true if the given selector matches the highlighted
|
* The DOM Rule containing the selector.
|
||||||
* element or any of its parents, otherwise false is returned.
|
* @param {Number} idx
|
||||||
|
* The index of the selector within the DOMRule.
|
||||||
|
* @return {boolean}
|
||||||
|
* true if the given selector matches the highlighted element or any
|
||||||
|
* of its parents, otherwise false is returned.
|
||||||
*/
|
*/
|
||||||
_selectorMatchesElement: function CL__selectorMatchesElement(aSelector)
|
selectorMatchesElement: function CL_selectorMatchesElement2(domRule, idx)
|
||||||
{
|
{
|
||||||
let element = this.viewedElement;
|
let element = this.viewedElement;
|
||||||
do {
|
do {
|
||||||
if (element.mozMatchesSelector(aSelector)) {
|
if (domUtils.selectorMatchesElement(element, domRule, idx)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} while ((element = element.parentNode) &&
|
} while ((element = element.parentNode) &&
|
||||||
@ -531,7 +534,7 @@ CssLogic.prototype = {
|
|||||||
if (rule.getPropertyValue(aProperty) &&
|
if (rule.getPropertyValue(aProperty) &&
|
||||||
(status == CssLogic.STATUS.MATCHED ||
|
(status == CssLogic.STATUS.MATCHED ||
|
||||||
(status == CssLogic.STATUS.PARENT_MATCH &&
|
(status == CssLogic.STATUS.PARENT_MATCH &&
|
||||||
this.domUtils.isInheritedProperty(aProperty)))) {
|
domUtils.isInheritedProperty(aProperty)))) {
|
||||||
result[aProperty] = true;
|
result[aProperty] = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -569,7 +572,7 @@ CssLogic.prototype = {
|
|||||||
CssLogic.STATUS.MATCHED : CssLogic.STATUS.PARENT_MATCH;
|
CssLogic.STATUS.MATCHED : CssLogic.STATUS.PARENT_MATCH;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
domRules = this.domUtils.getCSSStyleRules(element);
|
domRules = domUtils.getCSSStyleRules(element);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Services.console.
|
Services.console.
|
||||||
logStringMessage("CL__buildMatchedRules error: " + ex);
|
logStringMessage("CL__buildMatchedRules error: " + ex);
|
||||||
@ -690,65 +693,22 @@ CssLogic.getShortNamePath = function CssLogic_getShortNamePath(aElement)
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a string list of selectors for a given CSSStyleRule.selectorText
|
* Get a string list of selectors for a given DOMRule.
|
||||||
*
|
*
|
||||||
* @param {string} aSelectorText The CSSStyleRule.selectorText to parse.
|
* @param {DOMRule} aDOMRule
|
||||||
* @return {array} An array of string selectors.
|
* The DOMRule to parse.
|
||||||
|
* @return {Array}
|
||||||
|
* An array of string selectors.
|
||||||
*/
|
*/
|
||||||
CssLogic.getSelectors = function CssLogic_getSelectors(aSelectorText)
|
CssLogic.getSelectors = function CssLogic_getSelectors(aDOMRule)
|
||||||
{
|
{
|
||||||
let selectors = [];
|
let selectors = [];
|
||||||
|
|
||||||
let selector = aSelectorText.trim();
|
let len = domUtils.getSelectorCount(aDOMRule);
|
||||||
if (!selector) {
|
for (let i = 0; i < len; i++) {
|
||||||
return selectors;
|
let text = domUtils.getSelectorText(aDOMRule, i);
|
||||||
|
selectors.push(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
let nesting = 0;
|
|
||||||
let currentSelector = [];
|
|
||||||
|
|
||||||
// Parse a selector group into selectors. Normally we could just .split(',')
|
|
||||||
// however Gecko allows -moz-any(a, b, c) as a selector so we ignore commas
|
|
||||||
// inside brackets.
|
|
||||||
for (let i = 0, selLen = selector.length; i < selLen; i++) {
|
|
||||||
let c = selector.charAt(i);
|
|
||||||
switch (c) {
|
|
||||||
case ",":
|
|
||||||
if (nesting == 0 && currentSelector.length > 0) {
|
|
||||||
let selectorStr = currentSelector.join("").trim();
|
|
||||||
if (selectorStr) {
|
|
||||||
selectors.push(selectorStr);
|
|
||||||
}
|
|
||||||
currentSelector = [];
|
|
||||||
} else {
|
|
||||||
currentSelector.push(c);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "(":
|
|
||||||
nesting++;
|
|
||||||
currentSelector.push(c);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ")":
|
|
||||||
nesting--;
|
|
||||||
currentSelector.push(c);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
currentSelector.push(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the last selector.
|
|
||||||
if (nesting == 0 && currentSelector.length > 0) {
|
|
||||||
let selectorStr = currentSelector.join("").trim();
|
|
||||||
if (selectorStr) {
|
|
||||||
selectors.push(selectorStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return selectors;
|
return selectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1171,7 +1131,7 @@ function CssRule(aCssSheet, aDomRule, aElement)
|
|||||||
if (this._cssSheet) {
|
if (this._cssSheet) {
|
||||||
// parse _domRule.selectorText on call to this.selectors
|
// parse _domRule.selectorText on call to this.selectors
|
||||||
this._selectors = null;
|
this._selectors = null;
|
||||||
this.line = this._cssSheet._cssLogic.domUtils.getRuleLine(this._domRule);
|
this.line = domUtils.getRuleLine(this._domRule);
|
||||||
this.source = this._cssSheet.shortSource + ":" + this.line;
|
this.source = this._cssSheet.shortSource + ":" + this.line;
|
||||||
if (this.mediaText) {
|
if (this.mediaText) {
|
||||||
this.source += " @media " + this.mediaText;
|
this.source += " @media " + this.mediaText;
|
||||||
@ -1179,7 +1139,7 @@ function CssRule(aCssSheet, aDomRule, aElement)
|
|||||||
this.href = this._cssSheet.href;
|
this.href = this._cssSheet.href;
|
||||||
this.contentRule = this._cssSheet.contentSheet;
|
this.contentRule = this._cssSheet.contentSheet;
|
||||||
} else if (aElement) {
|
} else if (aElement) {
|
||||||
this._selectors = [ new CssSelector(this, "@element.style") ];
|
this._selectors = [ new CssSelector(this, "@element.style", 0) ];
|
||||||
this.line = -1;
|
this.line = -1;
|
||||||
this.source = CssLogic.l10n("rule.sourceElement");
|
this.source = CssLogic.l10n("rule.sourceElement");
|
||||||
this.href = "#";
|
this.href = "#";
|
||||||
@ -1263,8 +1223,12 @@ CssRule.prototype = {
|
|||||||
return this._selectors;
|
return this._selectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectors = CssLogic.getSelectors(this._domRule.selectorText);
|
let selectors = CssLogic.getSelectors(this._domRule);
|
||||||
this._selectors = [new CssSelector(this, text) for (text of selectors)];
|
|
||||||
|
for (let i = 0, len = selectors.length; i < len; i++) {
|
||||||
|
this._selectors.push(new CssSelector(this, selectors[i], i));
|
||||||
|
}
|
||||||
|
|
||||||
return this._selectors;
|
return this._selectors;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1281,13 +1245,15 @@ CssRule.prototype = {
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @param {CssRule} aCssRule the CssRule instance from where the selector comes.
|
* @param {CssRule} aCssRule the CssRule instance from where the selector comes.
|
||||||
* @param {string} aSelector The selector that we wish to investigate.
|
* @param {string} aSelector The selector that we wish to investigate.
|
||||||
|
* @param {Number} aIndex The index of the selector within it's rule.
|
||||||
*/
|
*/
|
||||||
this.CssSelector = function CssSelector(aCssRule, aSelector)
|
this.CssSelector = function CssSelector(aCssRule, aSelector, aIndex)
|
||||||
{
|
{
|
||||||
this._cssRule = aCssRule;
|
this._cssRule = aCssRule;
|
||||||
this.text = aSelector;
|
this.text = aSelector;
|
||||||
this.elementStyle = this.text == "@element.style";
|
this.elementStyle = this.text == "@element.style";
|
||||||
this._specificity = null;
|
this._specificity = null;
|
||||||
|
this.selectorIndex = aIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
CssSelector.prototype = {
|
CssSelector.prototype = {
|
||||||
@ -1402,8 +1368,7 @@ CssSelector.prototype = {
|
|||||||
* @see http://www.w3.org/TR/css3-selectors/#specificity
|
* @see http://www.w3.org/TR/css3-selectors/#specificity
|
||||||
* @see http://www.w3.org/TR/CSS2/selector.html
|
* @see http://www.w3.org/TR/CSS2/selector.html
|
||||||
*
|
*
|
||||||
* @return {object} an object holding specificity information for the current
|
* @return {Number} The selector's specificity.
|
||||||
* selector.
|
|
||||||
*/
|
*/
|
||||||
get specificity()
|
get specificity()
|
||||||
{
|
{
|
||||||
@ -1411,59 +1376,8 @@ CssSelector.prototype = {
|
|||||||
return this._specificity;
|
return this._specificity;
|
||||||
}
|
}
|
||||||
|
|
||||||
let specificity = {
|
this._specificity = domUtils.getSpecificity(this._cssRule._domRule,
|
||||||
ids: 0,
|
this.selectorIndex);
|
||||||
classes: 0,
|
|
||||||
tags: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
let text = this.text;
|
|
||||||
|
|
||||||
if (!this.elementStyle) {
|
|
||||||
// Remove universal selectors as they are not relevant as far as specificity
|
|
||||||
// is concerned.
|
|
||||||
text = text.replace(RX_UNIVERSAL_SELECTOR, "");
|
|
||||||
|
|
||||||
// not() is ignored but any selectors contained by it are counted. Let's
|
|
||||||
// remove the not() and keep the contents.
|
|
||||||
text = text.replace(RX_NOT, " $1");
|
|
||||||
|
|
||||||
// Simplify remaining psuedo classes & elements.
|
|
||||||
text = text.replace(RX_PSEUDO_CLASS_OR_ELT, " $1)");
|
|
||||||
|
|
||||||
// Replace connectors with spaces
|
|
||||||
text = text.replace(RX_CONNECTORS, " ");
|
|
||||||
|
|
||||||
text.split(/\s/).forEach(function(aSimple) {
|
|
||||||
// Count IDs.
|
|
||||||
aSimple = aSimple.replace(RX_ID, function() {
|
|
||||||
specificity.ids++;
|
|
||||||
return "";
|
|
||||||
});
|
|
||||||
|
|
||||||
// Count class names and attribute matchers.
|
|
||||||
aSimple = aSimple.replace(RX_CLASS_OR_ATTRIBUTE, function() {
|
|
||||||
specificity.classes++;
|
|
||||||
return "";
|
|
||||||
});
|
|
||||||
|
|
||||||
aSimple = aSimple.replace(RX_PSEUDO, function(aDummy, aPseudoName) {
|
|
||||||
if (this.pseudoElements.has(aPseudoName)) {
|
|
||||||
// Pseudo elements count as tags.
|
|
||||||
specificity.tags++;
|
|
||||||
} else {
|
|
||||||
// Pseudo classes count as classes.
|
|
||||||
specificity.classes++;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
if (aSimple) {
|
|
||||||
specificity.tags++;
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
this._specificity = specificity;
|
|
||||||
|
|
||||||
return this._specificity;
|
return this._specificity;
|
||||||
},
|
},
|
||||||
@ -1610,7 +1524,7 @@ CssPropertyInfo.prototype = {
|
|||||||
if (value &&
|
if (value &&
|
||||||
(aStatus == CssLogic.STATUS.MATCHED ||
|
(aStatus == CssLogic.STATUS.MATCHED ||
|
||||||
(aStatus == CssLogic.STATUS.PARENT_MATCH &&
|
(aStatus == CssLogic.STATUS.PARENT_MATCH &&
|
||||||
this._cssLogic.domUtils.isInheritedProperty(this.property)))) {
|
domUtils.isInheritedProperty(this.property)))) {
|
||||||
let selectorInfo = new CssSelectorInfo(aSelector, this.property, value,
|
let selectorInfo = new CssSelectorInfo(aSelector, this.property, value,
|
||||||
aStatus);
|
aStatus);
|
||||||
this._matchedSelectors.push(selectorInfo);
|
this._matchedSelectors.push(selectorInfo);
|
||||||
@ -1677,25 +1591,6 @@ function CssSelectorInfo(aSelector, aProperty, aValue, aStatus)
|
|||||||
|
|
||||||
let priority = this.selector._cssRule.getPropertyPriority(this.property);
|
let priority = this.selector._cssRule.getPropertyPriority(this.property);
|
||||||
this.important = (priority === "important");
|
this.important = (priority === "important");
|
||||||
|
|
||||||
/* Score prefix:
|
|
||||||
0 UA normal property
|
|
||||||
1 UA important property
|
|
||||||
2 normal property
|
|
||||||
3 inline (element.style)
|
|
||||||
4 important
|
|
||||||
5 inline important
|
|
||||||
*/
|
|
||||||
let scorePrefix = this.contentRule ? 2 : 0;
|
|
||||||
if (this.elementStyle) {
|
|
||||||
scorePrefix++;
|
|
||||||
}
|
|
||||||
if (this.important) {
|
|
||||||
scorePrefix += this.contentRule ? 2 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.specificityScore = "" + scorePrefix + this.specificity.ids +
|
|
||||||
this.specificity.classes + this.specificity.tags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CssSelectorInfo.prototype = {
|
CssSelectorInfo.prototype = {
|
||||||
@ -1824,14 +1719,8 @@ CssSelectorInfo.prototype = {
|
|||||||
if (this.important && !aThat.important) return -1;
|
if (this.important && !aThat.important) return -1;
|
||||||
if (aThat.important && !this.important) return 1;
|
if (aThat.important && !this.important) return 1;
|
||||||
|
|
||||||
if (this.specificity.ids > aThat.specificity.ids) return -1;
|
if (this.specificity > aThat.specificity) return -1;
|
||||||
if (aThat.specificity.ids > this.specificity.ids) return 1;
|
if (aThat.specificity > this.specificity) return 1;
|
||||||
|
|
||||||
if (this.specificity.classes > aThat.specificity.classes) return -1;
|
|
||||||
if (aThat.specificity.classes > this.specificity.classes) return 1;
|
|
||||||
|
|
||||||
if (this.specificity.tags > aThat.specificity.tags) return -1;
|
|
||||||
if (aThat.specificity.tags > this.specificity.tags) return 1;
|
|
||||||
|
|
||||||
if (this.sheetIndex > aThat.sheetIndex) return -1;
|
if (this.sheetIndex > aThat.sheetIndex) return -1;
|
||||||
if (aThat.sheetIndex > this.sheetIndex) return 1;
|
if (aThat.sheetIndex > this.sheetIndex) return 1;
|
||||||
@ -1847,3 +1736,7 @@ CssSelectorInfo.prototype = {
|
|||||||
return this.selector + " -> " + this.value;
|
return this.selector + " -> " + this.value;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "domUtils", function() {
|
||||||
|
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||||
|
});
|
||||||
|
@ -108,8 +108,6 @@ ElementStyle.prototype = {
|
|||||||
// to figure out how shorthand properties will be parsed.
|
// to figure out how shorthand properties will be parsed.
|
||||||
dummyElement: null,
|
dummyElement: null,
|
||||||
|
|
||||||
domUtils: Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the Rule object when it has been changed through the
|
* Called by the Rule object when it has been changed through the
|
||||||
* setProperty* methods.
|
* setProperty* methods.
|
||||||
@ -158,7 +156,7 @@ ElementStyle.prototype = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Get the styles that apply to the element.
|
// Get the styles that apply to the element.
|
||||||
var domRules = this.domUtils.getCSSStyleRules(aElement);
|
var domRules = domUtils.getCSSStyleRules(aElement);
|
||||||
|
|
||||||
// getCSStyleRules returns ordered from least-specific to
|
// getCSStyleRules returns ordered from least-specific to
|
||||||
// most-specific.
|
// most-specific.
|
||||||
@ -413,7 +411,7 @@ Rule.prototype = {
|
|||||||
// No stylesheet, no ruleLine
|
// No stylesheet, no ruleLine
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.elementStyle.domUtils.getRuleLine(this.domRule);
|
return domUtils.getRuleLine(this.domRule);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -576,8 +574,7 @@ Rule.prototype = {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
let name = matches[1];
|
let name = matches[1];
|
||||||
if (this.inherited &&
|
if (this.inherited && !domUtils.isInheritedProperty(name)) {
|
||||||
!this.elementStyle.domUtils.isInheritedProperty(name)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let value = store.userProperties.getProperty(this.style, name, matches[2]);
|
let value = store.userProperties.getProperty(this.style, name, matches[2]);
|
||||||
@ -1448,7 +1445,7 @@ RuleEditor.prototype = {
|
|||||||
// actually match. For custom selector text (such as for the 'element'
|
// actually match. For custom selector text (such as for the 'element'
|
||||||
// style, just show the text directly.
|
// style, just show the text directly.
|
||||||
if (this.rule.domRule && this.rule.domRule.selectorText) {
|
if (this.rule.domRule && this.rule.domRule.selectorText) {
|
||||||
let selectors = CssLogic.getSelectors(this.rule.selectorText);
|
let selectors = CssLogic.getSelectors(this.rule.domRule);
|
||||||
let element = this.rule.inherited || this.ruleView._viewedElement;
|
let element = this.rule.inherited || this.ruleView._viewedElement;
|
||||||
for (let i = 0; i < selectors.length; i++) {
|
for (let i = 0; i < selectors.length; i++) {
|
||||||
let selector = selectors[i];
|
let selector = selectors[i];
|
||||||
@ -1458,8 +1455,12 @@ RuleEditor.prototype = {
|
|||||||
textContent: ", "
|
textContent: ", "
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let cls = element.mozMatchesSelector(selector) ? "ruleview-selector-matched" :
|
let cls;
|
||||||
"ruleview-selector-unmatched";
|
if (domUtils.selectorMatchesElement(element, this.rule.domRule, i)) {
|
||||||
|
cls = "ruleview-selector-matched";
|
||||||
|
} else {
|
||||||
|
cls = "ruleview-selector-unmatched";
|
||||||
|
}
|
||||||
createChild(this.selectorText, "span", {
|
createChild(this.selectorText, "span", {
|
||||||
class: cls,
|
class: cls,
|
||||||
textContent: selector
|
textContent: selector
|
||||||
@ -2847,3 +2848,7 @@ XPCOMUtils.defineLazyGetter(this, "_strings", function() {
|
|||||||
XPCOMUtils.defineLazyGetter(this, "osString", function() {
|
XPCOMUtils.defineLazyGetter(this, "osString", function() {
|
||||||
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
|
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "domUtils", function() {
|
||||||
|
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||||
|
});
|
||||||
|
@ -9,41 +9,93 @@ Cu.import("resource:///modules/devtools/CssLogic.jsm", tempScope);
|
|||||||
let CssLogic = tempScope.CssLogic;
|
let CssLogic = tempScope.CssLogic;
|
||||||
let CssSelector = tempScope.CssSelector;
|
let CssSelector = tempScope.CssSelector;
|
||||||
|
|
||||||
function test()
|
function createDocument()
|
||||||
{
|
{
|
||||||
let tests = [
|
let doc = content.document;
|
||||||
{text: "*", expected: "000"},
|
doc.body.innerHTML = getStylesheetText();
|
||||||
{text: "LI", expected: "001"},
|
doc.title = "Computed view specificity test";
|
||||||
{text: "UL LI", expected: "002"},
|
runTests(doc);
|
||||||
{text: "UL OL+LI", expected: "003"},
|
}
|
||||||
{text: "H1 + *[REL=up]", expected: "011"},
|
|
||||||
{text: "UL OL LI.red", expected: "013"},
|
|
||||||
{text: "LI.red.level", expected: "021"},
|
|
||||||
{text: ".red .level", expected: "020"},
|
|
||||||
{text: "#x34y", expected: "100"},
|
|
||||||
{text: "#s12:not(FOO)", expected: "101"},
|
|
||||||
{text: "body#home div#warning p.message", expected: "213"},
|
|
||||||
{text: "* body#home div#warning p.message", expected: "213"},
|
|
||||||
{text: "#footer *:not(nav) li", expected: "102"},
|
|
||||||
{text: "bar:nth-child(1n+0)", expected: "011"},
|
|
||||||
{text: "li::-moz-list-number", expected: "002"},
|
|
||||||
{text: "a:hover", expected: "011"},
|
|
||||||
];
|
|
||||||
|
|
||||||
tests.forEach(function(aTest) {
|
function runTests(doc) {
|
||||||
let selector = new CssSelector(null, aTest.text);
|
let cssLogic = new CssLogic();
|
||||||
let specificity = selector.specificity;
|
cssLogic.highlight(doc.body);
|
||||||
|
|
||||||
let result = "" + specificity.ids + specificity.classes + specificity.tags;
|
let tests = getTests();
|
||||||
is(result, aTest.expected, "selector \"" + aTest.text +
|
let cssSheet = cssLogic.sheets[0];
|
||||||
"\" produces expected result");
|
let cssRule = cssSheet.domSheet.cssRules[0];
|
||||||
});
|
let selectors = CssLogic.getSelectors(cssRule);
|
||||||
|
|
||||||
|
for (let i = 0; i < selectors.length; i++) {
|
||||||
|
let selectorText = selectors[i];
|
||||||
|
let selector = new CssSelector(cssRule, selectorText, i);
|
||||||
|
let expected = getExpectedSpecificity(selectorText);
|
||||||
|
let specificity = selector.domUtils.getSpecificity(selector._cssRule,
|
||||||
|
selector.selectorIndex)
|
||||||
|
is(specificity, expected,
|
||||||
|
'selector "' + selectorText + '" has a specificity of ' + expected);
|
||||||
|
}
|
||||||
finishUp();
|
finishUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getExpectedSpecificity(selectorText) {
|
||||||
|
let tests = getTests();
|
||||||
|
|
||||||
|
for (let test of tests) {
|
||||||
|
if (test.text == selectorText) {
|
||||||
|
return test.expected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTests() {
|
||||||
|
return [
|
||||||
|
{text: "*", expected: 0},
|
||||||
|
{text: "LI", expected: 1},
|
||||||
|
{text: "UL LI", expected: 2},
|
||||||
|
{text: "UL OL + LI", expected: 3},
|
||||||
|
{text: "H1 + [REL=\"up\"]", expected: 257},
|
||||||
|
{text: "UL OL LI.red", expected: 259},
|
||||||
|
{text: "LI.red.level", expected: 513},
|
||||||
|
{text: ".red .level", expected: 512},
|
||||||
|
{text: "#x34y", expected: 65536},
|
||||||
|
{text: "#s12:not(FOO)", expected: 65537},
|
||||||
|
{text: "body#home div#warning p.message", expected: 131331},
|
||||||
|
{text: "* body#home div#warning p.message", expected: 131331},
|
||||||
|
{text: "#footer :not(nav) li", expected: 65538},
|
||||||
|
{text: "bar:nth-child(n)", expected: 257},
|
||||||
|
{text: "li::-moz-list-number", expected: 1},
|
||||||
|
{text: "a:hover", expected: 257},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStylesheetText() {
|
||||||
|
let tests = getTests();
|
||||||
|
let text = "";
|
||||||
|
|
||||||
|
tests.forEach(function(test) {
|
||||||
|
if (text.length > 0) {
|
||||||
|
text += ",";
|
||||||
|
}
|
||||||
|
text += test.text;
|
||||||
|
});
|
||||||
|
return '<style type="text/css">' + text + " {color:red;}</style>";
|
||||||
|
}
|
||||||
|
|
||||||
function finishUp()
|
function finishUp()
|
||||||
{
|
{
|
||||||
CssLogic = CssSelector = null;
|
CssLogic = CssSelector = tempScope = null;
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
gBrowser.selectedTab = gBrowser.addTab();
|
||||||
|
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||||
|
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||||
|
waitForFocus(createDocument, content);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
content.location = "data:text/html,Computed view specificity test";
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user