Bug 1503347 - Modify the Flex Item actor to consider CSS rules using the important keyword. r=pbro

Differential Revision: https://phabricator.services.mozilla.com/D11789

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Micah Tigley 2018-11-20 22:19:58 +00:00
parent 6be5837934
commit 3d84ed1aef
4 changed files with 98 additions and 16 deletions

View File

@ -3,6 +3,7 @@ tags = devtools
subsuite = devtools
support-files =
Ahem.ttf
doc_flexbox_CSS_property_with_!important.html
doc_flexbox_pseudos.html
doc_flexbox_specific_cases.html
doc_flexbox_text_nodes.html
@ -39,6 +40,7 @@ support-files =
[browser_flexbox_sizing_info_for_pseudos.js]
[browser_flexbox_sizing_info_for_text_nodes.js]
[browser_flexbox_sizing_info_has_correct_sections.js]
[browser_flexbox_sizing_info_matches_properties_with_!important.js]
[browser_flexbox_sizing_wanted_to_grow_but_was_clamped.js]
[browser_flexbox_text_nodes_are_listed.js]
[browser_flexbox_toggle_flexbox_highlighter_01.js]

View File

@ -0,0 +1,32 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that a flex item's sizing section shows the highest value of specificity for its
// CSS property.
const TEST_URI = URL_ROOT + "doc_flexbox_CSS_property_with_!important.html";
add_task(async function() {
await addTab(TEST_URI);
const { inspector, flexboxInspector } = await openLayoutView();
const { document: doc } = flexboxInspector;
info("Select the container's flex item sizing info.");
const onFlexItemSizingRendered = waitForDOM(doc, "ul.flex-item-sizing");
await selectNode(".item", inspector);
const [flexItemSizingContainer] = await onFlexItemSizingRendered;
info("Check that the max and flexibility sections show correct CSS property value.");
const flexSection = flexItemSizingContainer.querySelector(".section.flexibility");
const maxSection = flexItemSizingContainer.querySelector(".section.max");
const flexGrow = flexSection.querySelector(".css-property-link");
const maxSize = maxSection.querySelector(".css-property-link");
is(maxSize.textContent, "(max-width: 400px !important)",
"Maximum size section shows CSS property value with highest specificity.");
is(flexGrow.textContent, "(flex-grow: 5 !important)",
"Flexibility size section shows CSS property value with highest specificity.");
});

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.container {
display: flex;
width: 500px;
height: 150px;
margin: 10px;
}
.item {
background: yellow;
color: red;
flex-grow: 1 !important;
max-width: 350px;
max-width: 400px !important;
padding: 10px;
}
</style>
<div class="container">
<div class="item" style="flex-grow: 5 !important">Item</div>
</div>

View File

@ -16,8 +16,10 @@ const { SHOW_ELEMENT } = require("devtools/shared/dom-node-filter-constants");
const { getStringifiableFragments } =
require("devtools/server/actors/utils/css-grid-utils");
loader.lazyRequireGetter(this, "getCSSStyleRules", "devtools/shared/inspector/css-logic", true);
loader.lazyRequireGetter(this, "CssLogic", "devtools/server/actors/inspector/css-logic", true);
loader.lazyRequireGetter(this, "getCSSStyleRules", "devtools/shared/inspector/css-logic", true);
loader.lazyRequireGetter(this, "isCssPropertyKnown", "devtools/server/actors/css-properties", true);
loader.lazyRequireGetter(this, "parseDeclarations", "devtools/shared/css/parsing-utils", true);
loader.lazyRequireGetter(this, "nodeConstants", "devtools/shared/dom-node-constants");
/**
@ -175,25 +177,49 @@ const FlexItemActor = ActorClassWithSpec(flexItemSpec, {
if (isElementNode) {
for (const name in properties) {
let value = "";
// Look first on the element style.
if (this.element.style &&
this.element.style[name] && this.element.style[name] !== "auto") {
value = this.element.style[name];
} else {
// And then on the rules that apply to the element.
// getCSSStyleRules returns rules from least to most specific, so override
// values as we find them.
const cssRules = getCSSStyleRules(this.element);
for (const rule of cssRules) {
const rulePropertyValue = rule.style.getPropertyValue(name);
if (rulePropertyValue && rulePropertyValue !== "auto") {
value = rulePropertyValue;
const values = [];
const cssRules = getCSSStyleRules(this.element);
for (const rule of cssRules) {
// For each rule, go through *all* properties, because there may be several of
// them in the same rule and some with !important flags (which would be more
// important even if placed before another property with the same name)
const declarations = parseDeclarations(isCssPropertyKnown, rule.style.cssText);
for (const declaration of declarations) {
if (declaration.name === name && declaration.value !== "auto") {
values.push({ value: declaration.value, priority: declaration.priority });
}
}
}
properties[name] = value;
// Then go through the element style because it's usually more important, but
// might not be if there is a prior !important property
if (this.element.style && this.element.style[name] &&
this.element.style[name] !== "auto") {
values.push({
value: this.element.style.getPropertyValue(name),
priority: this.element.style.getPropertyPriority(name),
});
}
// Now that we have a list of all the property's rule values, go through all the
// values and show the property value with the highest priority. Therefore, show
// the last !important value. Otherwise, show the last value stored.
let rulePropertyValue = "";
if (values.length) {
const lastValueIndex = values.length - 1;
rulePropertyValue = values[lastValueIndex].value;
for (const { priority, value } of values) {
if (priority === "important") {
rulePropertyValue = `${value} !important`;
}
}
}
properties[name] = rulePropertyValue;
}
}