Bug 1530294 - Add option to skip cache when requesting authored text for CSS rule r=gl

This patch adds a boolean option to skip the cached value of `StyeRuleActor.authoredText` and re-parse the stylesheet for its value.
When changing content of a descendant rule inside an ancestor like @media or @select, the cached `authoredText` value is outdated.
This yields incorrect data when requesting the complete rule authored text, hence the need for a cache-busting option.

In addition to this change, there is a slight refactor to include the generated unique selector for the mock-rule for element inline styles.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Razvan Caliman 2019-02-26 09:09:01 +00:00
Родитель 4417ad8330
Коммит 3febb41272
2 изменённых файлов: 31 добавлений и 17 удалений

Просмотреть файл

@ -10,7 +10,6 @@ const { createFactory, createElement } = require("devtools/client/shared/vendor/
const { Provider } = require("devtools/client/shared/vendor/react-redux");
loader.lazyRequireGetter(this, "ChangesContextMenu", "devtools/client/inspector/changes/ChangesContextMenu");
loader.lazyRequireGetter(this, "prettifyCSS", "devtools/shared/inspector/css-logic", true);
loader.lazyRequireGetter(this, "clipboardHelper", "devtools/shared/platform/clipboard");
const ChangesApp = createFactory(require("./components/ChangesApp"));
@ -158,8 +157,7 @@ class ChangesView {
async copyRule(ruleId) {
const rule = await this.inspector.pageStyle.getRule(ruleId);
const text = await rule.getRuleText();
const prettyCSS = prettifyCSS(text);
clipboardHelper.copyString(prettyCSS);
clipboardHelper.copyString(text);
}
/**

Просмотреть файл

@ -23,6 +23,8 @@ loader.lazyRequireGetter(this, "isCssPropertyKnown",
"devtools/server/actors/css-properties", true);
loader.lazyRequireGetter(this, "parseNamedDeclarations",
"devtools/shared/css/parsing-utils", true);
loader.lazyRequireGetter(this, "prettifyCSS",
"devtools/shared/inspector/css-logic", true);
loader.lazyRequireGetter(this, "UPDATE_PRESERVING_RULES",
"devtools/server/actors/stylesheets", true);
loader.lazyRequireGetter(this, "UPDATE_GENERAL",
@ -1397,13 +1399,18 @@ var StyleRuleActor = protocol.ActorClassWithSpec(styleRuleSpec, {
* authored form is available, this also sets |this.authoredText|.
* The authored text will include invalid and otherwise ignored
* properties.
*
* @param {Boolean} skipCache
* If a value for authoredText was previously found and cached,
* ignore it and parse the stylehseet again. The authoredText
* may be outdated if a descendant of this rule has changed.
*/
getAuthoredCssText: function() {
getAuthoredCssText: function(skipCache = false) {
if (!this.canSetRuleText || !SUPPORTED_RULE_TYPES.includes(this.type)) {
return Promise.resolve("");
}
if (typeof this.authoredText === "string") {
if (typeof this.authoredText === "string" && !skipCache) {
return Promise.resolve(this.authoredText);
}
@ -1424,29 +1431,37 @@ var StyleRuleActor = protocol.ActorClassWithSpec(styleRuleSpec, {
* method includes the CSS selectors and at-rules (@media, @supports, @keyframes, etc.)
*
* If the rule type is unrecongized, the promise resolves to an empty string.
* If the rule is an element inline style, the promise resolves to the text content of
* If the rule is an element inline style, the promise resolves with the generated
* selector that uniquely identifies the element and with the rule body consisting of
* the element's style attribute.
*
* @return {String}
*/
getRuleText: async function() {
if (this.type === ELEMENT_STYLE) {
return Promise.resolve(this.rawNode.getAttribute("style"));
}
if (!SUPPORTED_RULE_TYPES.includes(this.type)) {
// Bail out if the rule is not supported or not an element inline style.
if (![...SUPPORTED_RULE_TYPES, ELEMENT_STYLE].includes(this.type)) {
return Promise.resolve("");
}
const ruleBodyText = await this.getAuthoredCssText();
const { str: stylesheetText } = await this.sheetActor.getText();
const [start, end] = getSelectorOffsets(stylesheetText, this.line, this.column);
const selectorText = stylesheetText.substring(start, end);
let ruleBodyText;
let selectorText;
let text;
// For element inline styles, use the style attribute and generated unique selector.
if (this.type === ELEMENT_STYLE) {
ruleBodyText = this.rawNode.getAttribute("style");
selectorText = this.metadata.selector;
} else {
// Get the rule's authored text and skip any cached value.
ruleBodyText = await this.getAuthoredCssText(true);
const { str: stylesheetText } = await this.sheetActor.getText();
const [start, end] = getSelectorOffsets(stylesheetText, this.line, this.column);
selectorText = stylesheetText.substring(start, end);
}
// CSS rule type as a string "@media", "@supports", "@keyframes", etc.
const typeName = CSSRuleTypeName[this.type];
let text;
// When dealing with at-rules, getSelectorOffsets() will not return the rule type.
// We prepend it ourselves.
if (typeName) {
@ -1455,7 +1470,8 @@ var StyleRuleActor = protocol.ActorClassWithSpec(styleRuleSpec, {
text = `${selectorText} {${ruleBodyText}}`;
}
return text;
const prettyCSS = prettifyCSS(text);
return Promise.resolve(prettyCSS);
},
/**