Skip to content

Commit d50dcd0

Browse files
Eric LeeseDevtools-frontend LUCI CQ
authored andcommitted
Find attributes on originating node of pseudo elements
Bug: 444208101 Change-Id: Iabe07c9bcb5e25ba64f8a6bcd6a09ff0a61cff56 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6939232 Reviewed-by: Philip Pfaffe <[email protected]> Commit-Queue: Eric Leese <[email protected]>
1 parent 648ad84 commit d50dcd0

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

front_end/core/sdk/CSSMatchedStyles.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,25 @@ describe('CSSMatchedStyles', () => {
698698
assert.isNull(matchedStyles.resolveProperty('background-color', styles[0]));
699699
});
700700

701+
it('reads attributes from the parent node of a pseudo-element', async () => {
702+
const node = sinon.createStubInstance(SDK.DOMModel.DOMNode);
703+
node.id = 1 as Protocol.DOM.NodeId;
704+
node.nodeType.returns(Node.ELEMENT_NODE);
705+
node.getAttribute.callsFake((name: string) => `parent-${name}`);
706+
const pseudoElement = sinon.createStubInstance(SDK.DOMModel.DOMNode);
707+
pseudoElement.id = 2 as Protocol.DOM.NodeId;
708+
pseudoElement.nodeType.returns(Node.ELEMENT_NODE);
709+
pseudoElement.parentNode = node;
710+
pseudoElement.pseudoType.returns('before');
711+
const matchedStyles = await getMatchedStyles({
712+
matchedPayload: [ruleMatch('div::before', {content: 'attr(data-content)'})],
713+
node: pseudoElement,
714+
});
715+
716+
const property = matchedStyles.rawAttributeValueFromStyle(matchedStyles.nodeStyles()[0], 'data-content');
717+
assert.strictEqual(property, 'parent-data-content');
718+
});
719+
701720
it('evaluates variables with attr() calls in the same way as blink', async () => {
702721
const attributes = [
703722
{name: 'data-test-nonexistent', value: 'attr(data-nonexistent)'},

front_end/core/sdk/CSSMatchedStyles.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,20 @@ export class CSSMatchedStyles {
868868
return domCascade ? domCascade.computeAttribute(style, attributeName, type) : null;
869869
}
870870

871+
rawAttributeValueFromStyle(style: CSSStyleDeclaration, attributeName: string): string|null {
872+
let node: DOMNode|null = this.nodeForStyle(style) ?? this.node();
873+
874+
// If it's a pseudo-element, we need to find the originating element.
875+
while (node?.pseudoType()) {
876+
node = node.parentNode;
877+
}
878+
879+
if (!node) {
880+
return null;
881+
}
882+
return node.getAttribute(attributeName) ?? null;
883+
}
884+
871885
resolveProperty(name: string, ownerStyle: CSSStyleDeclaration): CSSProperty|null {
872886
return this.#styleToDOMCascade.get(ownerStyle)?.resolveProperty(name, ownerStyle) ?? null;
873887
}
@@ -1304,16 +1318,8 @@ class DOMInheritanceCascade {
13041318
return this.innerComputeAttribute(nodeCascade, style, attributeName, type, new SCCRecord());
13051319
}
13061320

1307-
private rawAttributeValue(style: CSSStyleDeclaration, attributeName: string): string|null {
1308-
const node = this.#matchedStyles.nodeForStyle(style) ?? this.#matchedStyles.node();
1309-
if (!node) {
1310-
return null;
1311-
}
1312-
return node.getAttribute(attributeName) ?? null;
1313-
}
1314-
13151321
private attributeValueAsType(style: CSSStyleDeclaration, attributeName: string, type: string): string|null {
1316-
const rawValue = this.rawAttributeValue(style, attributeName);
1322+
const rawValue = this.#matchedStyles.rawAttributeValueFromStyle(style, attributeName);
13171323
if (rawValue === null) {
13181324
return null;
13191325
}
@@ -1322,7 +1328,7 @@ class DOMInheritanceCascade {
13221328

13231329
private attributeValueWithSubstitutions(
13241330
nodeCascade: NodeCascade, style: CSSStyleDeclaration, attributeName: string, sccRecord: SCCRecord): string|null {
1325-
const rawValue = this.rawAttributeValue(style, attributeName);
1331+
const rawValue = this.#matchedStyles.rawAttributeValueFromStyle(style, attributeName);
13261332
if (rawValue === null) {
13271333
return null;
13281334
}

front_end/core/sdk/CSSPropertyParserMatchers.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,8 @@ export class AttributeMatcher extends matcherBase(AttributeMatch) {
260260

261261
const attrName = matching.ast.text(nameNode);
262262

263+
const rawValue = this.matchedStyles.rawAttributeValueFromStyle(this.style, attrName);
263264
let substitutionText: string|null = null;
264-
const domNode = this.matchedStyles.nodeForStyle(this.style) ?? this.matchedStyles.node();
265-
const rawValue = domNode.getAttribute(attrName) ?? null;
266265
if (rawValue !== null) {
267266
substitutionText = isCSSTokens ? rawValue : localEvalCSS(rawValue, type ?? RAW_STRING_TYPE);
268267
} else if (!fallback) {

0 commit comments

Comments
 (0)