Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / devtools / client / fronts / style-rule.js
blob9124deec41f09f321ba86149c82d8383b19b0c66
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 const {
8 FrontClassWithSpec,
9 registerFront,
10 } = require("resource://devtools/shared/protocol.js");
11 const {
12 styleRuleSpec,
13 } = require("resource://devtools/shared/specs/style-rule.js");
15 loader.lazyRequireGetter(
16 this,
17 "RuleRewriter",
18 "resource://devtools/client/fronts/inspector/rule-rewriter.js"
21 /**
22 * StyleRuleFront, the front for the StyleRule actor.
24 class StyleRuleFront extends FrontClassWithSpec(styleRuleSpec) {
25 constructor(client, targetFront, parentFront) {
26 super(client, targetFront, parentFront);
28 this.before("location-changed", this._locationChangedPre.bind(this));
31 form(form) {
32 this.actorID = form.actor;
33 this._form = form;
34 this.traits = form.traits || {};
37 /**
38 * Ensure _form is updated when location-changed is emitted.
40 _locationChangedPre(line, column) {
41 this._form.line = line;
42 this._form.column = column;
45 /**
46 * Return a new RuleModificationList or RuleRewriter for this node.
47 * A RuleRewriter will be returned when the rule's canSetRuleText
48 * trait is true; otherwise a RuleModificationList will be
49 * returned.
51 * @param {CssPropertiesFront} cssProperties
52 * This is needed by the RuleRewriter.
53 * @return {RuleModificationList}
55 startModifyingProperties(cssProperties) {
56 if (this.canSetRuleText) {
57 return new RuleRewriter(cssProperties.isKnown, this, this.authoredText);
59 return new RuleModificationList(this);
62 get type() {
63 return this._form.type;
65 get line() {
66 return this._form.line || -1;
68 get column() {
69 return this._form.column || -1;
71 get cssText() {
72 return this._form.cssText;
74 get isNestedDeclarations() {
75 return !!this._form.isNestedDeclarations;
77 get authoredText() {
78 return typeof this._form.authoredText === "string"
79 ? this._form.authoredText
80 : this._form.cssText;
82 get declarations() {
83 return this._form.declarations || [];
85 get keyText() {
86 return this._form.keyText;
88 get name() {
89 return this._form.name;
91 get selectors() {
92 return this._form.selectors;
94 get selectorsSpecificity() {
95 return this._form.selectorsSpecificity;
98 /**
99 * Returns a concatenation of the rule's selector and all its ancestor "selectors".
100 * This is different from a "desugared" selector as what's returned is not an
101 * actual selector, but some kind of key that represent the rule selectors.
102 * This is used for the selector highlighter, where we need to know what's
103 * being highlighted.
105 * @returns {String}
107 get computedSelector() {
108 let selector = "";
109 for (const ancestor of this.ancestorData) {
110 let ancestorSelector;
111 if (ancestor.selectors) {
112 ancestorSelector = ancestor.selectors.join(",");
113 } else if (ancestor.type === "container") {
114 ancestorSelector =
115 ancestor.containerName + " " + ancestor.containerQuery;
116 } else if (ancestor.type === "supports") {
117 ancestorSelector = ancestor.conditionText;
118 } else if (ancestor.value) {
119 ancestorSelector = ancestor.value;
121 selector +=
122 "/" + (ancestor.type ? ancestor.type + " " : "") + ancestorSelector;
125 return (selector ? selector + "/" : "") + this._form.selectors.join(",");
128 get selectorWarnings() {
129 return this._form.selectorWarnings;
132 get parentStyleSheet() {
133 const resourceCommand = this.targetFront.commands.resourceCommand;
134 return resourceCommand.getResourceById(
135 resourceCommand.TYPES.STYLESHEET,
136 this._form.parentStyleSheet
140 get element() {
141 return this.conn.getFrontByID(this._form.element);
144 get href() {
145 if (this._form.href) {
146 return this._form.href;
148 const sheet = this.parentStyleSheet;
149 return sheet ? sheet.href : "";
152 get nodeHref() {
153 const sheet = this.parentStyleSheet;
154 return sheet ? sheet.nodeHref : "";
157 get canSetRuleText() {
158 return this._form.traits && this._form.traits.canSetRuleText;
161 get location() {
162 return {
163 source: this.parentStyleSheet,
164 href: this.href,
165 line: this.line,
166 column: this.column,
170 get ancestorData() {
171 return this._form.ancestorData;
174 get userAdded() {
175 return this._form.userAdded;
178 async modifySelector(node, value) {
179 const response = await super.modifySelector(
180 node,
181 value,
182 this.canSetRuleText
185 if (response.ruleProps) {
186 response.ruleProps = response.ruleProps.entries[0];
188 return response;
191 setRuleText(newText, modifications) {
192 this._form.authoredText = newText;
193 return super.setRuleText(newText, modifications);
197 exports.StyleRuleFront = StyleRuleFront;
198 registerFront(StyleRuleFront);
201 * Convenience API for building a list of attribute modifications
202 * for the `modifyProperties` request. A RuleModificationList holds a
203 * list of modifications that will be applied to a StyleRuleActor.
204 * The modifications are processed in the order in which they are
205 * added to the RuleModificationList.
207 * Objects of this type expose the same API as @see RuleRewriter.
208 * This lets the inspector use (mostly) the same code, regardless of
209 * whether the server implements setRuleText.
211 class RuleModificationList {
213 * Initialize a RuleModificationList.
214 * @param {StyleRuleFront} rule the associated rule
216 constructor(rule) {
217 this.rule = rule;
218 this.modifications = [];
222 * Apply the modifications in this object to the associated rule.
224 * @return {Promise} A promise which will be resolved when the modifications
225 * are complete; @see StyleRuleActor.modifyProperties.
227 apply() {
228 return this.rule.modifyProperties(this.modifications);
232 * Add a "set" entry to the modification list.
234 * @param {Number} index index of the property in the rule.
235 * This can be -1 in the case where
236 * the rule does not support setRuleText;
237 * generally for setting properties
238 * on an element's style.
239 * @param {String} name the property's name
240 * @param {String} value the property's value
241 * @param {String} priority the property's priority, either the empty
242 * string or "important"
244 setProperty(index, name, value, priority) {
245 this.modifications.push({ type: "set", index, name, value, priority });
249 * Add a "remove" entry to the modification list.
251 * @param {Number} index index of the property in the rule.
252 * This can be -1 in the case where
253 * the rule does not support setRuleText;
254 * generally for setting properties
255 * on an element's style.
256 * @param {String} name the name of the property to remove
258 removeProperty(index, name) {
259 this.modifications.push({ type: "remove", index, name });
263 * Rename a property. This implementation acts like
264 * |removeProperty|, because |setRuleText| is not available.
266 * @param {Number} index index of the property in the rule.
267 * This can be -1 in the case where
268 * the rule does not support setRuleText;
269 * generally for setting properties
270 * on an element's style.
271 * @param {String} name current name of the property
273 * This parameter is also passed, but as it is not used in this
274 * implementation, it is omitted. It is documented here as this
275 * code also defined the interface implemented by @see RuleRewriter.
276 * @param {String} newName new name of the property
278 renameProperty(index, name) {
279 this.removeProperty(index, name);
283 * Enable or disable a property. This implementation acts like
284 * a no-op when enabling, because |setRuleText| is not available.
286 * @param {Number} index index of the property in the rule.
287 * This can be -1 in the case where
288 * the rule does not support setRuleText;
289 * generally for setting properties
290 * on an element's style.
291 * @param {String} name current name of the property
292 * @param {Boolean} isEnabled true if the property should be enabled;
293 * false if it should be disabled
295 setPropertyEnabled(index, name, isEnabled) {
296 if (!isEnabled) {
297 this.modifications.push({ type: "disable", index, name });
302 * Create a new property. This implementation does nothing, because
303 * |setRuleText| is not available.
305 * These parameters are passed, but as they are not used in this
306 * implementation, they are omitted. They are documented here as
307 * this code also defined the interface implemented by @see
308 * RuleRewriter.
310 * @param {Number} index index of the property in the rule.
311 * This can be -1 in the case where
312 * the rule does not support setRuleText;
313 * generally for setting properties
314 * on an element's style.
315 * @param {String} name name of the new property
316 * @param {String} value value of the new property
317 * @param {String} priority priority of the new property; either
318 * the empty string or "important"
319 * @param {Boolean} enabled True if the new property should be
320 * enabled, false if disabled
322 createProperty() {
323 // Nothing.