Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style: Dishonor display: -moz-box if -webkit-box was specified before #18867

Merged
merged 2 commits into from Oct 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions components/script/dom/cssstyledeclaration.rs
Expand Up @@ -18,7 +18,7 @@ use servo_arc::Arc;
use servo_url::ServoUrl;
use std::ascii::AsciiExt;
use style::attr::AttrValue;
use style::properties::{Importance, PropertyDeclarationBlock, PropertyId, LonghandId, ShorthandId};
use style::properties::{DeclarationSource, Importance, PropertyDeclarationBlock, PropertyId, LonghandId, ShorthandId};
use style::properties::{parse_one_declaration_into, parse_style_attribute, SourcePropertyDeclaration};
use style::selector_parser::PseudoElement;
use style::shared_lock::Locked;
Expand Down Expand Up @@ -274,7 +274,11 @@ impl CSSStyleDeclaration {

// Step 7
// Step 8
*changed = pdb.extend_reset(declarations.drain(), importance);
*changed = pdb.extend(
declarations.drain(),
importance,
DeclarationSource::CssOm,
);

Ok(())
})
Expand Down
125 changes: 77 additions & 48 deletions components/style/properties/declaration_block.rs
Expand Up @@ -39,6 +39,17 @@ impl AnimationRules {
}
}

/// Whether a given declaration comes from CSS parsing, or from CSSOM.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum DeclarationSource {
/// The declaration was obtained from CSS parsing of sheets and such.
Parsing,
/// The declaration was obtained from CSSOM.
CssOm,
}

/// A declaration [importance][importance].
///
/// [importance]: https://drafts.csswg.org/css-cascade/#importance
Expand Down Expand Up @@ -378,30 +389,15 @@ impl PropertyDeclarationBlock {
}
}

/// Adds or overrides the declaration for a given property in this block,
/// **except** if an existing declaration for the same property is more
/// important.
/// Adds or overrides the declaration for a given property in this block.
///
/// Always ensures that the property declaration is at the end.
pub fn extend(&mut self, drain: SourcePropertyDeclarationDrain, importance: Importance) {
self.extend_common(drain, importance, false);
}

/// Adds or overrides the declaration for a given property in this block,
/// **even** if an existing declaration for the same property is more
/// important, and reuses the same position in the block.
///
/// Returns whether anything changed.
pub fn extend_reset(&mut self, drain: SourcePropertyDeclarationDrain,
importance: Importance) -> bool {
self.extend_common(drain, importance, true)
}

