Skip to content

Commit

Permalink
style: Have the CSSOM appending behavior behind a pref and only enabl…
Browse files Browse the repository at this point in the history
…e it on Nightly.

Bug: 1461285
Reviewed-by: emilio
MozReview-Commit-ID: 6BzPTNjXjyA
  • Loading branch information
upsuper authored and emilio committed Jul 16, 2018
1 parent 2be1375 commit d4ea70f
Showing 1 changed file with 55 additions and 12 deletions.
67 changes: 55 additions & 12 deletions components/style/properties/declaration_block.rs
Expand Up @@ -47,8 +47,12 @@ pub enum DeclarationPushMode {
/// importance, the new declaration will be discarded. Otherwise, it will
/// be appended to the end of the declaration block.
Parsing,
/// In this mode, if there is an existing declaration of the same property,
/// the value is updated in-place. Otherwise it's appended. This is one
/// possible behavior of CSSOM.
Update,
/// In this mode, the new declaration is always pushed to the end of the
/// declaration block. This is for CSSOM.
/// declaration block. This is another possible behavior of CSSOM.
Append,
}

Expand Down Expand Up @@ -414,10 +418,49 @@ impl PropertyDeclarationBlock {
}
}

/// Returns whether the property is definitely new for this declaration
/// block. It returns true when the declaration is a non-custom longhand
/// and it doesn't exist in the block, and returns false otherwise.
#[inline]
fn is_definitely_new(&self, decl: &PropertyDeclaration) -> bool {
match decl.id() {
PropertyDeclarationId::Longhand(id) => !self.longhands.contains(id),
PropertyDeclarationId::Custom(..) => false,
}
}

/// Returns whether calling extend with `DeclarationPushMode::Update`
/// will cause this declaration block to change.
pub fn will_change_in_update_mode(
&self,
source_declarations: &SourcePropertyDeclaration,
importance: Importance,
) -> bool {
// XXX The type of parameter seems to be necessary because otherwise
// the compiler complains about `decl` not living long enough in the
// all_shorthand expression. Why?
let needs_update = |decl: &_| {
if self.is_definitely_new(decl) {
return true;
}
self.declarations.iter().enumerate()
.find(|&(_, ref slot)| slot.id() == decl.id())
.map_or(true, |(i, slot)| {
let important = self.declarations_importance[i];
*slot != *decl || important != importance.important()
})
};
source_declarations.declarations.iter().any(&needs_update) ||
source_declarations.all_shorthand.declarations().any(|decl| needs_update(&decl))
}

/// Adds or overrides the declaration for a given property in this block.
///
/// See the documentation of `push` to see what impact `source` has when the
/// property is already there.
///
/// When calling with `DeclarationPushMode::Update`, this should not change
/// anything if `will_change_in_update_mode` returns false.
pub fn extend(
&mut self,
mut drain: SourcePropertyDeclarationDrain,
Expand Down Expand Up @@ -473,16 +516,7 @@ impl PropertyDeclarationBlock {
importance: Importance,
mode: DeclarationPushMode,
) -> bool {
let longhand_id = match declaration.id() {
PropertyDeclarationId::Longhand(id) => Some(id),
PropertyDeclarationId::Custom(..) => None,
};

let definitely_new = longhand_id.map_or(false, |id| {
!self.longhands.contains(id)
});

if !definitely_new {
if !self.is_definitely_new(&declaration) {
let mut index_to_remove = None;
for (i, slot) in self.declarations.iter_mut().enumerate() {
if slot.id() != declaration.id() {
Expand Down Expand Up @@ -514,6 +548,15 @@ impl PropertyDeclarationBlock {
}
}
}
if matches!(mode, DeclarationPushMode::Update) {
let important = self.declarations_importance[i];
if *slot == declaration && important == importance.important() {
return false;
}
*slot = declaration;
self.declarations_importance.set(i, importance.important());
return true;
}

index_to_remove = Some(i);
break;
Expand All @@ -528,7 +571,7 @@ impl PropertyDeclarationBlock {
}
}

if let Some(id) = longhand_id {
if let PropertyDeclarationId::Longhand(id) = declaration.id() {
self.longhands.insert(id);
}
self.declarations.push(declaration);
Expand Down

0 comments on commit d4ea70f

Please sign in to comment.