Commit 9f01adde authored by Oriol Brufau's avatar Oriol Brufau Committed by Commit Bot

[css-marker] Avoid DCHECK failure when devtools inspect nested ::marker

When inspecting a ::marker originated by a ::before or ::after pseudo
elements, the devtools use InspectorCSSAgent::getMatchedStylesForNode to
retrieve the styles of the ::marker.

This ends up calling MatchSlottedRules, which gets the AssignedSlot()
of the originating ::before or ::after. But pseudo-elements can't have
an assigned slot, so a DCHECK fails.

This patch avoids this problem by aborting PseudoCSSRulesForElement in
case that we have a pseudo-element.

This also fixes the issue that devtools used to say that a *::marker
selector would match a nested ::before::marker or ::after::marker.

BUG=457718

TEST=http/tests/devtools/elements/styles-2/nested-pseudo-elements.js
TEST=inspector-protocol/css/nested-pseudo-element-matching-selectors.js

Change-Id: I78a1efe708dc1668934025141231b2cc87f34136
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2138413
Commit-Queue: Oriol Brufau <obrufau@igalia.com>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757617}
parent ff1f65d5
......@@ -1305,8 +1305,11 @@ RuleIndexList* StyleResolver::PseudoCSSRulesForElement(
match_result, state.Style(),
EInsideLink::kNotInsideLink);
collector.SetMode(SelectorChecker::kCollectingCSSRules);
CollectPseudoRulesForElement(*element, collector, pseudo_id,
rules_to_include);
// TODO(obrufau): support collecting rules for nested ::marker
if (!element->IsPseudoElement()) {
CollectPseudoRulesForElement(*element, collector, pseudo_id,
rules_to_include);
}
if (tracker_)
AddMatchedRulesToTracker(collector);
......
......@@ -33,6 +33,10 @@ Running: dumpAfterStyles
content: "AFTER";
Running: dumpBeforeMarkerStyles
Running: dumpAfterMarkerStyles
Running: removeAfterMarker
- <div id="container">
- <div id="inspected">
......
......@@ -66,11 +66,19 @@
},
function dumpBeforeStyles(next) {
selectNodeAndDumpStyles('inspected', 'before', next);
selectNodeAndDumpStyles('inspected', ['before'], next);
},
function dumpAfterStyles(next) {
selectNodeAndDumpStyles('inspected', 'after', next);
selectNodeAndDumpStyles('inspected', ['after'], next);
},
function dumpBeforeMarkerStyles(next) {
selectNodeAndDumpStyles('inspected', ['before', 'marker'], next);
},
function dumpAfterMarkerStyles(next) {
selectNodeAndDumpStyles('inspected', ['after', 'marker'], next);
},
function removeAfterMarker(next) {
......@@ -137,11 +145,40 @@
}
}
function selectNodeAndDumpStyles(id, pseudoTypeName, callback) {
if (pseudoTypeName)
ElementsTestRunner.selectPseudoElementAndWaitForStyles('inspected', pseudoTypeName, stylesCallback);
else
ElementsTestRunner.selectNodeAndWaitForStyles('inspected', stylesCallback);
function selectPseudoElementAndWaitForStyles(parentId, pseudoTypes, callback) {
if (!pseudoTypes.length) {
ElementsTestRunner.selectNodeAndWaitForStyles(parentId, callback);
return;
}
pseudoTypes.reduce(async function(prev, pseudoType) {
let prevNode = await prev;
function isCurrentPseudoElement(node) {
if (node.pseudoType() !== pseudoType)
return false;
const {parentNode} = node;
if (!parentNode)
return false;
if (prevNode)
return parentNode === prevNode;
return parentNode.getAttribute('id') == parentId;
}
let stylesUpdated = new Promise((resolve) => {
waitForStylesRebuild(isCurrentPseudoElement, resolve, true);
});
let node = await new Promise((resolve) => {
ElementsTestRunner.findNode(isCurrentPseudoElement, resolve);
});
if (!node)
throw new Error("Can't find node");
Common.Revealer.reveal(node);
await stylesUpdated;
return node;
}, null).then(callback);
}
function selectNodeAndDumpStyles(id, pseudoTypeNames, callback) {
selectPseudoElementAndWaitForStyles(id, pseudoTypeNames, stylesCallback);
async function stylesCallback() {
await ElementsTestRunner.dumpSelectedElementStyles(true, false, false, true);
......
Test that matching styles report nested pseudo element styles.
=== Dump matching styles for #for-pseudo::before::marker ===
=== Dump matching styles for #for-pseudo::after::marker ===
(async function(testRunner) {
const {page, session, dp} = await testRunner.startHTML(`
<style>
::marker {
content: "This should NOT match";
}
#for-pseudo::before {
content: "BEFORE";
display: list-item;
}
#for-pseudo::after {
content: "AFTER";
display: list-item;
}
#for-pseudo::before::marker {
content: "MARKER";
}
</style>
<div id='for-pseudo'>Test</div>`, 'Test that matching styles report nested pseudo element styles.');
await dp.DOM.enable();
await dp.CSS.enable();
const NodeTracker = await testRunner.loadScript('../resources/node-tracker.js');
const nodeTracker = new NodeTracker(dp);
const DOMHelper = await testRunner.loadScript('../resources/dom-helper.js');
const CSSHelper = await testRunner.loadScript('../resources/css-helper.js');
const cssHelper = new CSSHelper(testRunner, dp);
function getPseudoElement(node, ...pseudoTypes) {
for (const pseudoType of pseudoTypes)
node = node.pseudoElements.find(pseudoElement => pseudoElement.pseudoType === pseudoType);
return node;
}
async function loadAndDumpMatchingRules(nodeId) {
const {result} = await dp.CSS.getMatchedStylesForNode({nodeId});
for (const ruleMatch of result.matchedCSSRules) {
const origin = ruleMatch.rule.origin;
if (origin !== 'inspector' && origin !== 'regular')
continue;
cssHelper.dumpRuleMatch(ruleMatch);
}
}
const documentNodeId = await cssHelper.requestDocumentNodeId();
await cssHelper.requestNodeId(documentNodeId, '#for-pseudo');
const node = nodeTracker.nodes().find(node => DOMHelper.attributes(node).get('id') === 'for-pseudo');
testRunner.log('\n=== Dump matching styles for #for-pseudo::before::marker ===\n');
await loadAndDumpMatchingRules(getPseudoElement(node, "before", "marker").nodeId);
testRunner.log('\n=== Dump matching styles for #for-pseudo::after::marker ===\n');
await loadAndDumpMatchingRules(getPseudoElement(node, "after", "marker").nodeId);
testRunner.completeTest();
})
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment