зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1919853 - Make InspectorUtils able to return CSSNestedDeclarations too. r=devtools-reviewers,nchevobbe,dshin
Rename getCSSStyleRules now that it can return something else, and change getCSSStyleRules_starting_style.html to cover this again. Unfortunately the asserts in ServoStyleRuleMap.cpp no longer hold, because the style attribute and other declarations are expected not to show up there. Differential Revision: https://phabricator.services.mozilla.com/D222856
This commit is contained in:
Родитель
ecc5c26f1d
Коммит
4a5f0fcca1
|
@ -200,7 +200,7 @@ const rollouts = [
|
|||
"gfx/layers/layerviewer/layerTreeView.js",
|
||||
"intl/uconv/tests/unit/test_charset_conversion.js",
|
||||
"js/src/builtin/**",
|
||||
"layout/inspector/tests/test_getCSSStyleRules.html",
|
||||
"layout/inspector/tests/test_getMatchingCSSRules.html",
|
||||
"layout/inspector/tests/test_is_valid_css_color.html",
|
||||
"layout/style/test/property_database.js",
|
||||
"layout/style/test/test_computed_style_grid_with_pseudo.html",
|
||||
|
|
|
@ -12,7 +12,7 @@ loader.lazyRequireGetter(
|
|||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"getCSSStyleRules",
|
||||
"getMatchingCSSRules",
|
||||
"resource://devtools/shared/inspector/css-logic.js",
|
||||
true
|
||||
);
|
||||
|
@ -45,9 +45,6 @@ const {
|
|||
},
|
||||
} = require("resource://devtools/shared/constants.js");
|
||||
|
||||
// Specified by the author CSS rule type.
|
||||
const STYLE_RULE = 1;
|
||||
|
||||
// Accessible action for showing long description.
|
||||
const CLICK_ACTION = "click";
|
||||
|
||||
|
@ -167,19 +164,15 @@ function hasStylesForFocusRelatedPseudoClass(
|
|||
currentNode,
|
||||
pseudoClass
|
||||
) {
|
||||
const defaultRules = getCSSStyleRules(currentNode);
|
||||
const defaultRules = getMatchingCSSRules(currentNode);
|
||||
|
||||
InspectorUtils.addPseudoClassLock(focusableNode, pseudoClass);
|
||||
|
||||
// Determine a set of properties that are specific to CSS rules that are only
|
||||
// present when a focus related pseudo-class is locked in.
|
||||
const tempRules = getCSSStyleRules(currentNode);
|
||||
const tempRules = getMatchingCSSRules(currentNode);
|
||||
const properties = new Set();
|
||||
for (const rule of tempRules) {
|
||||
if (rule.type !== STYLE_RULE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!defaultRules.includes(rule)) {
|
||||
for (let index = 0; index < rule.style.length; index++) {
|
||||
properties.add(rule.style.item(index));
|
||||
|
|
|
@ -17,7 +17,7 @@ const {
|
|||
getCurrentZoom,
|
||||
} = require("resource://devtools/shared/layout/utils.js");
|
||||
const {
|
||||
getCSSStyleRules,
|
||||
getMatchingCSSRules,
|
||||
} = require("resource://devtools/shared/inspector/css-logic.js");
|
||||
|
||||
const GEOMETRY_LABEL_SIZE = 6;
|
||||
|
@ -139,13 +139,13 @@ function getDefinedGeometryProperties(node) {
|
|||
}
|
||||
|
||||
// Get the list of css rules applying to the current node.
|
||||
const cssRules = getCSSStyleRules(node);
|
||||
const cssRules = getMatchingCSSRules(node);
|
||||
for (let i = 0; i < cssRules.length; i++) {
|
||||
const rule = cssRules[i];
|
||||
for (const name of GeoProp.allProps()) {
|
||||
const value = rule.style.getPropertyValue(name);
|
||||
if (value && value !== "auto") {
|
||||
// getCSSStyleRules returns rules ordered from least to most specific
|
||||
// getMatchingCSSRules returns rules ordered from least to most specific
|
||||
// so just override any previous properties we have set.
|
||||
props.set(name, {
|
||||
cssRule: rule,
|
||||
|
|
|
@ -36,7 +36,7 @@ const {
|
|||
} = require("resource://devtools/shared/layout/dom-matrix-2d.js");
|
||||
const EventEmitter = require("resource://devtools/shared/event-emitter.js");
|
||||
const {
|
||||
getCSSStyleRules,
|
||||
getMatchingCSSRules,
|
||||
} = require("resource://devtools/shared/inspector/css-logic.js");
|
||||
|
||||
const BASE_MARKER_SIZE = 5;
|
||||
|
@ -2991,7 +2991,7 @@ function getDefinedShapeProperties(node, property) {
|
|||
return prop;
|
||||
}
|
||||
|
||||
const cssRules = getCSSStyleRules(node);
|
||||
const cssRules = getMatchingCSSRules(node);
|
||||
for (let i = 0; i < cssRules.length; i++) {
|
||||
const rule = cssRules[i];
|
||||
const value = rule.style.getPropertyValue(property);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
const nodeConstants = require("resource://devtools/shared/dom-node-constants.js");
|
||||
const {
|
||||
getBindingElementAndPseudo,
|
||||
getCSSStyleRules,
|
||||
getMatchingCSSRules,
|
||||
hasVisitedState,
|
||||
isAgentStylesheet,
|
||||
isAuthorStylesheet,
|
||||
|
@ -586,7 +586,7 @@ class CssLogic {
|
|||
this.viewedElement === element ? STATUS.MATCHED : STATUS.PARENT_MATCH;
|
||||
|
||||
try {
|
||||
domRules = getCSSStyleRules(element);
|
||||
domRules = getMatchingCSSRules(element);
|
||||
} catch (ex) {
|
||||
console.log("CL__buildMatchedRules error: " + ex);
|
||||
continue;
|
||||
|
@ -601,17 +601,13 @@ class CssLogic {
|
|||
this._matchedRules.push([rule, status, distance]);
|
||||
}
|
||||
|
||||
// getCSSStyleRules can return null with a shadow DOM element.
|
||||
// getMatchingCSSRules can return null with a shadow DOM element.
|
||||
if (domRules !== null) {
|
||||
// getCSSStyleRules returns ordered from least-specific to most-specific,
|
||||
// getMatchingCSSRules returns ordered from least-specific to most-specific,
|
||||
// but we do want them from most-specific to least specific, so we need to loop
|
||||
// through the rules backward.
|
||||
for (let i = domRules.length - 1; i >= 0; i--) {
|
||||
const domRule = domRules[i];
|
||||
if (!CSSStyleRule.isInstance(domRule)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const sheet = this.getSheet(domRule.parentStyleSheet, -1);
|
||||
if (sheet._passId !== this._passId) {
|
||||
sheet.index = sheetIndex++;
|
||||
|
@ -1541,7 +1537,7 @@ class CssSelectorInfo {
|
|||
|
||||
/**
|
||||
* Compare the current CssSelectorInfo instance to another instance.
|
||||
* Since selectorInfos is computed from `InspectorUtils.getCSSStyleRules`,
|
||||
* Since selectorInfos is computed from `InspectorUtils.getMatchingCSSRules`,
|
||||
* it's already sorted for regular cases. We only need to handle important values.
|
||||
*
|
||||
* @param {CssSelectorInfo} that
|
||||
|
|
|
@ -30,7 +30,7 @@ loader.lazyRequireGetter(
|
|||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"getCSSStyleRules",
|
||||
"getMatchingCSSRules",
|
||||
"resource://devtools/shared/inspector/css-logic.js",
|
||||
true
|
||||
);
|
||||
|
@ -205,7 +205,7 @@ class FlexItemActor extends Actor {
|
|||
if (isElementNode) {
|
||||
for (const name in properties) {
|
||||
const values = [];
|
||||
const cssRules = getCSSStyleRules(this.element);
|
||||
const cssRules = getMatchingCSSRules(this.element);
|
||||
|
||||
for (const rule of cssRules) {
|
||||
// For each rule, go through *all* properties, because there may be several of
|
||||
|
|
|
@ -842,7 +842,7 @@ class PageStyleActor extends Actor {
|
|||
// we don't need to retrieve inherited starting style rules
|
||||
const includeStartingStyleRules =
|
||||
!inherited && DISPLAY_STARTING_STYLE_RULES;
|
||||
const domRules = InspectorUtils.getCSSStyleRules(
|
||||
const domRules = InspectorUtils.getMatchingCSSRules(
|
||||
node,
|
||||
pseudo,
|
||||
CssLogic.hasVisitedState(node),
|
||||
|
@ -857,7 +857,7 @@ class PageStyleActor extends Actor {
|
|||
|
||||
const doc = this.inspector.targetActor.window.document;
|
||||
|
||||
// getCSSStyleRules returns ordered from least-specific to
|
||||
// getMatchingCSSRules returns ordered from least-specific to
|
||||
// most-specific.
|
||||
for (let i = domRules.length - 1; i >= 0; i--) {
|
||||
const domRule = domRules[i];
|
||||
|
|
|
@ -559,16 +559,16 @@ function getBindingElementAndPseudo(node) {
|
|||
exports.getBindingElementAndPseudo = getBindingElementAndPseudo;
|
||||
|
||||
/**
|
||||
* Returns css style rules for a given a node.
|
||||
* Returns css rules for a given a node.
|
||||
* This function can handle ::before or ::after pseudo element as well as
|
||||
* normal element.
|
||||
*/
|
||||
function getCSSStyleRules(node) {
|
||||
function getMatchingCSSRules(node) {
|
||||
const { bindingElement, pseudo } = getBindingElementAndPseudo(node);
|
||||
const rules = InspectorUtils.getCSSStyleRules(bindingElement, pseudo);
|
||||
const rules = InspectorUtils.getMatchingCSSRules(bindingElement, pseudo);
|
||||
return rules;
|
||||
}
|
||||
exports.getCSSStyleRules = getCSSStyleRules;
|
||||
exports.getMatchingCSSRules = getMatchingCSSRules;
|
||||
|
||||
/**
|
||||
* Returns true if the given node has visited state.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
namespace InspectorUtils {
|
||||
// documentOnly tells whether user and UA sheets should get included.
|
||||
sequence<StyleSheet> getAllStyleSheets(Document document, optional boolean documentOnly = false);
|
||||
sequence<CSSStyleRule> getCSSStyleRules(
|
||||
sequence<CSSRule> getMatchingCSSRules(
|
||||
Element element,
|
||||
optional [LegacyNullToEmptyString] DOMString pseudo = "",
|
||||
optional boolean relevantLinkVisited = false,
|
||||
|
|
|
@ -31,7 +31,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=416896
|
|||
var linkedSheet = $("l").sheet;
|
||||
isnot(linkedSheet, null, "Should have sheet here");
|
||||
|
||||
var inspectedRules = InspectorUtils.getCSSStyleRules(document.links[0]);
|
||||
var inspectedRules = InspectorUtils.getMatchingCSSRules(document.links[0]);
|
||||
|
||||
var seenInline = false;
|
||||
var seenLinked = false;
|
||||
|
|
|
@ -8499,11 +8499,11 @@ void nsIFrame::ListTextRuns(FILE* out, nsTHashSet<const void*>& aSeen) const {
|
|||
}
|
||||
|
||||
void nsIFrame::ListMatchedRules(FILE* out, const char* aPrefix) const {
|
||||
nsTArray<const StyleLockedStyleRule*> rawRuleList;
|
||||
Servo_ComputedValues_GetStyleRuleList(mComputedStyle, &rawRuleList);
|
||||
for (const StyleLockedStyleRule* rawRule : rawRuleList) {
|
||||
nsTArray<const StyleLockedDeclarationBlock*> rawDecls;
|
||||
Servo_ComputedValues_GetMatchingDeclarations(Style(), &rawDecls);
|
||||
for (const StyleLockedDeclarationBlock* rawRule : rawDecls) {
|
||||
nsAutoCString ruleText;
|
||||
Servo_StyleRule_GetCssText(rawRule, &ruleText);
|
||||
Servo_DeclarationBlock_GetCssText(rawRule, &ruleText);
|
||||
fprintf_stderr(out, "%s%s\n", aPrefix, ruleText.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,16 +250,16 @@ static already_AddRefed<const ComputedStyle> GetStartingStyle(
|
|||
return styleSet->ResolveStartingStyle(aElement);
|
||||
}
|
||||
|
||||
static void GetCSSStyleRulesFromComputedValue(
|
||||
static void GetCSSRulesFromComputedValues(
|
||||
Element& aElement, const ComputedStyle* aComputedStyle,
|
||||
nsTArray<RefPtr<CSSStyleRule>>& aResult) {
|
||||
nsTArray<RefPtr<css::Rule>>& aResult) {
|
||||
const PresShell* presShell = aElement.OwnerDoc()->GetPresShell();
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoTArray<const StyleLockedStyleRule*, 8> rawRuleList;
|
||||
Servo_ComputedValues_GetStyleRuleList(aComputedStyle, &rawRuleList);
|
||||
AutoTArray<const StyleLockedDeclarationBlock*, 8> rawDecls;
|
||||
Servo_ComputedValues_GetMatchingDeclarations(aComputedStyle, &rawDecls);
|
||||
|
||||
AutoTArray<ServoStyleRuleMap*, 8> maps;
|
||||
{
|
||||
|
@ -295,41 +295,23 @@ static void GetCSSStyleRulesFromComputedValue(
|
|||
}
|
||||
|
||||
// Find matching rules in the table.
|
||||
for (const StyleLockedStyleRule* rawRule : Reversed(rawRuleList)) {
|
||||
CSSStyleRule* rule = nullptr;
|
||||
for (const StyleLockedDeclarationBlock* rawDecl : Reversed(rawDecls)) {
|
||||
for (ServoStyleRuleMap* map : maps) {
|
||||
rule = map->Lookup(rawRule);
|
||||
if (rule) {
|
||||
if (css::Rule* rule = map->Lookup(rawDecl)) {
|
||||
aResult.AppendElement(rule);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rule) {
|
||||
aResult.AppendElement(rule);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
aElement.Dump();
|
||||
printf_stderr("\n\n----\n\n");
|
||||
aComputedStyle->DumpMatchedRules();
|
||||
nsAutoCString str;
|
||||
Servo_StyleRule_Debug(rawRule, &str);
|
||||
printf_stderr("\n\n----\n\n");
|
||||
printf_stderr("%s\n", str.get());
|
||||
MOZ_CRASH_UNSAFE_PRINTF(
|
||||
"We should be able to map raw rule %p to a rule in one of the %zu "
|
||||
"maps: %s\n",
|
||||
rawRule, maps.Length(), str.get());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void InspectorUtils::GetCSSStyleRules(GlobalObject& aGlobalObject,
|
||||
Element& aElement,
|
||||
const nsAString& aPseudo,
|
||||
bool aIncludeVisitedStyle,
|
||||
bool aWithStartingStyle,
|
||||
nsTArray<RefPtr<CSSStyleRule>>& aResult) {
|
||||
void InspectorUtils::GetMatchingCSSRules(GlobalObject& aGlobalObject,
|
||||
Element& aElement,
|
||||
const nsAString& aPseudo,
|
||||
bool aIncludeVisitedStyle,
|
||||
bool aWithStartingStyle,
|
||||
nsTArray<RefPtr<css::Rule>>& aResult) {
|
||||
auto [type, functionalPseudoParameter] =
|
||||
nsCSSPseudoElements::ParsePseudoElement(aPseudo,
|
||||
CSSEnabledState::ForAllContent);
|
||||
|
@ -362,7 +344,7 @@ void InspectorUtils::GetCSSStyleRules(GlobalObject& aGlobalObject,
|
|||
}
|
||||
}
|
||||
|
||||
GetCSSStyleRulesFromComputedValue(aElement, computedStyle, aResult);
|
||||
GetCSSRulesFromComputedValues(aElement, computedStyle, aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -41,11 +41,11 @@ class InspectorUtils {
|
|||
static void GetAllStyleSheets(GlobalObject& aGlobal, Document& aDocument,
|
||||
bool aDocumentOnly,
|
||||
nsTArray<RefPtr<StyleSheet>>& aResult);
|
||||
static void GetCSSStyleRules(GlobalObject& aGlobal, Element& aElement,
|
||||
const nsAString& aPseudo,
|
||||
bool aIncludeVisitedStyle,
|
||||
bool aWithStartingStyle,
|
||||
nsTArray<RefPtr<CSSStyleRule>>& aResult);
|
||||
static void GetMatchingCSSRules(GlobalObject& aGlobal, Element& aElement,
|
||||
const nsAString& aPseudo,
|
||||
bool aIncludeVisitedStyle,
|
||||
bool aWithStartingStyle,
|
||||
nsTArray<RefPtr<css::Rule>>& aResult);
|
||||
|
||||
/**
|
||||
* Get the line number of a rule.
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/dom/CSSImportRule.h"
|
||||
#include "mozilla/dom/CSSRuleBinding.h"
|
||||
#include "mozilla/dom/CSSStyleRule.h"
|
||||
#include "mozilla/dom/CSSNestedDeclarations.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
|
@ -118,9 +119,14 @@ size_t ServoStyleRuleMap::SizeOfIncludingThis(
|
|||
|
||||
void ServoStyleRuleMap::FillTableFromRule(css::Rule& aRule) {
|
||||
switch (aRule.Type()) {
|
||||
case StyleCssRuleType::NestedDeclarations: {
|
||||
auto& rule = static_cast<CSSNestedDeclarations&>(aRule);
|
||||
mTable.InsertOrUpdate(rule.RawStyle(), &rule);
|
||||
break;
|
||||
}
|
||||
case StyleCssRuleType::Style: {
|
||||
auto& rule = static_cast<CSSStyleRule&>(aRule);
|
||||
mTable.InsertOrUpdate(rule.Raw(), &rule);
|
||||
mTable.InsertOrUpdate(rule.RawStyle(), &rule);
|
||||
[[fallthrough]];
|
||||
}
|
||||
case StyleCssRuleType::LayerBlock:
|
||||
|
@ -153,7 +159,6 @@ void ServoStyleRuleMap::FillTableFromRule(css::Rule& aRule) {
|
|||
case StyleCssRuleType::FontFeatureValues:
|
||||
case StyleCssRuleType::FontPaletteValues:
|
||||
case StyleCssRuleType::PositionTry:
|
||||
case StyleCssRuleType::NestedDeclarations:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef mozilla_ServoStyleRuleMap_h
|
||||
#define mozilla_ServoStyleRuleMap_h
|
||||
|
||||
#include "mozilla/dom/CSSStyleRule.h"
|
||||
#include "mozilla/css/Rule.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
|
||||
#include "nsTHashMap.h"
|
||||
|
@ -23,15 +23,15 @@ class Rule;
|
|||
namespace dom {
|
||||
class ShadowRoot;
|
||||
}
|
||||
class ServoStyleRuleMap {
|
||||
class ServoStyleRuleMap final {
|
||||
public:
|
||||
ServoStyleRuleMap() = default;
|
||||
|
||||
void EnsureTable(ServoStyleSet&);
|
||||
void EnsureTable(dom::ShadowRoot&);
|
||||
|
||||
dom::CSSStyleRule* Lookup(const StyleLockedStyleRule* aRawRule) const {
|
||||
return mTable.Get(aRawRule);
|
||||
css::Rule* Lookup(const StyleLockedDeclarationBlock* aDecls) const {
|
||||
return mTable.Get(aDecls);
|
||||
}
|
||||
|
||||
void SheetAdded(StyleSheet&);
|
||||
|
@ -55,8 +55,8 @@ class ServoStyleRuleMap {
|
|||
void FillTableFromRuleList(ServoCSSRuleList&);
|
||||
void FillTableFromStyleSheet(StyleSheet&);
|
||||
|
||||
using Hashtable = nsTHashMap<nsPtrHashKey<const StyleLockedStyleRule>,
|
||||
WeakPtr<dom::CSSStyleRule>>;
|
||||
using Hashtable = nsTHashMap<nsPtrHashKey<const StyleLockedDeclarationBlock>,
|
||||
WeakPtr<css::Rule>>;
|
||||
Hashtable mTable;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<p></p>
|
||||
<script>
|
||||
function start() {
|
||||
let rules = InspectorUtils.getCSSStyleRules(document.querySelector("p"));
|
||||
let rules = InspectorUtils.getMatchingCSSRules(document.querySelector("p"));
|
||||
ok(rules.length > 0, "Should have found some rules");
|
||||
is(rules[0].type, CSSRule.STYLE_RULE, "Should have found a style rule");
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
info(description);
|
||||
|
||||
const rules =
|
||||
InspectorUtils.getCSSStyleRules(target, undefined, isVisitedTest);
|
||||
InspectorUtils.getMatchingCSSRules(target, undefined, isVisitedTest);
|
||||
ok(getRule(rules, validSelector),
|
||||
`Rule of ${validSelector} is in rules`);
|
||||
ok(!getRule(rules, invalidSelector),
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="alternate stylesheet" title="x" href="getCSSStyleRules-1.css">
|
||||
<unknowntagname></unknowntagname>
|
|
@ -1,3 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="stylesheet" href="getCSSStyleRules-1.css">
|
||||
<unknowntagname></unknowntagname>
|
|
@ -0,0 +1,3 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="alternate stylesheet" title="x" href="getMatchingCSSRules-1.css">
|
||||
<unknowntagname></unknowntagname>
|
|
@ -0,0 +1,3 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="stylesheet" href="getMatchingCSSRules-1.css">
|
||||
<unknowntagname></unknowntagname>
|
|
@ -46,19 +46,19 @@ support-files = [
|
|||
|
||||
["test_getCSSPseudoElementNames.html"]
|
||||
|
||||
["test_getCSSStyleRules.html"]
|
||||
["test_getMatchingCSSRules.html"]
|
||||
support-files = [
|
||||
"file_getCSSStyleRules-default.html",
|
||||
"file_getCSSStyleRules-alternate.html",
|
||||
"getCSSStyleRules-1.css",
|
||||
"getCSSStyleRules-2.css",
|
||||
"file_getMatchingCSSRules-default.html",
|
||||
"file_getMatchingCSSRules-alternate.html",
|
||||
"getMatchingCSSRules-1.css",
|
||||
"getMatchingCSSRules-2.css",
|
||||
]
|
||||
|
||||
["test_getCSSStyleRules_pseudo.html"]
|
||||
["test_getMatchingCSSRules_pseudo.html"]
|
||||
|
||||
["test_getCSSStyleRules_slotted.html"]
|
||||
["test_getMatchingCSSRules_slotted.html"]
|
||||
|
||||
["test_getCSSStyleRules_starting_style.html"]
|
||||
["test_getMatchingCSSRules_starting_style.html"]
|
||||
|
||||
["test_getRegisteredCssHighlights.html"]
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ const InspectorUtils = SpecialPowers.InspectorUtils;
|
|||
|
||||
function do_test() {
|
||||
try {
|
||||
InspectorUtils.getCSSStyleRules(null);
|
||||
InspectorUtils.getMatchingCSSRules(null);
|
||||
ok(false, "expected an exception");
|
||||
}
|
||||
catch(e) {
|
||||
|
|
|
@ -31,10 +31,10 @@ function do_test() {
|
|||
var text = body.firstChild;
|
||||
|
||||
try {
|
||||
var res = InspectorUtils.getCSSStyleRules(docElement);
|
||||
is(res.length, 0, "getCSSStyleRules");
|
||||
res = InspectorUtils.getCSSStyleRules(body);
|
||||
is(res.length, 0, "getCSSStyleRules");
|
||||
var res = InspectorUtils.getMatchingCSSRules(docElement);
|
||||
is(res.length, 0, "getMatchingCSSRules");
|
||||
res = InspectorUtils.getMatchingCSSRules(body);
|
||||
is(res.length, 0, "getMatchingCSSRules");
|
||||
}
|
||||
catch(e) { ok(false, "got an unexpected exception:" + e); }
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ const CI = SpecialPowers.Ci;
|
|||
const CC = SpecialPowers.Cc;
|
||||
const InspectorUtils = SpecialPowers.InspectorUtils;
|
||||
|
||||
var rules = InspectorUtils.getCSSStyleRules(document.getElementById("display"));
|
||||
var rules = InspectorUtils.getMatchingCSSRules(document.getElementById("display"));
|
||||
var firstPRule = rules[rules.length - 2];
|
||||
firstPRule.style.removeProperty("color");
|
||||
ok(true, "should not crash");
|
||||
|
|
|
@ -22,7 +22,7 @@ const CI = SpecialPowers.Ci;
|
|||
const CC = SpecialPowers.Cc;
|
||||
const InspectorUtils = SpecialPowers.InspectorUtils;
|
||||
|
||||
var rules = InspectorUtils.getCSSStyleRules(document.getElementById("display"));
|
||||
var rules = InspectorUtils.getMatchingCSSRules(document.getElementById("display"));
|
||||
var firstPRule = rules[rules.length - 2];
|
||||
firstPRule.style.removeProperty("color");
|
||||
ok(true, "should not crash");
|
||||
|
|
|
@ -68,34 +68,34 @@ function getSelectors (rules) {
|
|||
var div = document.getElementById("div1");
|
||||
|
||||
/* empty or missing pseudo-element argument */
|
||||
var selectors = getSelectors(InspectorUtils.getCSSStyleRules(div));
|
||||
var selectors = getSelectors(InspectorUtils.getMatchingCSSRules(div));
|
||||
is(selectors.length, 1, "psuedo-element argument should be optional");
|
||||
is(selectors[0], "#div1", "should only have the non-pseudo element rule");
|
||||
|
||||
selectors = getSelectors(InspectorUtils.getCSSStyleRules(div, ""));
|
||||
selectors = getSelectors(InspectorUtils.getMatchingCSSRules(div, ""));
|
||||
is(selectors.length, 1, "pseudo-element argument can be empty string");
|
||||
is(selectors[0], "#div1", "should only have the non pseudo-element rule");
|
||||
|
||||
|
||||
/* invalid pseudo-element argument */
|
||||
var rules = InspectorUtils.getCSSStyleRules(div, "not a valid pseudo element");
|
||||
var rules = InspectorUtils.getMatchingCSSRules(div, "not a valid pseudo element");
|
||||
is(rules.length, 0, "invalid pseudo-element returns no rules");
|
||||
|
||||
|
||||
/* valid pseudo-element argument */
|
||||
selectors = getSelectors(InspectorUtils.getCSSStyleRules(div, ":first-letter"));
|
||||
selectors = getSelectors(InspectorUtils.getMatchingCSSRules(div, ":first-letter"));
|
||||
is(selectors.length, 1, "pseudo-element argument can be used");
|
||||
is(selectors[0], "#div1::first-letter", "should only have the ::first-letter rule");
|
||||
|
||||
selectors = getSelectors(InspectorUtils.getCSSStyleRules(div, ":before"));
|
||||
selectors = getSelectors(InspectorUtils.getMatchingCSSRules(div, ":before"));
|
||||
is(selectors.length, 2, "::before pseudo-element has two matching rules");
|
||||
isnot(selectors.indexOf("#div1::after, #div1::before"), -1, "fetched rule for ::before")
|
||||
isnot(selectors.indexOf("#div1::before"), -1, "fetched rule for ::before")
|
||||
|
||||
selectors = getSelectors(InspectorUtils.getCSSStyleRules(div, ":first-line"));
|
||||
selectors = getSelectors(InspectorUtils.getMatchingCSSRules(div, ":first-line"));
|
||||
is(selectors.length, 0, "valid pseudo-element but no matching rules");
|
||||
|
||||
selectors = getSelectors(InspectorUtils.getCSSStyleRules(div, "::selection"));
|
||||
selectors = getSelectors(InspectorUtils.getMatchingCSSRules(div, "::selection"));
|
||||
is(selectors.length, 1, "::selection pseudo-element has a matching rule");
|
||||
is(selectors[0], "::selection", "fetched rule for ::selection");
|
||||
|
||||
|
@ -105,11 +105,11 @@ range.setEnd(div.firstChild, 20);
|
|||
const highlight = new Highlight(range);
|
||||
CSS.highlights.set("search", highlight);
|
||||
|
||||
selectors = getSelectors(InspectorUtils.getCSSStyleRules(div, "::highlight(search)"));
|
||||
selectors = getSelectors(InspectorUtils.getMatchingCSSRules(div, "::highlight(search)"));
|
||||
is(selectors.length, 1, "::highlight(search) pseudo-element has a matching rule");
|
||||
is(selectors[0], "::highlight(search)", "fetched ::highlight(search) rule");
|
||||
|
||||
selectors = getSelectors(InspectorUtils.getCSSStyleRules(div, "::highlight(whatever)"));
|
||||
selectors = getSelectors(InspectorUtils.getMatchingCSSRules(div, "::highlight(whatever)"));
|
||||
is(selectors.length, 1, "::highlight(whatever) pseudo-element has a matching rule");
|
||||
is(selectors[0], "::highlight(whatever)", "fetched ::highlight(whatever) rule");
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<pre id="log">
|
||||
<script>
|
||||
/**
|
||||
* This test checks that getCSSStyleRules returns correct style set in
|
||||
* This test checks that getMatchingCSSRules returns correct style set in
|
||||
* various cases. To avoid effects from UA sheets, most of the tests use
|
||||
* an element with "unknowntagname".
|
||||
*/
|
||||
|
@ -22,14 +22,14 @@ let iframe = document.getElementById("test");
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function* getStyleRules(elem) {
|
||||
let rules = InspectorUtils.getCSSStyleRules(elem);
|
||||
let rules = InspectorUtils.getMatchingCSSRules(elem);
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
yield rules[i];
|
||||
}
|
||||
}
|
||||
|
||||
// This will check that value of z-index property declarations in the
|
||||
// rules from getCSSStyleRules matches the given content.
|
||||
// rules from getMatchingCSSRules matches the given content.
|
||||
function checkRules(doc, rulesContent, queryStr = "unknowntagname") {
|
||||
let elem = doc.querySelector(queryStr);
|
||||
let rules = [...getStyleRules(elem)];
|
||||
|
@ -52,7 +52,7 @@ const tests = [
|
|||
checkRules(doc, [1]);
|
||||
let link = doc.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "getCSSStyleRules-2.css";
|
||||
link.href = "getMatchingCSSRules-2.css";
|
||||
let load = new Promise(resolve => { link.onload = resolve; });
|
||||
doc.head.appendChild(link);
|
||||
await load;
|
||||
|
@ -121,7 +121,7 @@ const tests = [
|
|||
checkRules(doc, [3, 5, 4]);
|
||||
|
||||
info("Inserting import rule");
|
||||
sheet.insertRule("@import url(getCSSStyleRules-2.css);", 0);
|
||||
sheet.insertRule("@import url(getMatchingCSSRules-2.css);", 0);
|
||||
// There is no notification we can get when the associated style
|
||||
// sheet gets loaded, so we have to query it.
|
||||
while (true) {
|
||||
|
@ -189,7 +189,7 @@ add_task(async function runTests() {
|
|||
if (!test.base) {
|
||||
test.base = "default";
|
||||
}
|
||||
iframe.src = `file_getCSSStyleRules-${test.base}.html`;
|
||||
iframe.src = `file_getMatchingCSSRules-${test.base}.html`;
|
||||
await new Promise(resolve => { iframe.onload = resolve; });
|
||||
try {
|
||||
await test.run(iframe.contentDocument, iframe.contentWindow);
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test getCSSStyleRules for pseudo elements</title>
|
||||
<title>Test getMatchingCSSRules for pseudo elements</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
|
||||
|
@ -52,12 +52,12 @@ const InspectorUtils = SpecialPowers.InspectorUtils;
|
|||
function checkPseudoStyleForId(id) {
|
||||
let element = document.getElementById(id);
|
||||
|
||||
let beforeRules = InspectorUtils.getCSSStyleRules(element, ":before");
|
||||
let beforeRules = InspectorUtils.getMatchingCSSRules(element, ":before");
|
||||
is (beforeRules.length, 1, "Element " + id + ":before has expected number of rules.");
|
||||
let beforeDecl = beforeRules[0].style;
|
||||
is (beforeDecl.content, '":before"', "Element " + id + ":before has expected style content.");
|
||||
|
||||
let afterRules = InspectorUtils.getCSSStyleRules(element, ":after");
|
||||
let afterRules = InspectorUtils.getMatchingCSSRules(element, ":after");
|
||||
is (afterRules.length, 1, "Element " + id + ":after has expected number of rules.");
|
||||
let afterDecl = afterRules[0].style;
|
||||
is (afterDecl.content, '":after"', "Element " + id + ":after has expected style content.");
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test getCSSStyleRules for pseudo elements</title>
|
||||
<title>Test getMatchingCSSRules for pseudo elements</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
|||
|
||||
function checkElementRules(id, text, property) {
|
||||
const element = document.getElementById(id);
|
||||
let slottedRules = InspectorUtils.getCSSStyleRules(element);
|
||||
let slottedRules = InspectorUtils.getMatchingCSSRules(element);
|
||||
is(slottedRules.length, 1, "Slotted element has expected number of rules.");
|
||||
|
||||
let slottedText = slottedRules[0].cssText;
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>Test for InspectorUtils.getCSSStyleRules for starting style</title>
|
||||
<title>Test for InspectorUtils.getMatchingCSSRules for starting style</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
<style>
|
||||
|
@ -13,9 +13,7 @@
|
|||
opacity: 1;
|
||||
|
||||
@starting-style {
|
||||
& {
|
||||
opacity: 0;
|
||||
}
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,14 +26,7 @@
|
|||
background-color: tomato;
|
||||
|
||||
@starting-style {
|
||||
/*
|
||||
* FIXME(bug 1919853): getCSSStyleRules() doesn't return bare nested
|
||||
* declarations. Once we figure out the right thing to do there,
|
||||
* the wrapping `&{}` can go away.
|
||||
*/
|
||||
& {
|
||||
background-color: gold;
|
||||
}
|
||||
background-color: gold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -44,7 +35,7 @@
|
|||
<tagnametwo></tagnametwo>
|
||||
<script>
|
||||
/**
|
||||
* This test checks that InspectorUtils.getCSSStyleRules setting
|
||||
* This test checks that InspectorUtils.getMatchingCSSRules setting
|
||||
* withStartingStyle:true returns correct style set in various cases.
|
||||
* To avoid effects from UA sheets, we use an element with "unknowntagname".
|
||||
*/
|
||||
|
@ -56,7 +47,7 @@ add_task(async function testBasic() {
|
|||
|
||||
const styleSheet = document.styleSheets[1];
|
||||
const el = document.querySelector("tagname");
|
||||
let rules = InspectorUtils.getCSSStyleRules(el, "", false, true);
|
||||
let rules = InspectorUtils.getMatchingCSSRules(el, "", false, true);
|
||||
is(rules.length, 3, "Expected rules");
|
||||
|
||||
is(
|
||||
|
@ -81,7 +72,7 @@ add_task(async function testBasic() {
|
|||
"Check that starting style rules are not returned when withStartingStyle " +
|
||||
"param is false"
|
||||
);
|
||||
rules = InspectorUtils.getCSSStyleRules(el, "", false);
|
||||
rules = InspectorUtils.getMatchingCSSRules(el, "", false);
|
||||
is(rules.length, 1, "Expected rules");
|
||||
|
||||
is(
|
||||
|
@ -97,7 +88,7 @@ add_task(async function testCombinator() {
|
|||
|
||||
const styleSheet = document.styleSheets[1];
|
||||
const el = document.querySelector("tagnametwo");
|
||||
const rules = InspectorUtils.getCSSStyleRules(el, "", false, true);
|
||||
const rules = InspectorUtils.getMatchingCSSRules(el, "", false, true);
|
||||
is(rules.length, 3, "Got expected rules");
|
||||
|
||||
is(
|
|
@ -33,9 +33,9 @@
|
|||
);
|
||||
|
||||
is(
|
||||
InspectorUtils.getCSSStyleRules(spanEl).length,
|
||||
InspectorUtils.getMatchingCSSRules(spanEl).length,
|
||||
2,
|
||||
"getCSSStyleRules returned 2 rules for .mySpan"
|
||||
"getMatchingCSSRules returned 2 rules for .mySpan"
|
||||
);
|
||||
|
||||
info("Modify stylesheet using InspectorUtils.parseStyleSheet");
|
||||
|
@ -66,14 +66,14 @@
|
|||
"rgb(0, 0, 0)",
|
||||
"the color of the span element was properly updated"
|
||||
);
|
||||
const rules = InspectorUtils.getCSSStyleRules(spanEl);
|
||||
const rules = InspectorUtils.getMatchingCSSRules(spanEl);
|
||||
is(
|
||||
rules.length,
|
||||
2,
|
||||
"getCSSStyleRules still returned 2 rules for .mySpan after stylesheet was updated"
|
||||
"getMatchingCSSRules still returned 2 rules for .mySpan after stylesheet was updated"
|
||||
);
|
||||
is(rules[1].style.color, "black", "rule was properly updated");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -50,7 +50,7 @@ const InspectorUtils = SpecialPowers.InspectorUtils;
|
|||
function do_test() {
|
||||
var element = document.querySelector("#foo");
|
||||
|
||||
var elementRules = InspectorUtils.getCSSStyleRules(element);
|
||||
var elementRules = InspectorUtils.getMatchingCSSRules(element);
|
||||
|
||||
var multiSelectorRule = elementRules[2];
|
||||
is(multiSelectorRule.selectorText, `#foo, #bar, #foo::before`, "Got expected multi-selector rule");
|
||||
|
@ -77,7 +77,7 @@ function do_test() {
|
|||
SimpleTest.finish();
|
||||
|
||||
function checkPseudo(pseudo) {
|
||||
var rules = InspectorUtils.getCSSStyleRules(element, pseudo);
|
||||
var rules = InspectorUtils.getMatchingCSSRules(element, pseudo);
|
||||
var rule = rules[rules.length - 1];
|
||||
|
||||
is (rule.selectorMatchesElement(0, element), false,
|
||||
|
|
|
@ -116,6 +116,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CSSNestedDeclarations,
|
|||
// Keep this in sync with IsCCLeaf.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
StyleLockedDeclarationBlock* CSSNestedDeclarations::RawStyle() const {
|
||||
return mDecls.mDecls->Raw();
|
||||
}
|
||||
|
||||
bool CSSNestedDeclarations::IsCCLeaf() const {
|
||||
if (!css::Rule::IsCCLeaf()) {
|
||||
return false;
|
||||
|
|
|
@ -69,6 +69,7 @@ class CSSNestedDeclarations final : public css::Rule {
|
|||
nsICSSDeclaration* Style() { return &mDecls; }
|
||||
|
||||
StyleLockedNestedDeclarationsRule* Raw() const { return mRawRule.get(); }
|
||||
StyleLockedDeclarationBlock* RawStyle() const;
|
||||
void SetRawAfterClone(RefPtr<StyleLockedNestedDeclarationsRule>);
|
||||
|
||||
// Methods of mozilla::css::Rule
|
||||
|
|
|
@ -181,6 +181,10 @@ void CSSStyleRule::GetCssText(nsACString& aCssText) const {
|
|||
|
||||
/* CSSStyleRule implementation */
|
||||
|
||||
StyleLockedDeclarationBlock* CSSStyleRule::RawStyle() const {
|
||||
return mDecls.mDecls->Raw();
|
||||
}
|
||||
|
||||
void CSSStyleRule::GetSelectorText(nsACString& aSelectorText) {
|
||||
Servo_StyleRule_GetSelectorText(mRawRule, &aSelectorText);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "mozilla/css/GroupRule.h"
|
||||
#include "mozilla/ServoBindingTypes.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
#include "nsDOMCSSDeclaration.h"
|
||||
|
||||
|
@ -54,7 +53,7 @@ class CSSStyleRuleDeclaration final : public nsDOMCSSDeclaration {
|
|||
RefPtr<DeclarationBlock> mDecls;
|
||||
};
|
||||
|
||||
class CSSStyleRule final : public css::GroupRule, public SupportsWeakPtr {
|
||||
class CSSStyleRule final : public css::GroupRule {
|
||||
public:
|
||||
CSSStyleRule(already_AddRefed<StyleLockedStyleRule> aRawRule,
|
||||
StyleSheet* aSheet, css::Rule* aParentRule, uint32_t aLine,
|
||||
|
@ -84,6 +83,7 @@ class CSSStyleRule final : public css::GroupRule, public SupportsWeakPtr {
|
|||
nsICSSDeclaration* Style() { return &mDecls; }
|
||||
|
||||
StyleLockedStyleRule* Raw() const { return mRawRule; }
|
||||
StyleLockedDeclarationBlock* RawStyle() const;
|
||||
void SetRawAfterClone(RefPtr<StyleLockedStyleRule>);
|
||||
already_AddRefed<StyleLockedCssRules> GetOrCreateRawRules() final;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/dom/DocumentOrShadowRoot.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
|
@ -26,7 +27,7 @@ enum class StyleCssRuleType : uint8_t;
|
|||
namespace css {
|
||||
class GroupRule;
|
||||
|
||||
class Rule : public nsISupports, public nsWrapperCache {
|
||||
class Rule : public nsISupports, public nsWrapperCache, public SupportsWeakPtr {
|
||||
protected:
|
||||
Rule(StyleSheet* aSheet, Rule* aParentRule, uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
xhr.open('G', '', false)
|
||||
xhr.send()
|
||||
|
||||
SpecialPowers.InspectorUtils.getCSSStyleRules(document.documentElement)
|
||||
SpecialPowers.InspectorUtils.getMatchingCSSRules(document.documentElement)
|
||||
}
|
||||
|
||||
window.addEventListener('load', start)
|
||||
|
|
|
@ -372,7 +372,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// allocation
|
||||
#[inline]
|
||||
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
|
||||
this.ptr() as *const () == other.ptr() as *const ()
|
||||
this.raw_ptr() == other.raw_ptr()
|
||||
}
|
||||
|
||||
fn ptr(&self) -> *mut ArcInner<T> {
|
||||
|
@ -380,8 +380,8 @@ impl<T: ?Sized> Arc<T> {
|
|||
}
|
||||
|
||||
/// Returns a raw ptr to the underlying allocation.
|
||||
pub fn raw_ptr(&self) -> *const c_void {
|
||||
self.p.as_ptr() as *const _
|
||||
pub fn raw_ptr(&self) -> ptr::NonNull<()> {
|
||||
self.p.cast()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -145,14 +145,14 @@ trait PrivateMatchMethods: TElement {
|
|||
result |= Self::replace_single_rule_node(
|
||||
context.shared,
|
||||
CascadeLevel::same_tree_author_normal(),
|
||||
LayerOrder::root(),
|
||||
LayerOrder::style_attribute(),
|
||||
style_attribute,
|
||||
primary_rules,
|
||||
);
|
||||
result |= Self::replace_single_rule_node(
|
||||
context.shared,
|
||||
CascadeLevel::same_tree_author_important(),
|
||||
LayerOrder::root(),
|
||||
LayerOrder::style_attribute(),
|
||||
style_attribute,
|
||||
primary_rules,
|
||||
);
|
||||
|
|
|
@ -127,30 +127,33 @@ impl RuleCache {
|
|||
/// Walk the rule tree and return a rule node for using as the key
|
||||
/// for rule cache.
|
||||
///
|
||||
/// It currently skips a rule node when it is neither from a style
|
||||
/// rule, nor containing any declaration of reset property. We don't
|
||||
/// skip style rule so that we don't need to walk a long way in the
|
||||
/// worst case. Skipping declarations rule nodes should be enough
|
||||
/// to address common cases that rule cache would fail to share
|
||||
/// when using the rule node directly, like preshint, style attrs,
|
||||
/// and animations.
|
||||
/// It currently skips animation / style attribute / preshint rules when they don't contain any
|
||||
/// declaration of a reset property. We don't skip other levels because walking the whole
|
||||
/// parent chain can be expensive.
|
||||
///
|
||||
/// TODO(emilio): Measure this, this was not super-well measured for performance (this was done
|
||||
/// for memory in bug 1427681)... Walking the rule tree might be worth it if we hit the cache
|
||||
/// enough?
|
||||
fn get_rule_node_for_cache<'r>(
|
||||
guards: &StylesheetGuards,
|
||||
mut rule_node: Option<&'r StrongRuleNode>,
|
||||
) -> Option<&'r StrongRuleNode> {
|
||||
use crate::rule_tree::CascadeLevel;
|
||||
while let Some(node) = rule_node {
|
||||
match node.style_source() {
|
||||
Some(s) => match s.as_declarations() {
|
||||
Some(decls) => {
|
||||
let cascade_level = node.cascade_level();
|
||||
let decls = decls.read_with(cascade_level.guard(guards));
|
||||
if decls.contains_any_reset() {
|
||||
break;
|
||||
}
|
||||
},
|
||||
None => break,
|
||||
},
|
||||
None => {},
|
||||
let priority = node.cascade_priority();
|
||||
let cascade_level = priority.cascade_level();
|
||||
let should_try_to_skip =
|
||||
cascade_level.is_animation() ||
|
||||
matches!(cascade_level, CascadeLevel::PresHints) ||
|
||||
priority.layer_order().is_style_attribute_layer();
|
||||
if !should_try_to_skip {
|
||||
break;
|
||||
}
|
||||
if let Some(source) = node.style_source() {
|
||||
let decls = source.get().read_with(cascade_level.guard(guards));
|
||||
if decls.contains_any_reset() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rule_node = node.parent();
|
||||
}
|
||||
|
|
|
@ -214,24 +214,24 @@ impl RuleTree {
|
|||
current = current.parent().unwrap().clone();
|
||||
}
|
||||
|
||||
let cascade_priority = CascadePriority::new(level, layer_order);
|
||||
|
||||
// Then remove the one at the level we want to replace, if any.
|
||||
//
|
||||
// NOTE: Here we assume that only one rule can be at the level we're
|
||||
// replacing.
|
||||
// NOTE: Here we assume that only one rule can be at the level + priority we're replacing,
|
||||
// which holds because we only use this for HTML style attribute, animations and transition
|
||||
// rules.
|
||||
//
|
||||
// This is certainly true for HTML style attribute rules, animations and
|
||||
// transitions, but could not be so for SMIL animations, which we'd need
|
||||
// to special-case (isn't hard, it's just about removing the `if` and
|
||||
// special cases, and replacing them for a `while` loop, avoiding the
|
||||
// optimizations).
|
||||
if current.cascade_priority().cascade_level() == level {
|
||||
// This is certainly true for HTML style attribute rules, animations, transitions, and
|
||||
// SMIL.
|
||||
if current.cascade_priority() == cascade_priority {
|
||||
*important_rules_changed |= level.is_important();
|
||||
|
||||
let current_decls = current.style_source().unwrap().as_declarations();
|
||||
let current_decls = current.style_source().unwrap().get();
|
||||
|
||||
// If the only rule at the level we're replacing is exactly the
|
||||
// same as `pdb`, we're done, and `path` is still valid.
|
||||
if let (Some(ref pdb), Some(ref current_decls)) = (pdb, current_decls) {
|
||||
if let Some(ref pdb) = pdb {
|
||||
// If the only rule at the level we're replacing is exactly the
|
||||
// same as `pdb`, we're done, and `path` is still valid.
|
||||
//
|
||||
|
@ -241,30 +241,27 @@ impl RuleTree {
|
|||
// also equally valid. This is less likely, and would require an
|
||||
// in-place mutation of the source, which is, at best, fiddly,
|
||||
// so let's skip it for now.
|
||||
let is_here_already = ArcBorrow::ptr_eq(pdb, current_decls);
|
||||
let is_here_already = ArcBorrow::ptr_eq(pdb, ¤t_decls.borrow_arc());
|
||||
if is_here_already {
|
||||
debug!("Picking the fast path in rule replacement");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
if current_decls.is_some() {
|
||||
current = current.parent().unwrap().clone();
|
||||
}
|
||||
current = current.parent().unwrap().clone();
|
||||
}
|
||||
|
||||
// Insert the rule if it's relevant at this level in the cascade.
|
||||
//
|
||||
// These optimizations are likely to be important, because the levels
|
||||
// where replacements apply (style and animations) tend to trigger
|
||||
// pretty bad styling cases already.
|
||||
// These optimizations are likely to be important, because the levels where replacements
|
||||
// apply (style and animations) tend to trigger pretty bad styling cases already.
|
||||
if let Some(pdb) = pdb {
|
||||
if level.is_important() {
|
||||
if pdb.read_with(level.guard(guards)).any_important() {
|
||||
current = current.ensure_child(
|
||||
self.root(),
|
||||
StyleSource::from_declarations(pdb.clone_arc()),
|
||||
CascadePriority::new(level, layer_order),
|
||||
cascade_priority,
|
||||
);
|
||||
*important_rules_changed = true;
|
||||
}
|
||||
|
@ -273,7 +270,7 @@ impl RuleTree {
|
|||
current = current.ensure_child(
|
||||
self.root(),
|
||||
StyleSource::from_declarations(pdb.clone_arc()),
|
||||
CascadePriority::new(level, layer_order),
|
||||
cascade_priority,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,49 +6,38 @@
|
|||
|
||||
use crate::properties::PropertyDeclarationBlock;
|
||||
use crate::shared_lock::{Locked, SharedRwLockReadGuard};
|
||||
use crate::stylesheets::StyleRule;
|
||||
use servo_arc::{Arc, ArcBorrow, ArcUnion, ArcUnionBorrow};
|
||||
use servo_arc::Arc;
|
||||
use std::io::Write;
|
||||
use std::ptr;
|
||||
|
||||
/// A style source for the rule node. It can either be a CSS style rule or a
|
||||
/// declaration block.
|
||||
/// A style source for the rule node. It is a declaration block that may come from either a style
|
||||
/// rule or a standalone block like animations / transitions / smil / preshints / style attr...
|
||||
///
|
||||
/// Note that, even though the declaration block from inside the style rule
|
||||
/// could be enough to implement the rule tree, keeping the whole rule provides
|
||||
/// more debuggability, and also the ability of show those selectors to
|
||||
/// devtools.
|
||||
/// Keeping the style rule around would provide more debugability, but also causes more
|
||||
/// pointer-chasing in the common code-path, which is undesired. If needed, we could keep it around
|
||||
/// in debug builds or something along those lines.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StyleSource(ArcUnion<Locked<StyleRule>, Locked<PropertyDeclarationBlock>>);
|
||||
pub struct StyleSource(Arc<Locked<PropertyDeclarationBlock>>);
|
||||
|
||||
impl PartialEq for StyleSource {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
ArcUnion::ptr_eq(&self.0, &other.0)
|
||||
Arc::ptr_eq(&self.0, &other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl StyleSource {
|
||||
/// Creates a StyleSource from a StyleRule.
|
||||
pub fn from_rule(rule: Arc<Locked<StyleRule>>) -> Self {
|
||||
StyleSource(ArcUnion::from_first(rule))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn key(&self) -> ptr::NonNull<()> {
|
||||
self.0.ptr()
|
||||
self.0.raw_ptr()
|
||||
}
|
||||
|
||||
/// Creates a StyleSource from a PropertyDeclarationBlock.
|
||||
#[inline]
|
||||
pub fn from_declarations(decls: Arc<Locked<PropertyDeclarationBlock>>) -> Self {
|
||||
StyleSource(ArcUnion::from_second(decls))
|
||||
Self(decls)
|
||||
}
|
||||
|
||||
pub(super) fn dump<W: Write>(&self, guard: &SharedRwLockReadGuard, writer: &mut W) {
|
||||
if let Some(ref rule) = self.0.as_first() {
|
||||
let rule = rule.read_with(guard);
|
||||
let _ = write!(writer, "{:?}", rule.selectors);
|
||||
}
|
||||
|
||||
let _ = write!(writer, " -> {:?}", self.read(guard).declarations());
|
||||
}
|
||||
|
||||
|
@ -56,20 +45,12 @@ impl StyleSource {
|
|||
/// underlying property declaration block.
|
||||
#[inline]
|
||||
pub fn read<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a PropertyDeclarationBlock {
|
||||
let block: &Locked<PropertyDeclarationBlock> = match self.0.borrow() {
|
||||
ArcUnionBorrow::First(ref rule) => &rule.get().read_with(guard).block,
|
||||
ArcUnionBorrow::Second(ref block) => block.get(),
|
||||
};
|
||||
block.read_with(guard)
|
||||
}
|
||||
|
||||
/// Returns the style rule if applicable, otherwise None.
|
||||
pub fn as_rule(&self) -> Option<ArcBorrow<Locked<StyleRule>>> {
|
||||
self.0.as_first()
|
||||
self.0.read_with(guard)
|
||||
}
|
||||
|
||||
/// Returns the declaration block if applicable, otherwise None.
|
||||
pub fn as_declarations(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
|
||||
self.0.as_second()
|
||||
#[inline]
|
||||
pub fn get(&self) -> &Arc<Locked<PropertyDeclarationBlock>> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3239,7 +3239,6 @@ impl CascadeData {
|
|||
|
||||
fn add_styles(
|
||||
&mut self,
|
||||
style_source: StyleSource,
|
||||
selectors: &SelectorList<SelectorImpl>,
|
||||
declarations: &Arc<Locked<PropertyDeclarationBlock>>,
|
||||
ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
|
||||
|
@ -3270,7 +3269,7 @@ impl CascadeData {
|
|||
.expect("Expected precomputed declarations for the UA level")
|
||||
.get_or_insert_with(pseudo, Vec::new)
|
||||
.push(ApplicableDeclarationBlock::new(
|
||||
style_source.clone(),
|
||||
StyleSource::from_declarations(declarations.clone()),
|
||||
self.rules_source_order,
|
||||
CascadeLevel::UANormal,
|
||||
selector.specificity(),
|
||||
|
@ -3294,7 +3293,7 @@ impl CascadeData {
|
|||
let rule = Rule::new(
|
||||
selector,
|
||||
hashes,
|
||||
style_source.clone(),
|
||||
StyleSource::from_declarations(declarations.clone()),
|
||||
self.rules_source_order,
|
||||
containing_rule_state.layer_id,
|
||||
containing_rule_state.container_condition_id,
|
||||
|
@ -3428,7 +3427,6 @@ impl CascadeData {
|
|||
let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
|
||||
let collect_replaced_selectors = has_nested_rules && ancestor_selectors.is_some();
|
||||
self.add_styles(
|
||||
StyleSource::from_rule(locked.clone()),
|
||||
&style_rule.selectors,
|
||||
&style_rule.block,
|
||||
ancestor_selectors,
|
||||
|
@ -3467,7 +3465,6 @@ impl CascadeData {
|
|||
NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
|
||||
};
|
||||
self.add_styles(
|
||||
StyleSource::from_declarations(decls.clone()),
|
||||
selectors,
|
||||
decls,
|
||||
/* ancestor_selectors = */ None,
|
||||
|
|
|
@ -116,13 +116,8 @@ impl<T> ArcSlice<T> {
|
|||
/// Creates a value that can be passed via FFI, and forgets this value
|
||||
/// altogether.
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
pub fn forget(self) -> ForgottenArcSlicePtr<T> {
|
||||
let ret = unsafe {
|
||||
ForgottenArcSlicePtr(NonNull::new_unchecked(
|
||||
self.0.raw_ptr() as *const _ as *mut _
|
||||
))
|
||||
};
|
||||
let ret = ForgottenArcSlicePtr(self.0.raw_ptr().cast());
|
||||
mem::forget(self);
|
||||
ret
|
||||
}
|
||||
|
@ -134,7 +129,7 @@ impl<T> ArcSlice<T> {
|
|||
let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone();
|
||||
let ptr = empty.0.raw_ptr();
|
||||
std::mem::forget(empty);
|
||||
ptr as *mut _
|
||||
ptr.cast().as_ptr()
|
||||
}
|
||||
|
||||
/// Returns whether there's only one reference to this ArcSlice.
|
||||
|
|
|
@ -4471,9 +4471,9 @@ pub extern "C" fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
|
||||
pub extern "C" fn Servo_ComputedValues_GetMatchingDeclarations(
|
||||
values: &ComputedValues,
|
||||
rules: &mut nsTArray<*const LockedStyleRule>,
|
||||
rules: &mut nsTArray<*const LockedDeclarationBlock>,
|
||||
) {
|
||||
let rule_node = match values.rules {
|
||||
Some(ref r) => r,
|
||||
|
@ -4481,11 +4481,6 @@ pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
|
|||
};
|
||||
|
||||
for node in rule_node.self_and_ancestors() {
|
||||
let style_rule = match node.style_source().and_then(|x| x.as_rule()) {
|
||||
Some(rule) => rule,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
// For the rules with any important declaration, we insert them into
|
||||
// rule tree twice, one for normal level and another for important
|
||||
// level. So, we skip the important one to keep the specificity order of
|
||||
|
@ -4494,7 +4489,9 @@ pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
|
|||
continue;
|
||||
}
|
||||
|
||||
rules.push(&*style_rule);
|
||||
let Some(source) = node.style_source() else { continue };
|
||||
|
||||
rules.push(&**source.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4526,20 +4523,13 @@ fn dump_properties_and_rules(cv: &ComputedValues, properties: &LonghandIdSet) {
|
|||
#[cfg(feature = "gecko_debug")]
|
||||
fn dump_rules(cv: &ComputedValues) {
|
||||
println_stderr!(" Rules({:?}):", cv.pseudo());
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let guard = global_style_data.shared_lock.read();
|
||||
if let Some(rules) = cv.rules.as_ref() {
|
||||
for rn in rules.self_and_ancestors() {
|
||||
if rn.importance().important() {
|
||||
continue;
|
||||
}
|
||||
if let Some(d) = rn.style_source().and_then(|s| s.as_declarations()) {
|
||||
println_stderr!(" [DeclarationBlock: {:?}]", d);
|
||||
}
|
||||
if let Some(r) = rn.style_source().and_then(|s| s.as_rule()) {
|
||||
let mut s = nsCString::new();
|
||||
r.read_with(&guard).to_css(&guard, &mut s).unwrap();
|
||||
println_stderr!(" {}", s);
|
||||
if let Some(d) = rn.style_source() {
|
||||
println_stderr!(" {:?}", d.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче