Bug 1503896 - (Part 2) Support tracking multiple CSS declarations in one change; r=pbro

Depends on D10582
Improves the reducer for tracking CSS changes to handle more than one
CSS declaration changed in one operation. This is a requirement for
tracking whole rule removal or whole rule addition, like it happens
when renaming a CSS selector in the Rules view.

MozReview-Commit-ID: 25pf2GRiH4D

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Razvan Caliman 2018-11-05 14:50:04 +00:00
parent bed8c7e449
commit 625bcbde9a
2 changed files with 28 additions and 24 deletions

View File

@ -169,6 +169,9 @@ const reducers = {
const { selector, ancestors, ruleIndex } = change;
const sourceId = getSourceHash(change.source);
const ruleId = getRuleHash({ selector, ancestors, ruleIndex });
// Type coerce to boolean: `false` if value is undefined or `null`, `true` otherwise.
const hasAdd = !!change.add;
const hasRemove = !!change.remove;
// Copy or create object identifying the source (styelsheet/element) for this change.
const source = Object.assign({}, state[sourceId], { type, href, index });
@ -184,31 +187,32 @@ const reducers = {
// Copy or create collection of all CSS declarations ever removed from this rule.
const remove = Object.assign({}, rule.remove);
if (change.remove && change.remove.property) {
// Track the remove operation only if the property was not previously introduced
// by an add operation. This ensures repeated changes of the same property
// register as a single remove operation of its original value.
if (!add[change.remove.property]) {
remove[change.remove.property] = change.remove.value;
}
if (hasRemove) {
Object.entries(change.remove).forEach(([property, value]) => {
// Track the remove operation only if the property was not previously introduced
// by an add operation. This ensures repeated changes of the same property
// register as a single remove operation of its original value.
if (!add[property]) {
remove[property] = value;
}
// Delete any previous add operation which would be canceled out by this remove.
if (add[change.remove.property] === change.remove.value) {
delete add[change.remove.property];
}
// Delete any previous add operation which would be canceled out by this remove.
if (add[property] === value) {
delete add[property];
}
});
}
if (change.add && change.add.property) {
add[change.add.property] = change.add.value;
}
if (hasAdd) {
Object.entries(change.add).forEach(([property, value]) => {
add[property] = value;
const property = change.add && change.add.property ||
change.remove && change.remove.property;
// Remove tracked operations if they cancel each other out.
if (add[property] === remove[property]) {
delete add[property];
delete remove[property];
// Remove previously tracked declarations if they cancel each other out.
if (add[property] === remove[property]) {
delete add[property];
delete remove[property];
}
});
}
// Remove information about the rule if none its declarations changed.

View File

@ -1566,11 +1566,11 @@ var StyleRuleActor = protocol.ActorClassWithSpec(styleRuleSpec, {
// Otherwise, use the incoming value string.
const value = change.newName ? prevValue : newValue;
data.add = { property: name, value };
data.add = { [name]: value };
// If there is a previous value, log its removal together with the previous
// property name. Using the previous name handles the case for renaming a property
// and is harmless when updating an existing value (the name stays the same).
data.remove = prevValue ? { property: prevName, value: prevValue } : null;
data.remove = prevValue ? { [prevName]: prevValue } : null;
// When toggling a declaration from OFF to ON, if not renaming the property,
// do not mark the previous declaration for removal, otherwise the add and
@ -1584,7 +1584,7 @@ var StyleRuleActor = protocol.ActorClassWithSpec(styleRuleSpec, {
case "remove":
data.add = null;
data.remove = { property: change.name, value: prevValue };
data.remove = { [change.name]: prevValue };
break;
}