forked from mirrors/gecko-dev
Bug 1893409 - Make getCSSStyleRules() work for starting style as well. r=layout-reviewers,firefox-style-system-reviewers,nchevobbe,emilio
Update the API, `nspectorUtils.getCSSStyleRules`. Add one extra argument so the user can choose whether we should return the starting style, for a given element, at this moment. Differential Revision: https://phabricator.services.mozilla.com/D209318
This commit is contained in:
parent
300659b5ee
commit
6203ad286b
10 changed files with 202 additions and 29 deletions
|
|
@ -17,7 +17,8 @@ namespace InspectorUtils {
|
|||
sequence<CSSStyleRule> getCSSStyleRules(
|
||||
Element element,
|
||||
optional [LegacyNullToEmptyString] DOMString pseudo = "",
|
||||
optional boolean relevantLinkVisited = false);
|
||||
optional boolean relevantLinkVisited = false,
|
||||
optional boolean withStartingStyle = false);
|
||||
unsigned long getRuleLine(CSSRule rule);
|
||||
unsigned long getRuleColumn(CSSRule rule);
|
||||
unsigned long getRelativeRuleLine(CSSRule rule);
|
||||
|
|
|
|||
|
|
@ -229,41 +229,37 @@ void InspectorUtils::GetChildrenForNode(nsINode& aNode,
|
|||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void InspectorUtils::GetCSSStyleRules(GlobalObject& aGlobalObject,
|
||||
Element& aElement,
|
||||
const nsAString& aPseudo,
|
||||
bool aIncludeVisitedStyle,
|
||||
nsTArray<RefPtr<CSSStyleRule>>& aResult) {
|
||||
auto [type, functionalPseudoParameter] =
|
||||
nsCSSPseudoElements::ParsePseudoElement(aPseudo,
|
||||
CSSEnabledState::ForAllContent);
|
||||
if (!type) {
|
||||
return;
|
||||
static already_AddRefed<const ComputedStyle> GetStartingStyle(
|
||||
Element& aElement) {
|
||||
// If this element is unstyled, or it doesn't have matched rules in
|
||||
// @starting-style, we return.
|
||||
if (!Servo_Element_MayHaveStartingStyle(&aElement)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<const ComputedStyle> computedStyle = GetCleanComputedStyleForElement(
|
||||
&aElement, *type, functionalPseudoParameter);
|
||||
if (!computedStyle) {
|
||||
// This can fail for elements that are not in the document or
|
||||
// if the document they're in doesn't have a presshell. Bail out.
|
||||
return;
|
||||
const PresShell* presShell = aElement.OwnerDoc()->GetPresShell();
|
||||
if (!presShell) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aIncludeVisitedStyle) {
|
||||
if (auto* styleIfVisited = computedStyle->GetStyleIfVisited()) {
|
||||
computedStyle = styleIfVisited;
|
||||
}
|
||||
ServoStyleSet* styleSet = presShell->StyleSet();
|
||||
if (!styleSet) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Document* doc = aElement.OwnerDoc();
|
||||
PresShell* presShell = doc->GetPresShell();
|
||||
return styleSet->ResolveStartingStyle(aElement);
|
||||
}
|
||||
|
||||
static void GetCSSStyleRulesFromComputedValue(
|
||||
Element& aElement, const ComputedStyle* aComputedStyle,
|
||||
nsTArray<RefPtr<CSSStyleRule>>& aResult) {
|
||||
const PresShell* presShell = aElement.OwnerDoc()->GetPresShell();
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoTArray<const StyleLockedStyleRule*, 8> rawRuleList;
|
||||
Servo_ComputedValues_GetStyleRuleList(computedStyle, &rawRuleList);
|
||||
Servo_ComputedValues_GetStyleRuleList(aComputedStyle, &rawRuleList);
|
||||
|
||||
AutoTArray<ServoStyleRuleMap*, 8> maps;
|
||||
{
|
||||
|
|
@ -313,7 +309,7 @@ void InspectorUtils::GetCSSStyleRules(GlobalObject& aGlobalObject,
|
|||
#ifdef DEBUG
|
||||
aElement.Dump();
|
||||
printf_stderr("\n\n----\n\n");
|
||||
computedStyle->DumpMatchedRules();
|
||||
aComputedStyle->DumpMatchedRules();
|
||||
nsAutoCString str;
|
||||
Servo_StyleRule_Debug(rawRule, &str);
|
||||
printf_stderr("\n\n----\n\n");
|
||||
|
|
@ -327,6 +323,48 @@ void InspectorUtils::GetCSSStyleRules(GlobalObject& aGlobalObject,
|
|||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void InspectorUtils::GetCSSStyleRules(GlobalObject& aGlobalObject,
|
||||
Element& aElement,
|
||||
const nsAString& aPseudo,
|
||||
bool aIncludeVisitedStyle,
|
||||
bool aWithStartingStyle,
|
||||
nsTArray<RefPtr<CSSStyleRule>>& aResult) {
|
||||
auto [type, functionalPseudoParameter] =
|
||||
nsCSSPseudoElements::ParsePseudoElement(aPseudo,
|
||||
CSSEnabledState::ForAllContent);
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<const ComputedStyle> computedStyle;
|
||||
if (aWithStartingStyle) {
|
||||
computedStyle = GetStartingStyle(aElement);
|
||||
}
|
||||
|
||||
// Note: GetStartingStyle() return nullptr if this element doesn't have rules
|
||||
// inside @starting-style. For this case, we would like to return the primay
|
||||
// rules of this element.
|
||||
if (!computedStyle) {
|
||||
computedStyle = GetCleanComputedStyleForElement(&aElement, *type,
|
||||
functionalPseudoParameter);
|
||||
}
|
||||
|
||||
if (!computedStyle) {
|
||||
// This can fail for elements that are not in the document or
|
||||
// if the document they're in doesn't have a presshell. Bail out.
|
||||
return;
|
||||
}
|
||||
|
||||
if (aIncludeVisitedStyle) {
|
||||
if (const auto* styleIfVisited = computedStyle->GetStyleIfVisited()) {
|
||||
computedStyle = styleIfVisited;
|
||||
}
|
||||
}
|
||||
|
||||
GetCSSStyleRulesFromComputedValue(aElement, computedStyle, aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
uint32_t InspectorUtils::GetRuleLine(GlobalObject& aGlobal, css::Rule& aRule) {
|
||||
uint32_t line = aRule.GetLineNumber();
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class InspectorUtils {
|
|||
static void GetCSSStyleRules(GlobalObject& aGlobal, Element& aElement,
|
||||
const nsAString& aPseudo,
|
||||
bool aIncludeVisitedStyle,
|
||||
bool aWithStartingStyle,
|
||||
nsTArray<RefPtr<CSSStyleRule>>& aResult);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ prefs = [
|
|||
"layout.css.basic-shape-shape.enabled=true",
|
||||
"layout.css.basic-shape-xywh.enabled=true",
|
||||
"layout.css.properties-and-values.enabled=true",
|
||||
"layout.css.starting-style-at-rules.enabled=true",
|
||||
"layout.css.transition-behavior.enabled=true",
|
||||
"dom.customHighlightAPI.enabled=true",
|
||||
]
|
||||
|
|
@ -56,6 +57,8 @@ support-files = [
|
|||
|
||||
["test_getCSSStyleRules_slotted.html"]
|
||||
|
||||
["test_getCSSStyleRules_starting_style.html"]
|
||||
|
||||
["test_getRegisteredCssHighlights.html"]
|
||||
|
||||
["test_getRegisteredCustomProperties.html"]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>Test for InspectorUtils.getCSSStyleRules for starting style</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
<style>
|
||||
@starting-style {
|
||||
unknowntagname {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
unknowntagname {
|
||||
color: blue;
|
||||
opacity: 1;
|
||||
|
||||
@starting-style {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<pre id="log"></pre>
|
||||
<unknowntagname></unknowntagname>
|
||||
<script>
|
||||
/**
|
||||
* This test checks that InspectorUtils.getCSSStyleRules setting
|
||||
* withStartingStyle:true returns correct style set in various cases.
|
||||
* To avoid effects from UA sheets, we use an element with "unknowntagname".
|
||||
*/
|
||||
|
||||
const InspectorUtils = SpecialPowers.InspectorUtils;
|
||||
|
||||
add_task(async function runTests() {
|
||||
const styleSheet = document.styleSheets[1];
|
||||
const el = document.querySelector("unknowntagname");
|
||||
let rules = InspectorUtils.getCSSStyleRules(el, "", false, true);
|
||||
is(rules.length, 3, "Expected rules");
|
||||
|
||||
is(
|
||||
rules[0].cssText,
|
||||
styleSheet.cssRules[0].cssRules[0].cssText,
|
||||
"first returned rule is the one in the top-level starting-style rule"
|
||||
);
|
||||
|
||||
is(
|
||||
rules[1].cssText,
|
||||
styleSheet.cssRules[1].cssText,
|
||||
"first returned rule is top-level unknowntagname rule"
|
||||
);
|
||||
|
||||
is(
|
||||
rules[2].cssText,
|
||||
styleSheet.cssRules[1].cssRules[0].cssRules[0].cssText,
|
||||
"second returned rule is the one in the top-level starting-style rule"
|
||||
);
|
||||
|
||||
info(
|
||||
"Check that starting style rules are not returned when withStartingStyle " +
|
||||
"param is false"
|
||||
);
|
||||
rules = InspectorUtils.getCSSStyleRules(el, "", false);
|
||||
is(rules.length, 1, "Expected rules");
|
||||
|
||||
is(
|
||||
rules[0].cssText,
|
||||
styleSheet.cssRules[1].cssText,
|
||||
"Only returned rule is top-level unknowntagname rule"
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
|
@ -598,6 +598,18 @@ already_AddRefed<ComputedStyle> ServoStyleSet::ResolveXULTreePseudoStyle(
|
|||
.Consume();
|
||||
}
|
||||
|
||||
already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStartingStyle(
|
||||
dom::Element& aElement) {
|
||||
nsPresContext* pc = GetPresContext();
|
||||
if (!pc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return Servo_ResolveStartingStyle(
|
||||
&aElement, &pc->RestyleManager()->Snapshots(), mRawData.get())
|
||||
.Consume();
|
||||
}
|
||||
|
||||
// manage the set of style sheets in the style set
|
||||
void ServoStyleSet::AppendStyleSheet(StyleSheet& aSheet) {
|
||||
MOZ_ASSERT(aSheet.IsApplicable());
|
||||
|
|
|
|||
|
|
@ -257,6 +257,10 @@ class ServoStyleSet {
|
|||
dom::Element* aParentElement, nsCSSAnonBoxPseudoStaticAtom* aPseudoTag,
|
||||
ComputedStyle* aParentStyle, const AtomArray& aInputWord);
|
||||
|
||||
// Try to resolve the staring style for a given element. Please call this
|
||||
// function after checking if it may have rules inside @starting-style.
|
||||
already_AddRefed<ComputedStyle> ResolveStartingStyle(dom::Element& aElement);
|
||||
|
||||
size_t SheetCount(Origin) const;
|
||||
StyleSheet* SheetAt(Origin, size_t aIndex) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ trait PrivateMatchMethods: TElement {
|
|||
PseudoElementResolution::IfApplicable,
|
||||
);
|
||||
|
||||
let starting_style = resolver.resolve_starting_style();
|
||||
let starting_style = resolver.resolve_starting_style().style;
|
||||
if starting_style.style().clone_display().is_none() {
|
||||
return None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -629,7 +629,7 @@ where
|
|||
}
|
||||
|
||||
/// Resolve the starting style.
|
||||
pub fn resolve_starting_style(&mut self) -> ResolvedStyle {
|
||||
pub fn resolve_starting_style(&mut self) -> PrimaryStyle {
|
||||
// Compute after-change style for the parent and the layout parent.
|
||||
// Per spec, starting style inherits from the parent’s after-change style just like
|
||||
// after-change style does.
|
||||
|
|
@ -665,7 +665,6 @@ where
|
|||
layout_parent_values,
|
||||
IncludeStartingStyle::Yes,
|
||||
)
|
||||
.style
|
||||
}
|
||||
|
||||
/// If there is no transition rule in the ComputedValues, it returns None.
|
||||
|
|
|
|||
|
|
@ -1555,6 +1555,17 @@ pub extern "C" fn Servo_Element_IsPrimaryStyleReusedViaRuleNode(element: &RawGec
|
|||
.contains(data::ElementDataFlags::PRIMARY_STYLE_REUSED_VIA_RULE_NODE)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_Element_MayHaveStartingStyle(element: &RawGeckoElement) -> bool {
|
||||
let element = GeckoElement(element);
|
||||
let data = match element.borrow_data() {
|
||||
Some(d) => d,
|
||||
None => return false,
|
||||
};
|
||||
data.flags
|
||||
.contains(data::ElementDataFlags::MAY_HAVE_STARTING_STYLE)
|
||||
}
|
||||
|
||||
fn mode_to_origin(mode: SheetParsingMode) -> Origin {
|
||||
match mode {
|
||||
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
|
||||
|
|
@ -6094,6 +6105,42 @@ pub extern "C" fn Servo_ResolveStyleLazily(
|
|||
.into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ResolveStartingStyle(
|
||||
element: &RawGeckoElement,
|
||||
snapshots: *const ServoElementSnapshotTable,
|
||||
raw_data: &PerDocumentStyleData,
|
||||
) -> Strong<ComputedValues> {
|
||||
use style::style_resolver::{PseudoElementResolution, StyleResolverForElement};
|
||||
|
||||
let doc_data = raw_data.borrow();
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let guard = global_style_data.shared_lock.read();
|
||||
let shared = create_shared_context(
|
||||
&global_style_data,
|
||||
&guard,
|
||||
&doc_data.stylist,
|
||||
TraversalFlags::empty(),
|
||||
unsafe { &*snapshots },
|
||||
);
|
||||
let mut tlc = ThreadLocalStyleContext::new();
|
||||
let mut context = StyleContext {
|
||||
shared: &shared,
|
||||
thread_local: &mut tlc,
|
||||
};
|
||||
|
||||
let element = GeckoElement(element);
|
||||
let mut resolver = StyleResolverForElement::new(
|
||||
element,
|
||||
&mut context,
|
||||
RuleInclusion::All,
|
||||
PseudoElementResolution::IfApplicable,
|
||||
);
|
||||
|
||||
let starting_style = resolver.resolve_starting_style();
|
||||
starting_style.style.0.into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ReparentStyle(
|
||||
style_to_reparent: &ComputedValues,
|
||||
|
|
|
|||
Loading…
Reference in a new issue