fn extend_common(
/// See the documentation of `push` to see what impact `source` has when the
/// property is already there.
pub fn extend(
&mut self,
mut drain: SourcePropertyDeclarationDrain,
importance: Importance,
overwrite_more_important_and_reuse_slot: bool,
source: DeclarationSource,
) -> bool {
let all_shorthand_len = match drain.all_shorthand {
AllShorthand::NotSet => 0,
Expand All @@ -415,53 +411,56 @@ impl PropertyDeclarationBlock {

let mut changed = false;
for decl in &mut drain.declarations {
changed |= self.push_common(
changed |= self.push(
decl,
importance,
overwrite_more_important_and_reuse_slot,
source,
);
}
match drain.all_shorthand {
AllShorthand::NotSet => {}
AllShorthand::CSSWideKeyword(keyword) => {
for &id in ShorthandId::All.longhands() {
let decl = PropertyDeclaration::CSSWideKeyword(id, keyword);
changed |= self.push_common(
changed |= self.push(
decl,
importance,
overwrite_more_important_and_reuse_slot,
source,
);
}
}
AllShorthand::WithVariables(unparsed) => {
for &id in ShorthandId::All.longhands() {
let decl = PropertyDeclaration::WithVariables(id, unparsed.clone());
changed |= self.push_common(
changed |= self.push(
decl,
importance,
overwrite_more_important_and_reuse_slot,
source,
);
}
}
}
changed
}

/// Adds or overrides the declaration for a given property in this block,
/// **except** if an existing declaration for the same property is more
/// important.
/// Adds or overrides the declaration for a given property in this block.
///
/// Ensures that, if inserted, it's inserted at the end of the declaration
/// Depending on the value of `source`, this has a different behavior in the
/// presence of another declaration with the same ID in the declaration
/// block.
pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) {
self.push_common(declaration, importance, false);
}

fn push_common(
///
/// * For `DeclarationSource::Parsing`, this will not override a
/// declaration with more importance, and will ensure that, if inserted,
/// it's inserted at the end of the declaration block.
///
/// * For `DeclarationSource::CssOm`, this will override importance and
/// will preserve the original position on the block.
///
pub fn push(
&mut self,
declaration: PropertyDeclaration,
importance: Importance,
overwrite_more_important_and_reuse_slot: bool
source: DeclarationSource,
) -> bool {
let longhand_id = match declaration.id() {
PropertyDeclarationId::Longhand(id) => Some(id),
Expand All @@ -481,7 +480,9 @@ impl PropertyDeclarationBlock {
(false, true) => {}

(true, false) => {
if !overwrite_more_important_and_reuse_slot {
// For declarations set from the OM, less-important
// declarations are overridden.
if !matches!(source, DeclarationSource::CssOm) {
return false
}
}
Expand All @@ -490,17 +491,41 @@ impl PropertyDeclarationBlock {
}
}

if overwrite_more_important_and_reuse_slot {
*slot = declaration;
self.declarations_importance.set(i as u32, importance.important());
return true;
}
match source {
// CSSOM preserves the declaration position, and
// overrides importance.
DeclarationSource::CssOm => {
*slot = declaration;
self.declarations_importance.set(i as u32, importance.important());
return true;
}
DeclarationSource::Parsing => {
// As a compatibility hack, specially on Android,
// don't allow to override a prefixed webkit display
// value with an unprefixed version from parsing
// code.
//
// TODO(emilio): Unship.
if let PropertyDeclaration::Display(old_display) = *slot {
use properties::longhands::display::computed_value::T as display;

let new_display = match declaration {
PropertyDeclaration::Display(new_display) => new_display,
_ => unreachable!("How could the declaration id be the same?"),
};

if display::should_ignore_parsed_value(old_display, new_display) {
return false;
}
}

// NOTE(emilio): We could avoid this and just override for
// properties not affected by logical props, but it's not
// clear it's worth it given the `definitely_new` check.
index_to_remove = Some(i);
break;
// NOTE(emilio): We could avoid this and just override for
// properties not affected by logical props, but it's not
// clear it's worth it given the `definitely_new` check.
index_to_remove = Some(i);
break;
}
}
}
}

Expand Down Expand Up @@ -1118,7 +1143,11 @@ pub fn parse_property_declaration_list<R>(context: &ParserContext,
while let Some(declaration) = iter.next() {
match declaration {
Ok(importance) => {
block.extend(iter.parser.declarations.drain(), importance);
block.extend(
iter.parser.declarations.drain(),
importance,
DeclarationSource::Parsing,
);
}
Err((error, slice)) => {
iter.parser.declarations.clear();
Expand Down
27 changes: 27 additions & 0 deletions components/style/properties/longhand/box.mako.rs
Expand Up @@ -68,6 +68,33 @@
)
}

/// Whether `new_display` should be ignored, given a previous
/// `old_display` value.
///
/// This is used to ignore `display: -moz-box` declarations after an
/// equivalent `display: -webkit-box` declaration, since the former
/// has a vastly different meaning. See bug 1107378 and bug 1407701.
///
/// FIXME(emilio): This is a pretty decent hack, we should try to
/// remove it.
pub fn should_ignore_parsed_value(
_old_display: Self,
_new_display: Self,
) -> bool {
#[cfg(feature = "gecko")]
{
match (_old_display, _new_display) {
(T::_webkit_box, T::_moz_box) |
(T::_webkit_inline_box, T::_moz_inline_box) => {
return true;
}
_ => {},
}
}

return false;
}

/// Returns whether this "display" value is one of the types for
/// ruby.
#[cfg(feature = "gecko")]
Expand Down
10 changes: 7 additions & 3 deletions components/style/stylesheets/keyframes_rule.rs
Expand Up @@ -8,8 +8,8 @@ use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, Parse
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule, SourceLocation};
use error_reporting::{NullReporter, ContextualParseError, ParseErrorReporter};
use parser::{ParserContext, ParserErrorContext};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId, PropertyParserContext};
use properties::{PropertyDeclarationId, LonghandId, SourcePropertyDeclaration};
use properties::{DeclarationSource, Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
use properties::{PropertyDeclarationId, PropertyParserContext, LonghandId, SourcePropertyDeclaration};
use properties::LonghandIdSet;
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
use servo_arc::Arc;
Expand Down Expand Up @@ -549,7 +549,11 @@ impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for KeyframeListPars
while let Some(declaration) = iter.next() {
match declaration {
Ok(()) => {
block.extend(iter.parser.declarations.drain(), Importance::Normal);
block.extend(
iter.parser.declarations.drain(),
Importance::Normal,
DeclarationSource::Parsing,
);
}
Err((error, slice)) => {
iter.parser.declarations.clear();
Expand Down