зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1892192 - [devtools] Display @starting-style rules in Rules view. r=devtools-reviewers,bomsy.
This takes care of displaying `@starting-style` rules in the Rules view. A test is added to cover this, as well as a test case to make sure those starting style rules are not impacting the computed panel. Depends on D210363 Differential Revision: https://phabricator.services.mozilla.com/D209329
This commit is contained in:
Родитель
e76d75367b
Коммит
5f5e0ad8a3
|
@ -7,6 +7,7 @@
|
||||||
const TEST_URI = URL_ROOT + "doc_matched_selectors.html";
|
const TEST_URI = URL_ROOT + "doc_matched_selectors.html";
|
||||||
|
|
||||||
add_task(async function () {
|
add_task(async function () {
|
||||||
|
await pushPref("layout.css.starting-style-at-rules.enabled", true);
|
||||||
await addTab(TEST_URI);
|
await addTab(TEST_URI);
|
||||||
const { inspector, view } = await openComputedView();
|
const { inspector, view } = await openComputedView();
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,11 @@
|
||||||
min-width: 10px;
|
min-width: 10px;
|
||||||
min-height: 10px;
|
min-height: 10px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
|
/* starting-style rules should be ignored by the computed view */
|
||||||
|
@starting-style {
|
||||||
|
background-color: honeydew;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -72,6 +72,8 @@ skip-if = ["verify && debug && os == 'win'"]
|
||||||
|
|
||||||
["browser_rules_at_scope.js"]
|
["browser_rules_at_scope.js"]
|
||||||
|
|
||||||
|
["browser_rules_at_starting-style.js"]
|
||||||
|
|
||||||
["browser_rules_authored.js"]
|
["browser_rules_authored.js"]
|
||||||
|
|
||||||
["browser_rules_authored_color.js"]
|
["browser_rules_authored_color.js"]
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test that the rule-view properly handles @starting-style rules.
|
||||||
|
|
||||||
|
const TEST_URI = `
|
||||||
|
<style>
|
||||||
|
h1, [data-test="top-level"] {
|
||||||
|
color: tomato;
|
||||||
|
transition: all 1s;
|
||||||
|
|
||||||
|
@starting-style {
|
||||||
|
color: gold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@starting-style {
|
||||||
|
body, [data-test="in-starting-style"] {
|
||||||
|
color: navy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer {
|
||||||
|
body, [data-test="in-starting-style-layer"] {
|
||||||
|
color: hotpink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, [data-test="in-starting-style"] {
|
||||||
|
background-color: salmon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<h1>Hello @starting-style!</h1>`;
|
||||||
|
|
||||||
|
add_task(async function () {
|
||||||
|
await pushPref("layout.css.starting-style-at-rules.enabled", true);
|
||||||
|
await addTab(
|
||||||
|
"https://example.com/document-builder.sjs?html=" +
|
||||||
|
encodeURIComponent(TEST_URI)
|
||||||
|
);
|
||||||
|
const { inspector, view } = await openRuleView();
|
||||||
|
await assertRules("body", [
|
||||||
|
{ selector: `element`, ancestorRulesData: null },
|
||||||
|
{
|
||||||
|
selector: `body, [data-test="in-starting-style"]`,
|
||||||
|
ancestorRulesData: ["@starting-style {"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: `body, [data-test="in-starting-style-layer"]`,
|
||||||
|
ancestorRulesData: ["@starting-style {", " @layer {"],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
await assertRules("h1", [
|
||||||
|
{ selector: `element`, ancestorRulesData: null },
|
||||||
|
{
|
||||||
|
selector: `&`,
|
||||||
|
ancestorRulesData: [
|
||||||
|
`h1, [data-test="top-level"] {`,
|
||||||
|
" @starting-style {",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: `h1, [data-test="in-starting-style"]`,
|
||||||
|
ancestorRulesData: ["@starting-style {"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: `h1, [data-test="top-level"]`,
|
||||||
|
ancestorRulesData: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// TODO: Check overridden and "transitioned" properties
|
||||||
|
|
||||||
|
async function assertRules(nodeSelector, expectedRules) {
|
||||||
|
await selectNode(nodeSelector, inspector);
|
||||||
|
const rulesInView = Array.from(
|
||||||
|
view.element.querySelectorAll(".ruleview-rule")
|
||||||
|
);
|
||||||
|
is(
|
||||||
|
rulesInView.length,
|
||||||
|
expectedRules.length,
|
||||||
|
`[${nodeSelector}] All expected rules are displayed`
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let i = 0; i < expectedRules.length; i++) {
|
||||||
|
const expectedRule = expectedRules[i];
|
||||||
|
info(`[${nodeSelector}] Checking rule #${i}: ${expectedRule.selector}`);
|
||||||
|
|
||||||
|
const selector = rulesInView[i].querySelector(
|
||||||
|
".ruleview-selectors-container"
|
||||||
|
)?.innerText;
|
||||||
|
|
||||||
|
is(
|
||||||
|
selector,
|
||||||
|
expectedRule.selector,
|
||||||
|
`[${nodeSelector}] Expected selector for rule #${i}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const isInherited = rulesInView[i].matches(
|
||||||
|
".ruleview-header-inherited + .ruleview-rule"
|
||||||
|
);
|
||||||
|
if (expectedRule.inherited) {
|
||||||
|
ok(isInherited, `[${nodeSelector}] rule #${i} is inherited`);
|
||||||
|
} else {
|
||||||
|
ok(!isInherited, `[${nodeSelector}] rule #${i} is not inherited`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expectedRule.ancestorRulesData == null) {
|
||||||
|
is(
|
||||||
|
getRuleViewAncestorRulesDataElementByIndex(view, i),
|
||||||
|
null,
|
||||||
|
`[${nodeSelector}] No ancestor rules data displayed for ${selector}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
is(
|
||||||
|
getRuleViewAncestorRulesDataTextByIndex(view, i),
|
||||||
|
expectedRule.ancestorRulesData.join("\n"),
|
||||||
|
`[${nodeSelector}] Expected ancestor rules data displayed for ${selector}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -263,6 +263,8 @@ RuleEditor.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectorContainer.append(this.doc.createTextNode(text));
|
selectorContainer.append(this.doc.createTextNode(text));
|
||||||
|
} else if (ancestorData.type == "starting-style") {
|
||||||
|
selectorContainer.append(this.doc.createTextNode(`@starting-style`));
|
||||||
} else if (ancestorData.selectors) {
|
} else if (ancestorData.selectors) {
|
||||||
ancestorData.selectors.forEach((selector, i) => {
|
ancestorData.selectors.forEach((selector, i) => {
|
||||||
if (i !== 0) {
|
if (i !== 0) {
|
||||||
|
|
|
@ -751,7 +751,9 @@ class PageStyleActor extends Actor {
|
||||||
const domRules = InspectorUtils.getCSSStyleRules(
|
const domRules = InspectorUtils.getCSSStyleRules(
|
||||||
node,
|
node,
|
||||||
pseudo,
|
pseudo,
|
||||||
CssLogic.hasVisitedState(node)
|
CssLogic.hasVisitedState(node),
|
||||||
|
/* we don't need to retrieve inherited starting style rules */
|
||||||
|
!inherited
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!domRules) {
|
if (!domRules) {
|
||||||
|
|
|
@ -550,6 +550,10 @@ class StyleRuleActor extends Actor {
|
||||||
start: rawRule.start,
|
start: rawRule.start,
|
||||||
end: rawRule.end,
|
end: rawRule.end,
|
||||||
});
|
});
|
||||||
|
} else if (ruleClassName === "CSSStartingStyleRule") {
|
||||||
|
ancestorData.push({
|
||||||
|
type,
|
||||||
|
});
|
||||||
} else if (rawRule.selectorText) {
|
} else if (rawRule.selectorText) {
|
||||||
// All the previous cases where about at-rules; this one is for regular rule
|
// All the previous cases where about at-rules; this one is for regular rule
|
||||||
// that are ancestors because CSS nesting was used.
|
// that are ancestors because CSS nesting was used.
|
||||||
|
|
|
@ -75,6 +75,7 @@ exports.CSSAtRuleClassNameType = {
|
||||||
CSSNamespaceRule: "namespace",
|
CSSNamespaceRule: "namespace",
|
||||||
CSSPageRule: "page",
|
CSSPageRule: "page",
|
||||||
CSSScopeRule: "scope",
|
CSSScopeRule: "scope",
|
||||||
|
CSSStartingStyleRule: "starting-style",
|
||||||
CSSSupportsRule: "supports",
|
CSSSupportsRule: "supports",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче