forked from mirrors/gecko-dev
Bug 1865563 - Rustfmt servo/. r=firefox-style-system-reviewers,emilio
$ git ls-files servo/*.rs | xargs rustup run nightly rustfmt Differential Revision: https://phabricator.services.mozilla.com/D194020
This commit is contained in:
parent
34bd197686
commit
2d02e6d74f
90 changed files with 2441 additions and 1313 deletions
|
|
@ -714,7 +714,8 @@ impl MallocSizeOf for selectors::parser::AncestorHashes {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf for selectors::parser::Selector<Impl>
|
||||
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf
|
||||
for selectors::parser::Selector<Impl>
|
||||
where
|
||||
Impl::NonTSPseudoClass: MallocSizeOf,
|
||||
Impl::PseudoElement: MallocSizeOf,
|
||||
|
|
@ -734,7 +735,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf for selectors::parser::SelectorList<Impl>
|
||||
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf
|
||||
for selectors::parser::SelectorList<Impl>
|
||||
where
|
||||
Impl::NonTSPseudoClass: MallocSizeOf,
|
||||
Impl::PseudoElement: MallocSizeOf,
|
||||
|
|
@ -754,7 +756,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf for selectors::parser::Component<Impl>
|
||||
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf
|
||||
for selectors::parser::Component<Impl>
|
||||
where
|
||||
Impl::NonTSPseudoClass: MallocSizeOf,
|
||||
Impl::PseudoElement: MallocSizeOf,
|
||||
|
|
|
|||
|
|
@ -66,11 +66,7 @@ impl<AttrValue> AttrSelectorOperation<AttrValue> {
|
|||
operator,
|
||||
case_sensitivity,
|
||||
ref value,
|
||||
} => operator.eval_str(
|
||||
element_attr_value,
|
||||
value.as_ref(),
|
||||
case_sensitivity,
|
||||
),
|
||||
} => operator.eval_str(element_attr_value, value.as_ref(), case_sensitivity),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ fn split_from_end<T>(s: &[T], at: usize) -> (&[T], &[T]) {
|
|||
|
||||
/// Flags that indicate at which point of parsing a selector are we.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, ToShmem)]
|
||||
pub (crate) struct SelectorFlags(u8);
|
||||
pub(crate) struct SelectorFlags(u8);
|
||||
|
||||
bitflags! {
|
||||
impl SelectorFlags: u8 {
|
||||
|
|
@ -188,7 +188,7 @@ impl SelectorFlags {
|
|||
///
|
||||
/// It is not supposed to work, because :is(::before) is invalid. We can't propagate the
|
||||
/// pseudo-flags from inner to outer selectors, to avoid breaking our invariants.
|
||||
pub (crate) fn for_nesting() -> Self {
|
||||
pub(crate) fn for_nesting() -> Self {
|
||||
Self::all() - (Self::HAS_PSEUDO | Self::HAS_SLOTTED | Self::HAS_PART)
|
||||
}
|
||||
}
|
||||
|
|
@ -268,7 +268,9 @@ where
|
|||
specificity.element_selectors += 1
|
||||
},
|
||||
Component::Slotted(ref selector) => {
|
||||
flags.insert(SelectorFlags::HAS_SLOTTED | SelectorFlags::HAS_NON_FEATURELESS_COMPONENT);
|
||||
flags.insert(
|
||||
SelectorFlags::HAS_SLOTTED | SelectorFlags::HAS_NON_FEATURELESS_COMPONENT,
|
||||
);
|
||||
specificity.element_selectors += 1;
|
||||
// Note that due to the way ::slotted works we only compete with
|
||||
// other ::slotted rules, so the above rule doesn't really
|
||||
|
|
|
|||
|
|
@ -508,11 +508,7 @@ fn relative_selector_match_early<E: Element>(
|
|||
if context
|
||||
.selector_caches
|
||||
.relative_selector_filter_map
|
||||
.fast_reject(
|
||||
element,
|
||||
selector,
|
||||
context.quirks_mode(),
|
||||
)
|
||||
.fast_reject(element, selector, context.quirks_mode())
|
||||
{
|
||||
// Alright, add as unmatched to cache.
|
||||
context.selector_caches.relative_selector.add(
|
||||
|
|
@ -691,7 +687,9 @@ fn assigned_slot<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E
|
|||
where
|
||||
E: Element,
|
||||
{
|
||||
debug_assert!(element.assigned_slot().map_or(true, |s| s.is_html_slot_element()));
|
||||
debug_assert!(element
|
||||
.assigned_slot()
|
||||
.map_or(true, |s| s.is_html_slot_element()));
|
||||
let scope = context.current_host?;
|
||||
let mut current_slot = element.assigned_slot()?;
|
||||
while current_slot.containing_shadow_host().unwrap().opaque() != scope {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ use fxhash::FxHashMap;
|
|||
|
||||
use crate::bloom::BloomFilter;
|
||||
use crate::context::QuirksMode;
|
||||
use crate::parser::{
|
||||
collect_selector_hashes, RelativeSelector, RelativeSelectorMatchHint,
|
||||
};
|
||||
use crate::parser::{collect_selector_hashes, RelativeSelector, RelativeSelectorMatchHint};
|
||||
use crate::tree::{Element, OpaqueElement};
|
||||
use crate::SelectorImpl;
|
||||
|
||||
|
|
@ -121,7 +119,10 @@ impl RelativeSelectorFilterMap {
|
|||
selector: &RelativeSelector<Impl>,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> bool {
|
||||
if matches!(selector.match_hint, RelativeSelectorMatchHint::InNextSibling) {
|
||||
if matches!(
|
||||
selector.match_hint,
|
||||
RelativeSelectorMatchHint::InNextSibling
|
||||
) {
|
||||
// Don't bother.
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -892,11 +892,7 @@ impl<H, T> UniqueArc<HeaderSlice<H, T>> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_header_and_iter_with_size<I>(
|
||||
header: H,
|
||||
items: I,
|
||||
num_items: usize,
|
||||
) -> Self
|
||||
pub fn from_header_and_iter_with_size<I>(header: H, items: I, num_items: usize) -> Self
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -312,12 +312,8 @@ impl ElementData {
|
|||
return InvalidationResult::empty();
|
||||
}
|
||||
|
||||
let mut processor = StateAndAttrInvalidationProcessor::new(
|
||||
shared_context,
|
||||
element,
|
||||
self,
|
||||
selector_caches,
|
||||
);
|
||||
let mut processor =
|
||||
StateAndAttrInvalidationProcessor::new(shared_context, element, self, selector_caches);
|
||||
|
||||
let invalidator = TreeStyleInvalidator::new(element, stack_limit_checker, &mut processor);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ use crate::invalidation::element::invalidator::{InvalidationProcessor, Invalidat
|
|||
use crate::selector_parser::SelectorImpl;
|
||||
use crate::values::AtomIdent;
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
|
||||
use selectors::matching::{
|
||||
self, MatchingForInvalidation, MatchingContext, MatchingMode, NeedsSelectorFlags,
|
||||
self, MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags,
|
||||
SelectorCaches,
|
||||
};
|
||||
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
|
||||
use selectors::parser::{Combinator, Component, LocalName};
|
||||
use selectors::{Element, SelectorList};
|
||||
use smallvec::SmallVec;
|
||||
|
|
@ -461,11 +461,13 @@ where
|
|||
Component::AttributeInNoNamespaceExists {
|
||||
ref local_name,
|
||||
ref local_name_lower,
|
||||
} => {
|
||||
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||
element.has_attr_in_no_namespace(matching::select_name(&element, local_name, local_name_lower))
|
||||
})
|
||||
},
|
||||
} => collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||
element.has_attr_in_no_namespace(matching::select_name(
|
||||
&element,
|
||||
local_name,
|
||||
local_name_lower,
|
||||
))
|
||||
}),
|
||||
Component::AttributeInNoNamespace {
|
||||
ref local_name,
|
||||
ref value,
|
||||
|
|
@ -480,7 +482,10 @@ where
|
|||
local_name,
|
||||
&AttrSelectorOperation::WithValue {
|
||||
operator,
|
||||
case_sensitivity: matching::to_unconditional_case_sensitivity(case_sensitivity, &element),
|
||||
case_sensitivity: matching::to_unconditional_case_sensitivity(
|
||||
case_sensitivity,
|
||||
&element,
|
||||
),
|
||||
value,
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -54,9 +54,8 @@ fn with_pool_in_place_scope<'scope, R>(
|
|||
if work_unit_max == 0 || pool.is_none() {
|
||||
closure(None)
|
||||
} else {
|
||||
pool.unwrap().in_place_scope_fifo(|scope| {
|
||||
closure(Some(scope))
|
||||
})
|
||||
pool.unwrap()
|
||||
.in_place_scope_fifo(|scope| closure(Some(scope)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +115,11 @@ where
|
|||
thread_local: &mut tlc,
|
||||
};
|
||||
|
||||
debug_assert_eq!(scoped_tls.current_thread_index(), 0, "Main thread should be the first thread");
|
||||
debug_assert_eq!(
|
||||
scoped_tls.current_thread_index(),
|
||||
0,
|
||||
"Main thread should be the first thread"
|
||||
);
|
||||
|
||||
let mut discovered = VecDeque::with_capacity(work_unit_max * 2);
|
||||
discovered.push_back(unsafe { SendNode::new(root.as_node()) });
|
||||
|
|
@ -125,7 +128,9 @@ where
|
|||
discovered,
|
||||
root.as_node().opaque(),
|
||||
work_unit_max,
|
||||
PerLevelTraversalData { current_dom_depth: root.depth() },
|
||||
PerLevelTraversalData {
|
||||
current_dom_depth: root.depth(),
|
||||
},
|
||||
maybe_scope,
|
||||
traversal,
|
||||
&scoped_tls,
|
||||
|
|
|
|||
|
|
@ -19,11 +19,7 @@ use style_traits::ParseError;
|
|||
#[derive(Debug)]
|
||||
pub enum ContextualParseError<'a> {
|
||||
/// A property declaration was not recognized.
|
||||
UnsupportedPropertyDeclaration(
|
||||
&'a str,
|
||||
ParseError<'a>,
|
||||
&'a [SelectorList<SelectorImpl>],
|
||||
),
|
||||
UnsupportedPropertyDeclaration(&'a str, ParseError<'a>, &'a [SelectorList<SelectorImpl>]),
|
||||
/// A property descriptor was not recognized.
|
||||
UnsupportedPropertyDescriptor(&'a str, ParseError<'a>),
|
||||
/// A font face descriptor was not recognized.
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ use crate::gecko_bindings::bindings;
|
|||
use crate::gecko_bindings::structs;
|
||||
use crate::gecko_bindings::structs::ScreenColorGamut;
|
||||
use crate::media_queries::{Device, MediaType};
|
||||
use crate::queries::condition::KleeneValue;
|
||||
use crate::queries::feature::{AllowsRanges, Evaluator, FeatureFlags, QueryFeatureDescription};
|
||||
use crate::queries::values::Orientation;
|
||||
use crate::queries::condition::KleeneValue;
|
||||
use crate::values::computed::{CSSPixelLength, Context, Ratio, Resolution};
|
||||
use crate::values::AtomString;
|
||||
use app_units::Au;
|
||||
|
|
@ -615,10 +615,10 @@ fn eval_moz_overlay_scrollbars(context: &Context) -> bool {
|
|||
}
|
||||
|
||||
fn eval_moz_bool_pref(_: &Context, pref: Option<&AtomString>) -> KleeneValue {
|
||||
let Some(pref) = pref else { return KleeneValue::False };
|
||||
KleeneValue::from(unsafe {
|
||||
bindings::Gecko_ComputeBoolPrefMediaQuery(pref.as_ptr())
|
||||
})
|
||||
let Some(pref) = pref else {
|
||||
return KleeneValue::False;
|
||||
};
|
||||
KleeneValue::from(unsafe { bindings::Gecko_ComputeBoolPrefMediaQuery(pref.as_ptr()) })
|
||||
}
|
||||
|
||||
fn get_lnf_int(int_id: i32) -> i32 {
|
||||
|
|
|
|||
|
|
@ -168,10 +168,12 @@ impl PseudoElement {
|
|||
pub fn enabled_in_content(&self) -> bool {
|
||||
match *self {
|
||||
Self::Highlight(..) => pref!("dom.customHighlightAPI.enabled"),
|
||||
Self::SliderFill | Self::SliderTrack | Self::SliderThumb => pref!("layout.css.modern-range-pseudos.enabled"),
|
||||
Self::SliderFill | Self::SliderTrack | Self::SliderThumb => {
|
||||
pref!("layout.css.modern-range-pseudos.enabled")
|
||||
},
|
||||
// If it's not explicitly enabled in UA sheets or chrome, then we're enabled for
|
||||
// content.
|
||||
_ => (self.flags() & structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME) == 0
|
||||
_ => (self.flags() & structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME) == 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ use crate::selector_parser::{AttrValue, SnapshotMap};
|
|||
use crate::string_cache::WeakAtom;
|
||||
use crate::values::AtomIdent;
|
||||
use crate::{Atom, CaseSensitivityExt, LocalName, Namespace};
|
||||
use selectors::attr::{CaseSensitivity, NamespaceConstraint, AttrSelectorOperation, AttrSelectorOperator};
|
||||
use selectors::attr::{
|
||||
AttrSelectorOperation, AttrSelectorOperator, CaseSensitivity, NamespaceConstraint,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
/// A function that, given an element of type `T`, allows you to get a single
|
||||
|
|
@ -291,36 +293,24 @@ fn attr_matches_checked_name(
|
|||
let value = value.as_ptr();
|
||||
unsafe {
|
||||
match operator {
|
||||
AttrSelectorOperator::Equal => bindings::Gecko_AttrEquals(
|
||||
&attr.mValue,
|
||||
value,
|
||||
ignore_case,
|
||||
),
|
||||
AttrSelectorOperator::Includes => bindings::Gecko_AttrIncludes(
|
||||
&attr.mValue,
|
||||
value,
|
||||
ignore_case,
|
||||
),
|
||||
AttrSelectorOperator::DashMatch => bindings::Gecko_AttrDashEquals(
|
||||
&attr.mValue,
|
||||
value,
|
||||
ignore_case,
|
||||
),
|
||||
AttrSelectorOperator::Prefix => bindings::Gecko_AttrHasPrefix(
|
||||
&attr.mValue,
|
||||
value,
|
||||
ignore_case,
|
||||
),
|
||||
AttrSelectorOperator::Suffix => bindings::Gecko_AttrHasSuffix(
|
||||
&attr.mValue,
|
||||
value,
|
||||
ignore_case,
|
||||
),
|
||||
AttrSelectorOperator::Substring => bindings::Gecko_AttrHasSubstring(
|
||||
&attr.mValue,
|
||||
value,
|
||||
ignore_case,
|
||||
),
|
||||
AttrSelectorOperator::Equal => {
|
||||
bindings::Gecko_AttrEquals(&attr.mValue, value, ignore_case)
|
||||
},
|
||||
AttrSelectorOperator::Includes => {
|
||||
bindings::Gecko_AttrIncludes(&attr.mValue, value, ignore_case)
|
||||
},
|
||||
AttrSelectorOperator::DashMatch => {
|
||||
bindings::Gecko_AttrDashEquals(&attr.mValue, value, ignore_case)
|
||||
},
|
||||
AttrSelectorOperator::Prefix => {
|
||||
bindings::Gecko_AttrHasPrefix(&attr.mValue, value, ignore_case)
|
||||
},
|
||||
AttrSelectorOperator::Suffix => {
|
||||
bindings::Gecko_AttrHasSuffix(&attr.mValue, value, ignore_case)
|
||||
},
|
||||
AttrSelectorOperator::Substring => {
|
||||
bindings::Gecko_AttrHasSubstring(&attr.mValue, value, ignore_case)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,7 +304,8 @@ impl<'ln> GeckoNode<'ln> {
|
|||
|
||||
#[inline]
|
||||
fn set_selector_flags(&self, flags: u32) {
|
||||
self.selector_flags_atomic().fetch_or(flags, Ordering::Relaxed);
|
||||
self.selector_flags_atomic()
|
||||
.fetch_or(flags, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -1250,9 +1251,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
F: FnMut(&AtomIdent),
|
||||
{
|
||||
for attr in self.attrs() {
|
||||
unsafe {
|
||||
AtomIdent::with(attr.mName.name(), |a| callback(a))
|
||||
}
|
||||
unsafe { AtomIdent::with(attr.mName.name(), |a| callback(a)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1366,7 +1365,10 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
return None;
|
||||
}
|
||||
|
||||
PseudoElement::from_pseudo_type(unsafe { bindings::Gecko_GetImplementedPseudo(self.0) }, None)
|
||||
PseudoElement::from_pseudo_type(
|
||||
unsafe { bindings::Gecko_GetImplementedPseudo(self.0) },
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -1889,7 +1891,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
// Handle flags that apply to the element.
|
||||
let self_flags = flags.for_self();
|
||||
if !self_flags.is_empty() {
|
||||
self.as_node().set_selector_flags(selector_flags_to_node_flags(flags))
|
||||
self.as_node()
|
||||
.set_selector_flags(selector_flags_to_node_flags(flags))
|
||||
}
|
||||
|
||||
// Handle flags that apply to the parent.
|
||||
|
|
@ -2016,7 +2019,9 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
NonTSPseudoClass::MozRevealed |
|
||||
NonTSPseudoClass::MozValueEmpty => self.state().intersects(pseudo_class.state_flag()),
|
||||
// TODO: This applying only to HTML elements is weird.
|
||||
NonTSPseudoClass::Dir(ref dir) => self.is_html_element() && self.state().intersects(dir.element_state()),
|
||||
NonTSPseudoClass::Dir(ref dir) => {
|
||||
self.is_html_element() && self.state().intersects(dir.element_state())
|
||||
},
|
||||
NonTSPseudoClass::AnyLink => self.is_link(),
|
||||
NonTSPseudoClass::Link => {
|
||||
self.is_link() && context.visited_handling().matches_unvisited()
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ use crate::thread_state;
|
|||
use gecko_profiler;
|
||||
use parking_lot::{Mutex, RwLock, RwLockReadGuard};
|
||||
use rayon;
|
||||
use std::{io, thread};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::thread::{JoinHandleExt, RawPthread};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::{io::AsRawHandle, prelude::RawHandle};
|
||||
use std::{io, thread};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
/// Platform-specific handle to a thread.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::invalidation::element::state_and_attributes;
|
|||
use crate::stylist::CascadeData;
|
||||
use dom::DocumentState;
|
||||
use selectors::matching::{
|
||||
MatchingForInvalidation, MatchingContext, MatchingMode, NeedsSelectorFlags, QuirksMode,
|
||||
MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags, QuirksMode,
|
||||
SelectorCaches, VisitedHandlingMode,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -163,7 +163,10 @@ impl Dependency {
|
|||
/// The kind of normal invalidation that this would generate. The dependency
|
||||
/// in question must be a normal dependency.
|
||||
pub fn normal_invalidation_kind(&self) -> NormalDependencyInvalidationKind {
|
||||
debug_assert!(self.relative_kind.is_none(), "Querying normal invalidation kind on relative dependency.");
|
||||
debug_assert!(
|
||||
self.relative_kind.is_none(),
|
||||
"Querying normal invalidation kind on relative dependency."
|
||||
);
|
||||
match self.combinator() {
|
||||
None => NormalDependencyInvalidationKind::Element,
|
||||
Some(Combinator::Child) | Some(Combinator::Descendant) => {
|
||||
|
|
@ -174,7 +177,9 @@ impl Dependency {
|
|||
},
|
||||
// TODO(emilio): We could look at the selector itself to see if it's
|
||||
// an eager pseudo, and return only Descendants here if not.
|
||||
Some(Combinator::PseudoElement) => NormalDependencyInvalidationKind::ElementAndDescendants,
|
||||
Some(Combinator::PseudoElement) => {
|
||||
NormalDependencyInvalidationKind::ElementAndDescendants
|
||||
},
|
||||
Some(Combinator::SlotAssignment) => NormalDependencyInvalidationKind::SlottedElements,
|
||||
Some(Combinator::Part) => NormalDependencyInvalidationKind::Parts,
|
||||
}
|
||||
|
|
@ -197,7 +202,8 @@ impl Dependency {
|
|||
return false;
|
||||
}
|
||||
matches!(
|
||||
self.selector.combinator_at_match_order(self.selector_offset - 1),
|
||||
self.selector
|
||||
.combinator_at_match_order(self.selector_offset - 1),
|
||||
Combinator::NextSibling
|
||||
)
|
||||
}
|
||||
|
|
@ -209,8 +215,9 @@ impl Dependency {
|
|||
pub fn dependency_is_relative_with_single_next_sibling(&self) -> bool {
|
||||
match self.invalidation_kind() {
|
||||
DependencyInvalidationKind::Normal(_) => false,
|
||||
DependencyInvalidationKind::Relative(kind) =>
|
||||
kind == RelativeDependencyInvalidationKind::PrevSibling,
|
||||
DependencyInvalidationKind::Relative(kind) => {
|
||||
kind == RelativeDependencyInvalidationKind::PrevSibling
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1030,7 +1037,9 @@ impl<'a> Collector for RelativeSelectorDependencyCollector<'a> {
|
|||
selector_offset: self.compound_state.state.offset,
|
||||
relative_kind: Some(match self.combinator_count.get_match_hint() {
|
||||
RelativeSelectorMatchHint::InChild => RelativeDependencyInvalidationKind::Parent,
|
||||
RelativeSelectorMatchHint::InSubtree => RelativeDependencyInvalidationKind::Ancestors,
|
||||
RelativeSelectorMatchHint::InSubtree => {
|
||||
RelativeDependencyInvalidationKind::Ancestors
|
||||
},
|
||||
RelativeSelectorMatchHint::InNextSibling => {
|
||||
RelativeDependencyInvalidationKind::PrevSibling
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
use crate::context::StackLimitChecker;
|
||||
use crate::dom::{TElement, TNode, TShadowRoot};
|
||||
use crate::invalidation::element::invalidation_map::{
|
||||
Dependency, NormalDependencyInvalidationKind, DependencyInvalidationKind, RelativeDependencyInvalidationKind
|
||||
Dependency, DependencyInvalidationKind, NormalDependencyInvalidationKind,
|
||||
RelativeDependencyInvalidationKind,
|
||||
};
|
||||
use selectors::matching::matches_compound_selector_from;
|
||||
use selectors::matching::{CompoundSelectorMatchingResult, MatchingContext};
|
||||
|
|
@ -272,7 +273,8 @@ impl<'a> Invalidation<'a> {
|
|||
pub fn new(dependency: &'a Dependency, scope: Option<OpaqueElement>) -> Self {
|
||||
debug_assert!(
|
||||
dependency.selector_offset == dependency.selector.len() + 1 ||
|
||||
dependency.normal_invalidation_kind() != NormalDependencyInvalidationKind::Element,
|
||||
dependency.normal_invalidation_kind() !=
|
||||
NormalDependencyInvalidationKind::Element,
|
||||
"No point to this, if the dependency matched the element we should just invalidate it"
|
||||
);
|
||||
Self {
|
||||
|
|
@ -936,8 +938,11 @@ where
|
|||
match invalidation_kind {
|
||||
DependencyInvalidationKind::Normal(_) => &**p,
|
||||
DependencyInvalidationKind::Relative(kind) => {
|
||||
self.processor
|
||||
.found_relative_selector_invalidation(self.element, kind, &**p);
|
||||
self.processor.found_relative_selector_invalidation(
|
||||
self.element,
|
||||
kind,
|
||||
&**p,
|
||||
);
|
||||
return SingleInvalidationResult {
|
||||
invalidated_self: false,
|
||||
matched: true,
|
||||
|
|
@ -962,7 +967,9 @@ where
|
|||
};
|
||||
}
|
||||
|
||||
if cur_dependency.normal_invalidation_kind() == NormalDependencyInvalidationKind::Element {
|
||||
if cur_dependency.normal_invalidation_kind() ==
|
||||
NormalDependencyInvalidationKind::Element
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@ pub mod document_state;
|
|||
pub mod element_wrapper;
|
||||
pub mod invalidation_map;
|
||||
pub mod invalidator;
|
||||
pub mod relative_selector;
|
||||
pub mod restyle_hints;
|
||||
pub mod state_and_attributes;
|
||||
pub mod relative_selector;
|
||||
|
|
|
|||
|
|
@ -348,7 +348,11 @@ where
|
|||
dependency: &'a Dependency,
|
||||
host: Option<OpaqueElement>,
|
||||
) {
|
||||
match self.invalidations.iter_mut().find(|(_, _, d)| dependency_selectors_match(dependency, d)) {
|
||||
match self
|
||||
.invalidations
|
||||
.iter_mut()
|
||||
.find(|(_, _, d)| dependency_selectors_match(dependency, d))
|
||||
{
|
||||
Some((e, h, d)) => {
|
||||
// Just keep one.
|
||||
if d.selector_offset > dependency.selector_offset {
|
||||
|
|
@ -357,7 +361,7 @@ where
|
|||
},
|
||||
None => {
|
||||
self.invalidations.push((element, host, dependency));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -392,11 +396,7 @@ where
|
|||
{
|
||||
return;
|
||||
}
|
||||
self.insert_invalidation(
|
||||
element,
|
||||
dependency,
|
||||
host,
|
||||
);
|
||||
self.insert_invalidation(element, dependency, host);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -411,12 +411,7 @@ where
|
|||
},
|
||||
DependencyInvalidationKind::Relative(kind) => {
|
||||
if let Some(context) = self.optimization_context.as_ref() {
|
||||
if context.can_be_ignored(
|
||||
element != self.top,
|
||||
element,
|
||||
host,
|
||||
dependency,
|
||||
) {
|
||||
if context.can_be_ignored(element != self.top, element, host, dependency) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ use crate::{Atom, WeakAtom};
|
|||
use dom::ElementState;
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use selectors::matching::{
|
||||
matches_selector, MatchingForInvalidation, MatchingContext, MatchingMode,
|
||||
NeedsSelectorFlags, SelectorCaches, VisitedHandlingMode,
|
||||
matches_selector, MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags,
|
||||
SelectorCaches, VisitedHandlingMode,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
|
@ -239,7 +239,9 @@ where
|
|||
let wrapper = ElementWrapper::new(element, &*self.shared_context.snapshot_map);
|
||||
|
||||
let state_changes = wrapper.state_changes();
|
||||
let Some(snapshot) = wrapper.snapshot() else { return false };
|
||||
let Some(snapshot) = wrapper.snapshot() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if !snapshot.has_attrs() && state_changes.is_empty() {
|
||||
return false;
|
||||
|
|
@ -485,8 +487,12 @@ where
|
|||
|
||||
fn scan_dependency(&mut self, dependency: &'selectors Dependency) {
|
||||
debug_assert!(
|
||||
matches!(dependency.invalidation_kind(), DependencyInvalidationKind::Normal(_)),
|
||||
"Found relative selector dependency");
|
||||
matches!(
|
||||
dependency.invalidation_kind(),
|
||||
DependencyInvalidationKind::Normal(_)
|
||||
),
|
||||
"Found relative selector dependency"
|
||||
);
|
||||
debug!(
|
||||
"TreeStyleInvalidator::scan_dependency({:?}, {:?})",
|
||||
self.element, dependency
|
||||
|
|
@ -535,7 +541,9 @@ where
|
|||
fn dependency_may_be_relevant(&self, dependency: &Dependency) -> bool {
|
||||
match dependency.normal_invalidation_kind() {
|
||||
NormalDependencyInvalidationKind::Element => !self.invalidates_self,
|
||||
NormalDependencyInvalidationKind::SlottedElements => self.element.is_html_slot_element(),
|
||||
NormalDependencyInvalidationKind::SlottedElements => {
|
||||
self.element.is_html_slot_element()
|
||||
},
|
||||
NormalDependencyInvalidationKind::Parts => self.element.shadow_root().is_some(),
|
||||
NormalDependencyInvalidationKind::ElementAndDescendants |
|
||||
NormalDependencyInvalidationKind::Siblings |
|
||||
|
|
|
|||
|
|
@ -152,7 +152,13 @@ impl StylesheetInvalidationSet {
|
|||
|
||||
let quirks_mode = device.quirks_mode();
|
||||
for rule in stylesheet.effective_rules(device, guard) {
|
||||
self.collect_invalidations_for_rule(rule, guard, device, quirks_mode, /* is_generic_change = */ false);
|
||||
self.collect_invalidations_for_rule(
|
||||
rule,
|
||||
guard,
|
||||
device,
|
||||
quirks_mode,
|
||||
/* is_generic_change = */ false,
|
||||
);
|
||||
if self.fully_invalid {
|
||||
break;
|
||||
}
|
||||
|
|
@ -549,16 +555,19 @@ impl StylesheetInvalidationSet {
|
|||
return;
|
||||
}
|
||||
|
||||
if !is_generic_change &&
|
||||
!EffectiveRules::is_effective(guard, device, quirks_mode, rule)
|
||||
{
|
||||
if !is_generic_change && !EffectiveRules::is_effective(guard, device, quirks_mode, rule) {
|
||||
return;
|
||||
}
|
||||
|
||||
let rules =
|
||||
EffectiveRulesIterator::effective_children(device, quirks_mode, guard, rule);
|
||||
let rules = EffectiveRulesIterator::effective_children(device, quirks_mode, guard, rule);
|
||||
for rule in rules {
|
||||
self.collect_invalidations_for_rule(rule, guard, device, quirks_mode, /* is_generic_change = */ false);
|
||||
self.collect_invalidations_for_rule(
|
||||
rule,
|
||||
guard,
|
||||
device,
|
||||
quirks_mode,
|
||||
/* is_generic_change = */ false,
|
||||
);
|
||||
if self.fully_invalid {
|
||||
break;
|
||||
}
|
||||
|
|
@ -606,8 +615,8 @@ impl StylesheetInvalidationSet {
|
|||
// invalidate fully.
|
||||
return self.invalidate_fully();
|
||||
},
|
||||
Document(..) | Import(..) | Media(..) | Supports(..) |
|
||||
Container(..) | LayerBlock(..) => {
|
||||
Document(..) | Import(..) | Media(..) | Supports(..) | Container(..) |
|
||||
LayerBlock(..) => {
|
||||
// Do nothing, relevant nested rules are visited as part of rule iteration.
|
||||
},
|
||||
FontFace(..) => {
|
||||
|
|
@ -633,10 +642,7 @@ impl StylesheetInvalidationSet {
|
|||
// Do nothing, this animation can't affect the style of existing elements.
|
||||
}
|
||||
},
|
||||
CounterStyle(..) |
|
||||
Property(..) |
|
||||
FontFeatureValues(..) |
|
||||
FontPaletteValues(..) => {
|
||||
CounterStyle(..) | Property(..) | FontFeatureValues(..) | FontPaletteValues(..) => {
|
||||
debug!(" > Found unsupported rule, marking the whole subtree invalid.");
|
||||
self.invalidate_fully();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1478,10 +1478,10 @@ impl LogicalSide {
|
|||
pub fn to_physical(self, wm: WritingMode) -> PhysicalSide {
|
||||
// Block mapping depends only on vertical+vertical-lr
|
||||
static BLOCK_MAPPING: [[PhysicalSide; 2]; 4] = [
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // horizontal-tb
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // vertical-rl
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // (horizontal-bt)
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // vertical-lr
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // horizontal-tb
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // vertical-rl
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // (horizontal-bt)
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // vertical-lr
|
||||
];
|
||||
|
||||
if self.is_block() {
|
||||
|
|
@ -1506,34 +1506,35 @@ impl LogicalSide {
|
|||
// text. (The former 'sideways-left' value, no longer in the spec, would have produced
|
||||
// this in vertical-rl mode.)
|
||||
static INLINE_MAPPING: [[PhysicalSide; 2]; 16] = [
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // horizontal-tb ltr
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // vertical-rl ltr
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // horizontal-tb rtl
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // vertical-rl rtl
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // (horizontal-bt) (inverted) ltr
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // sideways-lr rtl
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // (horizontal-bt) (inverted) rtl
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // sideways-lr ltr
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // horizontal-tb (inverted) rtl
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // vertical-rl (inverted) rtl
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // horizontal-tb (inverted) ltr
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // vertical-rl (inverted) ltr
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // (horizontal-bt) ltr
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // vertical-lr ltr
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // (horizontal-bt) rtl
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // vertical-lr rtl
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // horizontal-tb ltr
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // vertical-rl ltr
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // horizontal-tb rtl
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // vertical-rl rtl
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // (horizontal-bt) (inverted) ltr
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // sideways-lr rtl
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // (horizontal-bt) (inverted) rtl
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // sideways-lr ltr
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // horizontal-tb (inverted) rtl
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // vertical-rl (inverted) rtl
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // horizontal-tb (inverted) ltr
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // vertical-rl (inverted) ltr
|
||||
[PhysicalSide::Left, PhysicalSide::Right], // (horizontal-bt) ltr
|
||||
[PhysicalSide::Top, PhysicalSide::Bottom], // vertical-lr ltr
|
||||
[PhysicalSide::Right, PhysicalSide::Left], // (horizontal-bt) rtl
|
||||
[PhysicalSide::Bottom, PhysicalSide::Top], // vertical-lr rtl
|
||||
];
|
||||
|
||||
debug_assert!(WritingMode::VERTICAL.bits() == 0x01 &&
|
||||
WritingMode::INLINE_REVERSED.bits() == 0x02 &&
|
||||
WritingMode::VERTICAL_LR.bits() == 0x04 &&
|
||||
WritingMode::LINE_INVERTED.bits() == 0x08);
|
||||
debug_assert!(
|
||||
WritingMode::VERTICAL.bits() == 0x01 &&
|
||||
WritingMode::INLINE_REVERSED.bits() == 0x02 &&
|
||||
WritingMode::VERTICAL_LR.bits() == 0x04 &&
|
||||
WritingMode::LINE_INVERTED.bits() == 0x08
|
||||
);
|
||||
let index = (wm.bits() & 0xF) as usize;
|
||||
INLINE_MAPPING[index][edge]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum LogicalCorner {
|
||||
|
|
@ -1598,10 +1599,30 @@ impl PhysicalCorner {
|
|||
// sides were to be parallel, we fall back to returning TopLeft.
|
||||
const IMPOSSIBLE: PhysicalCorner = PhysicalCorner::TopLeft;
|
||||
static SIDES_TO_CORNER: [[PhysicalCorner; 4]; 4] = [
|
||||
[IMPOSSIBLE, PhysicalCorner::TopRight, IMPOSSIBLE, PhysicalCorner::TopLeft ],
|
||||
[PhysicalCorner::TopRight, IMPOSSIBLE, PhysicalCorner::BottomRight, IMPOSSIBLE ],
|
||||
[IMPOSSIBLE, PhysicalCorner::BottomRight, IMPOSSIBLE, PhysicalCorner::BottomLeft ],
|
||||
[PhysicalCorner::TopLeft, IMPOSSIBLE, PhysicalCorner::BottomLeft, IMPOSSIBLE ],
|
||||
[
|
||||
IMPOSSIBLE,
|
||||
PhysicalCorner::TopRight,
|
||||
IMPOSSIBLE,
|
||||
PhysicalCorner::TopLeft,
|
||||
],
|
||||
[
|
||||
PhysicalCorner::TopRight,
|
||||
IMPOSSIBLE,
|
||||
PhysicalCorner::BottomRight,
|
||||
IMPOSSIBLE,
|
||||
],
|
||||
[
|
||||
IMPOSSIBLE,
|
||||
PhysicalCorner::BottomRight,
|
||||
IMPOSSIBLE,
|
||||
PhysicalCorner::BottomLeft,
|
||||
],
|
||||
[
|
||||
PhysicalCorner::TopLeft,
|
||||
IMPOSSIBLE,
|
||||
PhysicalCorner::BottomLeft,
|
||||
IMPOSSIBLE,
|
||||
],
|
||||
];
|
||||
SIDES_TO_CORNER[a as usize][b as usize]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ pub const STACK_SAFETY_MARGIN_KB: usize = 168;
|
|||
/// out of line so we don't allocate stack space for the entire struct
|
||||
/// in the caller.
|
||||
#[inline(never)]
|
||||
pub (crate) fn create_thread_local_context<'scope, E>(slot: &mut Option<ThreadLocalStyleContext<E>>)
|
||||
pub(crate) fn create_thread_local_context<'scope, E>(slot: &mut Option<ThreadLocalStyleContext<E>>)
|
||||
where
|
||||
E: TElement + 'scope,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -208,10 +208,12 @@ impl PiecewiseLinearFunctionBuilder {
|
|||
if self.entries.len() == 1 {
|
||||
// Don't bother resolving anything.
|
||||
return PiecewiseLinearFunction {
|
||||
entries: crate::ArcSlice::from_iter(std::iter::once(PiecewiseLinearFunctionEntry {
|
||||
x: 0.,
|
||||
y: self.entries[0].y,
|
||||
})),
|
||||
entries: crate::ArcSlice::from_iter(std::iter::once(
|
||||
PiecewiseLinearFunctionEntry {
|
||||
x: 0.,
|
||||
y: self.entries[0].y,
|
||||
},
|
||||
)),
|
||||
};
|
||||
}
|
||||
// Guaranteed at least two elements.
|
||||
|
|
|
|||
|
|
@ -297,7 +297,8 @@ where
|
|||
let mut shorthand_cache = ShorthandsWithPropertyReferencesCache::default();
|
||||
let properties_to_apply = match cascade_mode {
|
||||
CascadeMode::Visited { unvisited_context } => {
|
||||
cascade.context.builder.custom_properties = unvisited_context.builder.custom_properties.clone();
|
||||
cascade.context.builder.custom_properties =
|
||||
unvisited_context.builder.custom_properties.clone();
|
||||
cascade.context.builder.writing_mode = unvisited_context.builder.writing_mode;
|
||||
// We never insert visited styles into the cache so we don't need to try looking it up.
|
||||
// It also wouldn't be super-profitable, only a handful :visited properties are
|
||||
|
|
@ -340,7 +341,11 @@ where
|
|||
},
|
||||
};
|
||||
|
||||
cascade.apply_non_prioritary_properties(&declarations.longhand_declarations, &mut shorthand_cache, &properties_to_apply);
|
||||
cascade.apply_non_prioritary_properties(
|
||||
&declarations.longhand_declarations,
|
||||
&mut shorthand_cache,
|
||||
&properties_to_apply,
|
||||
);
|
||||
|
||||
cascade.finished_applying_properties();
|
||||
|
||||
|
|
@ -690,12 +695,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
);
|
||||
loop {
|
||||
let decl = decls.longhand_declarations[index as usize];
|
||||
self.apply_one_longhand(
|
||||
longhand_id,
|
||||
decl.decl,
|
||||
decl.priority,
|
||||
cache,
|
||||
);
|
||||
self.apply_one_longhand(longhand_id, decl.decl, decl.priority, cache);
|
||||
if self.seen.contains(longhand_id) {
|
||||
return true; // Common case, we're done.
|
||||
}
|
||||
|
|
@ -717,15 +717,23 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
false
|
||||
}
|
||||
|
||||
fn apply_prioritary_properties(&mut self, decls: &Declarations, cache: &mut ShorthandsWithPropertyReferencesCache) {
|
||||
fn apply_prioritary_properties(
|
||||
&mut self,
|
||||
decls: &Declarations,
|
||||
cache: &mut ShorthandsWithPropertyReferencesCache,
|
||||
) {
|
||||
if !decls.has_prioritary_properties {
|
||||
return;
|
||||
}
|
||||
|
||||
let has_writing_mode = self
|
||||
.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::WritingMode) |
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::Direction) |
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::TextOrientation);
|
||||
let has_writing_mode =
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::WritingMode) |
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::Direction) |
|
||||
self.apply_one_prioritary_property(
|
||||
decls,
|
||||
cache,
|
||||
PrioritaryPropertyId::TextOrientation,
|
||||
);
|
||||
if has_writing_mode {
|
||||
self.compute_writing_mode();
|
||||
}
|
||||
|
|
@ -737,7 +745,8 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
// Compute font-family.
|
||||
let has_font_family =
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::FontFamily);
|
||||
let has_lang = self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::XLang);
|
||||
let has_lang =
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::XLang);
|
||||
if has_lang {
|
||||
self.recompute_initial_font_family_if_needed();
|
||||
}
|
||||
|
|
@ -753,8 +762,11 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::FontSize);
|
||||
let has_math_depth =
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::MathDepth);
|
||||
let has_min_font_size_ratio =
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::MozMinFontSizeRatio);
|
||||
let has_min_font_size_ratio = self.apply_one_prioritary_property(
|
||||
decls,
|
||||
cache,
|
||||
PrioritaryPropertyId::MozMinFontSizeRatio,
|
||||
);
|
||||
|
||||
if has_math_depth && has_font_size {
|
||||
self.recompute_math_font_size_if_needed();
|
||||
|
|
@ -796,7 +808,10 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
let is_logical = longhand_id.is_logical();
|
||||
if is_logical {
|
||||
let wm = self.context.builder.writing_mode;
|
||||
self.context.rule_cache_conditions.borrow_mut().set_writing_mode_dependency(wm);
|
||||
self.context
|
||||
.rule_cache_conditions
|
||||
.borrow_mut()
|
||||
.set_writing_mode_dependency(wm);
|
||||
longhand_id = longhand_id.to_physical(wm);
|
||||
}
|
||||
self.apply_one_longhand(
|
||||
|
|
@ -834,9 +849,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
}
|
||||
|
||||
if self.reverted_set.contains(longhand_id) {
|
||||
if let Some(&(reverted_priority, is_origin_revert)) =
|
||||
self.reverted.get(&longhand_id)
|
||||
{
|
||||
if let Some(&(reverted_priority, is_origin_revert)) = self.reverted.get(&longhand_id) {
|
||||
if !reverted_priority.allows_when_reverted(&priority, is_origin_revert) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -864,8 +877,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
// We intentionally don't want to insert it into `self.seen`, `reverted` takes
|
||||
// care of rejecting other declarations as needed.
|
||||
self.reverted_set.insert(longhand_id);
|
||||
self.reverted
|
||||
.insert(longhand_id, (priority, origin_revert));
|
||||
self.reverted.insert(longhand_id, (priority, origin_revert));
|
||||
return;
|
||||
},
|
||||
CSSWideKeyword::Unset => true,
|
||||
|
|
@ -884,13 +896,15 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.do_apply_declaration(longhand_id, &declaration)
|
||||
}
|
||||
unsafe { self.do_apply_declaration(longhand_id, &declaration) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn do_apply_declaration(&mut self, longhand_id: LonghandId, declaration: &PropertyDeclaration) {
|
||||
unsafe fn do_apply_declaration(
|
||||
&mut self,
|
||||
longhand_id: LonghandId,
|
||||
declaration: &PropertyDeclaration,
|
||||
) {
|
||||
debug_assert!(!longhand_id.is_logical());
|
||||
// We could (and used to) use a pattern match here, but that bloats this
|
||||
// function to over 100K of compiled code!
|
||||
|
|
@ -945,7 +959,9 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
visited_parent!(parent_style),
|
||||
visited_parent!(layout_parent_style),
|
||||
self.first_line_reparenting,
|
||||
CascadeMode::Visited { unvisited_context: &*self.context },
|
||||
CascadeMode::Visited {
|
||||
unvisited_context: &*self.context,
|
||||
},
|
||||
// Cascade input flags don't matter for the visited style, they are
|
||||
// in the main (unvisited) style.
|
||||
Default::default(),
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
//! Registered custom properties.
|
||||
|
||||
use crate::Atom;
|
||||
use super::rule::{Inherits, InitialValue, PropertyRuleName};
|
||||
use super::syntax::Descriptor;
|
||||
use crate::selector_map::PrecomputedHashMap;
|
||||
use crate::stylesheets::UrlExtraData;
|
||||
use crate::Atom;
|
||||
use cssparser::SourceLocation;
|
||||
use super::syntax::Descriptor;
|
||||
use super::rule::{InitialValue, Inherits, PropertyRuleName};
|
||||
|
||||
/// A computed, already-validated property registration.
|
||||
/// <https://drafts.css-houdini.org/css-properties-values-api-1/#custom-property-registration>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
//! https://drafts.css-houdini.org/css-properties-values-api-1/#at-property-rule
|
||||
|
||||
use super::{
|
||||
syntax::Descriptor,
|
||||
registry::PropertyRegistration,
|
||||
syntax::Descriptor,
|
||||
value::{AllowComputationallyDependent, SpecifiedValue as SpecifiedRegisteredValue},
|
||||
};
|
||||
use crate::custom_properties::{Name as CustomPropertyName, SpecifiedValue};
|
||||
|
|
@ -71,15 +71,21 @@ pub fn parse_property_block<'i, 't>(
|
|||
//
|
||||
// The syntax descriptor is required for the @property rule to be valid; if it’s
|
||||
// missing, the @property rule is invalid.
|
||||
let Some(syntax) = descriptors.syntax else { return Err(input.new_error(BasicParseErrorKind::AtRuleBodyInvalid)) };
|
||||
let Some(syntax) = descriptors.syntax else {
|
||||
return Err(input.new_error(BasicParseErrorKind::AtRuleBodyInvalid));
|
||||
};
|
||||
|
||||
// https://drafts.css-houdini.org/css-properties-values-api-1/#inherits-descriptor:
|
||||
//
|
||||
// The inherits descriptor is required for the @property rule to be valid; if it’s
|
||||
// missing, the @property rule is invalid.
|
||||
let Some(inherits) = descriptors.inherits else { return Err(input.new_error(BasicParseErrorKind::AtRuleBodyInvalid)) };
|
||||
let Some(inherits) = descriptors.inherits else {
|
||||
return Err(input.new_error(BasicParseErrorKind::AtRuleBodyInvalid));
|
||||
};
|
||||
|
||||
if PropertyRegistration::validate_initial_value(&syntax, descriptors.initial_value.as_ref()).is_err() {
|
||||
if PropertyRegistration::validate_initial_value(&syntax, descriptors.initial_value.as_ref())
|
||||
.is_err()
|
||||
{
|
||||
return Err(input.new_error(BasicParseErrorKind::AtRuleBodyInvalid));
|
||||
}
|
||||
|
||||
|
|
@ -239,7 +245,7 @@ impl PropertyRegistration {
|
|||
// initial-value descriptor is optional. If omitted, the initial value of the property is
|
||||
// the guaranteed-invalid value.
|
||||
if syntax.is_universal() && initial_value.is_none() {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Otherwise, if the value of the syntax descriptor is not the universal syntax definition,
|
||||
|
|
@ -247,7 +253,7 @@ impl PropertyRegistration {
|
|||
|
||||
// The initial-value descriptor must be present.
|
||||
let Some(initial) = initial_value else {
|
||||
return Err(PropertyRegistrationError::NoInitialValue)
|
||||
return Err(PropertyRegistrationError::NoInitialValue);
|
||||
};
|
||||
|
||||
// A value that references the environment or other variables is not computationally
|
||||
|
|
|
|||
|
|
@ -90,25 +90,23 @@ impl ToCss for DataType {
|
|||
W: Write,
|
||||
{
|
||||
dest.write_char('<')?;
|
||||
dest.write_str(
|
||||
match *self {
|
||||
DataType::Length => "length",
|
||||
DataType::Number => "number",
|
||||
DataType::Percentage => "percentage",
|
||||
DataType::LengthPercentage => "length-percentage",
|
||||
DataType::Color => "color",
|
||||
DataType::Image => "image",
|
||||
DataType::Url => "url",
|
||||
DataType::Integer => "integer",
|
||||
DataType::Angle => "angle",
|
||||
DataType::Time => "time",
|
||||
DataType::Resolution => "resolution",
|
||||
DataType::TransformFunction => "transform-function",
|
||||
DataType::CustomIdent => "custom-ident",
|
||||
DataType::TransformList => "transform-list",
|
||||
DataType::String => "string",
|
||||
}
|
||||
)?;
|
||||
dest.write_str(match *self {
|
||||
DataType::Length => "length",
|
||||
DataType::Number => "number",
|
||||
DataType::Percentage => "percentage",
|
||||
DataType::LengthPercentage => "length-percentage",
|
||||
DataType::Color => "color",
|
||||
DataType::Image => "image",
|
||||
DataType::Url => "url",
|
||||
DataType::Integer => "integer",
|
||||
DataType::Angle => "angle",
|
||||
DataType::Time => "time",
|
||||
DataType::Resolution => "resolution",
|
||||
DataType::TransformFunction => "transform-function",
|
||||
DataType::CustomIdent => "custom-ident",
|
||||
DataType::TransformList => "transform-list",
|
||||
DataType::String => "string",
|
||||
})?;
|
||||
dest.write_char('>')
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,11 @@ impl Descriptor {
|
|||
return Err(ParseError::EmptyInput);
|
||||
}
|
||||
|
||||
let specified = if save_specified { Some(Box::from(css)) } else { None };
|
||||
let specified = if save_specified {
|
||||
Some(Box::from(css))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// 3. If string's length is 1, and the only code point in string is U+002A
|
||||
// ASTERISK (*), return the universal syntax descriptor.
|
||||
|
|
@ -113,7 +117,10 @@ impl ToCss for Descriptor {
|
|||
|
||||
impl Parse for Descriptor {
|
||||
/// Parse a syntax descriptor.
|
||||
fn parse<'i>( _: &ParserContext, parser: &mut CSSParser<'i, '_>,) -> Result<Self, StyleParseError<'i>> {
|
||||
fn parse<'i>(
|
||||
_: &ParserContext,
|
||||
parser: &mut CSSParser<'i, '_>,
|
||||
) -> Result<Self, StyleParseError<'i>> {
|
||||
let input = parser.expect_string()?;
|
||||
Descriptor::from_str(input.as_ref(), /* save_specified = */ true)
|
||||
.map_err(|err| parser.new_custom_error(StyleParseErrorKind::PropertySyntaxField(err)))
|
||||
|
|
@ -134,12 +141,10 @@ impl ToCss for Multiplier {
|
|||
where
|
||||
W: Write,
|
||||
{
|
||||
dest.write_char(
|
||||
match *self {
|
||||
Multiplier::Space => '+',
|
||||
Multiplier::Comma => '#',
|
||||
}
|
||||
)
|
||||
dest.write_char(match *self {
|
||||
Multiplier::Space => '+',
|
||||
Multiplier::Comma => '#',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -413,7 +413,9 @@ impl SpecifiedValue {
|
|||
allow_computationally_dependent: AllowComputationallyDependent,
|
||||
) -> Result<Self, StyleParseError<'i>> {
|
||||
if syntax.is_universal() {
|
||||
return Ok(Self::Universal(ComputedPropertyValue::parse(&mut input, url_data)?));
|
||||
return Ok(Self::Universal(ComputedPropertyValue::parse(
|
||||
&mut input, url_data,
|
||||
)?));
|
||||
}
|
||||
|
||||
let mut values = SmallComponentVec::new();
|
||||
|
|
|
|||
|
|
@ -654,10 +654,7 @@ impl QueryFeatureExpression {
|
|||
return evaluator(context, computed);
|
||||
},
|
||||
Evaluator::String(evaluator) => {
|
||||
let string = self
|
||||
.kind
|
||||
.non_ranged_value()
|
||||
.map(|v| expect!(String, v));
|
||||
let string = self.kind.non_ranged_value().map(|v| expect!(String, v));
|
||||
return evaluator(context, string);
|
||||
},
|
||||
Evaluator::BoolInteger(eval) => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::values::serialize_atom_identifier;
|
|||
use crate::Atom;
|
||||
use cssparser::{Parser as CssParser, ParserInput};
|
||||
use dom::ElementState;
|
||||
use selectors::parser::{SelectorList, ParseRelative};
|
||||
use selectors::parser::{ParseRelative, SelectorList};
|
||||
use std::fmt::{self, Debug, Write};
|
||||
use style_traits::{CssWriter, ParseError, ToCss};
|
||||
|
||||
|
|
|
|||
|
|
@ -137,8 +137,7 @@ where
|
|||
|
||||
let for_element = target.revalidation_match_results(stylist, bloom, selector_caches);
|
||||
|
||||
let for_candidate =
|
||||
candidate.revalidation_match_results(stylist, bloom, selector_caches);
|
||||
let for_candidate = candidate.revalidation_match_results(stylist, bloom, selector_caches);
|
||||
|
||||
// This assert "ensures", to some extent, that the two candidates have
|
||||
// matched the same rulehash buckets, and as such, that the bits we're
|
||||
|
|
|
|||
|
|
@ -635,7 +635,8 @@ impl<E: TElement> StyleSharingCache<E> {
|
|||
.style
|
||||
.0
|
||||
.flags
|
||||
.intersects(ComputedValueFlags::ANCHORS_RELATIVE_SELECTOR) {
|
||||
.intersects(ComputedValueFlags::ANCHORS_RELATIVE_SELECTOR)
|
||||
{
|
||||
debug!("Failing to insert to the cache: may anchor relative selector");
|
||||
return;
|
||||
}
|
||||
|
|
@ -898,7 +899,11 @@ impl<E: TElement> StyleSharingCache<E> {
|
|||
// RELEVANT_LINK_VISITED flag, so we can't share by rule node between visited and
|
||||
// unvisited styles. We don't check for visitedness and just refuse to share for links
|
||||
// entirely, so that visitedness doesn't affect timing.
|
||||
debug_assert_eq!(target.is_link(), candidate.element.is_link(), "Linkness mismatch");
|
||||
debug_assert_eq!(
|
||||
target.is_link(),
|
||||
candidate.element.is_link(),
|
||||
"Linkness mismatch"
|
||||
);
|
||||
if target.is_link() {
|
||||
return None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use crate::selector_parser::{PseudoElement, SelectorImpl};
|
|||
use crate::stylist::RuleInclusion;
|
||||
use log::Level::Trace;
|
||||
use selectors::matching::{
|
||||
MatchingForInvalidation, MatchingContext, MatchingMode, NeedsSelectorFlags,
|
||||
MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags,
|
||||
RelativeSelectorMatchingState, VisitedHandlingMode,
|
||||
};
|
||||
use servo_arc::Arc;
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ pub use self::loader::StylesheetLoader;
|
|||
pub use self::media_rule::MediaRule;
|
||||
pub use self::namespace_rule::NamespaceRule;
|
||||
pub use self::origin::{Origin, OriginSet, OriginSetIterator, PerOrigin, PerOriginIter};
|
||||
pub use self::page_rule::{PagePseudoClassFlags, PageRule, PageSelector, PageSelectors};
|
||||
pub use self::property_rule::PropertyRule;
|
||||
pub use self::page_rule::{PageRule, PagePseudoClassFlags, PageSelector, PageSelectors};
|
||||
pub use self::rule_list::{CssRules, CssRulesHelpers};
|
||||
pub use self::rule_parser::{InsertRuleContext, State, TopLevelRuleParser};
|
||||
pub use self::rules_iterator::{AllRules, EffectiveRules};
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ use cssparser::{Parser, SourceLocation, Token};
|
|||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
||||
use servo_arc::Arc;
|
||||
use std::fmt::{self, Write};
|
||||
use smallvec::SmallVec;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError, ToCss};
|
||||
|
||||
macro_rules! page_pseudo_classes {
|
||||
|
|
@ -123,7 +123,7 @@ type PagePseudoClasses = SmallVec<[PagePseudoClass; 4]>;
|
|||
///
|
||||
/// [page-selectors]: https://drafts.csswg.org/css2/page.html#page-selectors
|
||||
#[derive(Clone, Debug, MallocSizeOf, ToShmem)]
|
||||
pub struct PageSelector{
|
||||
pub struct PageSelector {
|
||||
/// Page name
|
||||
///
|
||||
/// https://drafts.csswg.org/css-page-3/#page-type-selector
|
||||
|
|
@ -177,18 +177,20 @@ impl PageSelector {
|
|||
let mut h: usize = 0;
|
||||
for pc in self.pseudos.iter() {
|
||||
if !flags.contains_class(pc) {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
match pc {
|
||||
PagePseudoClass::First |
|
||||
PagePseudoClass::Blank => g += 1,
|
||||
PagePseudoClass::Left |
|
||||
PagePseudoClass::Right => h += 1,
|
||||
PagePseudoClass::First | PagePseudoClass::Blank => g += 1,
|
||||
PagePseudoClass::Left | PagePseudoClass::Right => h += 1,
|
||||
}
|
||||
}
|
||||
let h = h.min(0xFFFF) as u32;
|
||||
let g = (g.min(0x7FFF) as u32) << 16;
|
||||
let f = if self.name.0.is_empty() { 0 } else { 0x80000000 };
|
||||
let f = if self.name.0.is_empty() {
|
||||
0
|
||||
} else {
|
||||
0x80000000
|
||||
};
|
||||
Some(h + g + f)
|
||||
}
|
||||
}
|
||||
|
|
@ -196,7 +198,7 @@ impl PageSelector {
|
|||
impl ToCss for PageSelector {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write
|
||||
W: Write,
|
||||
{
|
||||
self.name.to_css(dest)?;
|
||||
for pc in self.pseudos.iter() {
|
||||
|
|
@ -206,9 +208,7 @@ impl ToCss for PageSelector {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_page_name<'i, 't>(
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<AtomIdent, ParseError<'i>> {
|
||||
fn parse_page_name<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AtomIdent, ParseError<'i>> {
|
||||
let s = input.expect_ident()?;
|
||||
Ok(AtomIdent::from(&**s))
|
||||
}
|
||||
|
|
@ -218,12 +218,14 @@ impl Parse for PageSelector {
|
|||
_context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let name = input.try_parse(parse_page_name).unwrap_or(AtomIdent(atom!("")));
|
||||
let name = input
|
||||
.try_parse(parse_page_name)
|
||||
.unwrap_or(AtomIdent(atom!("")));
|
||||
let mut pseudos = PagePseudoClasses::default();
|
||||
while let Ok(pc) = input.try_parse(PagePseudoClass::parse) {
|
||||
pseudos.push(pc);
|
||||
}
|
||||
Ok(PageSelector{name, pseudos})
|
||||
Ok(PageSelector { name, pseudos })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -542,7 +542,8 @@ impl<'a, 'i> NestedRuleParser<'a, 'i> {
|
|||
}
|
||||
let declarations = if parse_declarations {
|
||||
let top = &mut **parser;
|
||||
top.declaration_parser_state.report_errors_if_needed(&top.context, &top.error_reporting_state);
|
||||
top.declaration_parser_state
|
||||
.report_errors_if_needed(&top.context, &top.error_reporting_state);
|
||||
parser.declaration_parser_state.take_declarations()
|
||||
} else {
|
||||
PropertyDeclarationBlock::default()
|
||||
|
|
@ -586,7 +587,9 @@ impl<'a, 'i> NestedRuleParser<'a, 'i> {
|
|||
if found_host && found_non_host {
|
||||
self.context.log_css_error(
|
||||
start.source_location(),
|
||||
ContextualParseError::NeverMatchingHostSelector(selector.to_css_string()),
|
||||
ContextualParseError::NeverMatchingHostSelector(
|
||||
selector.to_css_string(),
|
||||
),
|
||||
);
|
||||
continue 'selector_loop;
|
||||
}
|
||||
|
|
@ -774,11 +777,8 @@ impl<'a, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'i> {
|
|||
})))
|
||||
},
|
||||
AtRulePrelude::Property(name) => self.nest_for_rule(CssRuleType::Property, |p| {
|
||||
let rule_data = parse_property_block(
|
||||
&p.context,
|
||||
input,
|
||||
name,
|
||||
start.source_location())?;
|
||||
let rule_data =
|
||||
parse_property_block(&p.context, input, name, start.source_location())?;
|
||||
Ok::<CssRule, ParseError<'i>>(CssRule::Property(Arc::new(rule_data)))
|
||||
})?,
|
||||
AtRulePrelude::Document(condition) => {
|
||||
|
|
@ -922,7 +922,9 @@ impl<'a, 'i> DeclarationParser<'i> for NestedRuleParser<'a, 'i> {
|
|||
}
|
||||
|
||||
impl<'a, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for NestedRuleParser<'a, 'i> {
|
||||
fn parse_qualified(&self) -> bool { true }
|
||||
fn parse_qualified(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// If nesting is disabled, we can't get there for a non-style-rule. If it's enabled, we parse
|
||||
/// raw declarations there.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ use crate::str::CssStringWriter;
|
|||
use crate::stylesheets::CssRules;
|
||||
use cssparser::SourceLocation;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocUnconditionalShallowSizeOf, MallocUnconditionalSizeOf, MallocSizeOf, MallocSizeOfOps};
|
||||
use malloc_size_of::{
|
||||
MallocSizeOf, MallocSizeOfOps, MallocUnconditionalShallowSizeOf, MallocUnconditionalSizeOf,
|
||||
};
|
||||
use selectors::SelectorList;
|
||||
use servo_arc::Arc;
|
||||
use std::fmt::{self, Write};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use crate::applicable_declarations::{
|
|||
ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority,
|
||||
};
|
||||
use crate::context::{CascadeInputs, QuirksMode};
|
||||
use crate::custom_properties::{CustomPropertiesMap, ComputedCustomProperties};
|
||||
use crate::custom_properties::{ComputedCustomProperties, CustomPropertiesMap};
|
||||
use crate::dom::TElement;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
|
||||
|
|
@ -22,7 +22,9 @@ use crate::invalidation::stylesheets::RuleChangeKind;
|
|||
use crate::media_queries::Device;
|
||||
use crate::properties::{self, CascadeMode, ComputedValues, FirstLineReparenting};
|
||||
use crate::properties::{AnimationDeclarations, PropertyDeclarationBlock};
|
||||
use crate::properties_and_values::registry::{ScriptRegistry as CustomPropertyScriptRegistry, PropertyRegistration};
|
||||
use crate::properties_and_values::registry::{
|
||||
PropertyRegistration, ScriptRegistry as CustomPropertyScriptRegistry,
|
||||
};
|
||||
use crate::rule_cache::{RuleCache, RuleCacheConditions};
|
||||
use crate::rule_collector::RuleCollector;
|
||||
use crate::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
|
||||
|
|
@ -40,8 +42,8 @@ use crate::stylesheets::{
|
|||
CounterStyleRule, FontFaceRule, FontFeatureValuesRule, FontPaletteValuesRule,
|
||||
};
|
||||
use crate::stylesheets::{
|
||||
CssRule, EffectiveRulesIterator, Origin, OriginSet, PerOrigin, PerOriginIter,
|
||||
PagePseudoClassFlags, PageRule,
|
||||
CssRule, EffectiveRulesIterator, Origin, OriginSet, PagePseudoClassFlags, PageRule, PerOrigin,
|
||||
PerOriginIter,
|
||||
};
|
||||
use crate::stylesheets::{StyleRule, StylesheetContents, StylesheetInDocument};
|
||||
use crate::values::computed;
|
||||
|
|
@ -1428,11 +1430,12 @@ impl Stylist {
|
|||
// [1]: https://github.com/w3c/csswg-drafts/issues/1995
|
||||
// [2]: https://bugzil.la/1458189
|
||||
let mut animation = None;
|
||||
let doc_rules_apply = element.each_applicable_non_document_style_rule_data(|data, _host| {
|
||||
if animation.is_none() {
|
||||
animation = data.animations.get(name);
|
||||
}
|
||||
});
|
||||
let doc_rules_apply =
|
||||
element.each_applicable_non_document_style_rule_data(|data, _host| {
|
||||
if animation.is_none() {
|
||||
animation = data.animations.get(name);
|
||||
}
|
||||
});
|
||||
|
||||
if animation.is_some() {
|
||||
return animation;
|
||||
|
|
@ -1743,16 +1746,22 @@ impl PageRuleMap {
|
|||
let cascade_data = cascade_data.borrow_for_origin(origin);
|
||||
let start = matched_rules.len();
|
||||
|
||||
self.match_and_add_rules(matched_rules, level, guards, cascade_data, &atom!(""), pseudos);
|
||||
self.match_and_add_rules(
|
||||
matched_rules,
|
||||
level,
|
||||
guards,
|
||||
cascade_data,
|
||||
&atom!(""),
|
||||
pseudos,
|
||||
);
|
||||
if let Some(name) = name {
|
||||
self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
|
||||
}
|
||||
|
||||
// Because page-rules do not have source location information stored,
|
||||
// use stable sort to ensure source locations are preserved.
|
||||
matched_rules[start..].sort_by_key(|block| {
|
||||
(block.layer_order(), block.specificity, block.source_order())
|
||||
});
|
||||
matched_rules[start..]
|
||||
.sort_by_key(|block| (block.layer_order(), block.specificity, block.source_order()));
|
||||
}
|
||||
|
||||
fn match_and_add_rules(
|
||||
|
|
@ -1856,7 +1865,10 @@ impl ExtraStyleData {
|
|||
let page_rule = rule.read_with(guard);
|
||||
let mut add_rule = |name| {
|
||||
let vec = self.pages.rules.entry(name).or_default();
|
||||
vec.push(PageRuleData{layer, rule: rule.clone()});
|
||||
vec.push(PageRuleData {
|
||||
layer,
|
||||
rule: rule.clone(),
|
||||
});
|
||||
};
|
||||
if page_rule.selectors.0.is_empty() {
|
||||
add_rule(atom!(""));
|
||||
|
|
@ -2047,7 +2059,7 @@ impl<'a> StylistSelectorVisitor<'a> {
|
|||
fn visit_nested_selector(
|
||||
&mut self,
|
||||
in_selector_list_of: SelectorListKind,
|
||||
selector: &Selector<SelectorImpl>
|
||||
selector: &Selector<SelectorImpl>,
|
||||
) {
|
||||
let old_passed_rightmost_selector = self.passed_rightmost_selector;
|
||||
let old_in_selector_list_of = self.in_selector_list_of;
|
||||
|
|
@ -2777,9 +2789,11 @@ impl CascadeData {
|
|||
self.num_declarations += style_rule.block.read_with(&guard).len();
|
||||
|
||||
let has_nested_rules = style_rule.rules.is_some();
|
||||
let mut ancestor_selectors = containing_rule_state.ancestor_selector_lists.last_mut();
|
||||
let mut ancestor_selectors =
|
||||
containing_rule_state.ancestor_selector_lists.last_mut();
|
||||
let mut replaced_selectors = SmallVec::<[Selector<SelectorImpl>; 4]>::new();
|
||||
let collect_replaced_selectors = has_nested_rules && ancestor_selectors.is_some();
|
||||
let collect_replaced_selectors =
|
||||
has_nested_rules && ancestor_selectors.is_some();
|
||||
|
||||
for selector in style_rule.selectors.slice() {
|
||||
self.num_selectors += 1;
|
||||
|
|
|
|||
|
|
@ -352,7 +352,11 @@ impl Quaternion {
|
|||
// direction: [-360, 0]. And quaternions between the range [720*k, 720*(k+1)] will be
|
||||
// treated as rotations [0, 720]. So it does not make sense to use quaternions to rotate
|
||||
// the element more than ±360deg. Therefore, we have to make sure its range is (-360, 360).
|
||||
let half_angle = angle.abs().rem_euclid(std::f64::consts::TAU).copysign(angle) / 2.;
|
||||
let half_angle = angle
|
||||
.abs()
|
||||
.rem_euclid(std::f64::consts::TAU)
|
||||
.copysign(angle) /
|
||||
2.;
|
||||
|
||||
// Reference:
|
||||
// https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
|
||||
|
|
@ -393,7 +397,12 @@ impl Add for Quaternion {
|
|||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self(self.0 + other.0, self.1 + other.1, self.2 + other.2, self.3 + other.3)
|
||||
Self(
|
||||
self.0 + other.0,
|
||||
self.1 + other.1,
|
||||
self.2 + other.2,
|
||||
self.3 + other.3,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
//! Computed color values.
|
||||
|
||||
use crate::color::parsing::Color as CSSParserColor;
|
||||
use crate::color::AbsoluteColor;
|
||||
use crate::values::animated::ToAnimatedZero;
|
||||
use crate::values::computed::percentage::Percentage;
|
||||
use crate::values::generics::color::{
|
||||
GenericCaretColor, GenericColor, GenericColorMix, GenericColorOrAuto,
|
||||
};
|
||||
use crate::color::parsing::Color as CSSParserColor;
|
||||
use std::fmt;
|
||||
use style_traits::{CssWriter, ToCss};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@ pub use specified::ImageRendering;
|
|||
|
||||
/// Computed values for an image according to CSS-IMAGES.
|
||||
/// <https://drafts.csswg.org/css-images/#image-values>
|
||||
pub type Image =
|
||||
generic::GenericImage<Gradient, ComputedImageUrl, Color, Percentage, Resolution>;
|
||||
pub type Image = generic::GenericImage<Gradient, ComputedImageUrl, Color, Percentage, Resolution>;
|
||||
|
||||
// Images should remain small, see https://github.com/servo/servo/pull/18430
|
||||
size_of_test!(Image, 16);
|
||||
|
|
@ -87,7 +86,10 @@ impl ToComputedValue for specified::ImageSet {
|
|||
}
|
||||
|
||||
let candidate_resolution = item.resolution.dppx();
|
||||
debug_assert!(candidate_resolution >= 0.0, "Resolutions should be non-negative");
|
||||
debug_assert!(
|
||||
candidate_resolution >= 0.0,
|
||||
"Resolutions should be non-negative"
|
||||
);
|
||||
if candidate_resolution == 0.0 {
|
||||
// If the resolution is 0, we also treat it as an invalid image.
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ use crate::media_queries::Device;
|
|||
use crate::properties;
|
||||
use crate::properties::{ComputedValues, StyleBuilder};
|
||||
use crate::rule_cache::RuleCacheConditions;
|
||||
use crate::stylist::Stylist;
|
||||
use crate::stylesheets::container_rule::{
|
||||
ContainerInfo, ContainerSizeQuery, ContainerSizeQueryResult,
|
||||
};
|
||||
use crate::stylist::Stylist;
|
||||
use crate::values::specified::length::FontBaseSize;
|
||||
use crate::{ArcSlice, Atom, One};
|
||||
use euclid::{default, Point2D, Rect, Size2D};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::values::computed::image::Image;
|
|||
use crate::values::computed::Number;
|
||||
use crate::values::generics::ui as generics;
|
||||
|
||||
pub use crate::values::specified::ui::{CursorKind, BoolInteger, UserSelect, MozTheme};
|
||||
pub use crate::values::specified::ui::{BoolInteger, CursorKind, MozTheme, UserSelect};
|
||||
|
||||
/// A computed value for the `cursor` property.
|
||||
pub type Cursor = generics::GenericCursor<CursorImage>;
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ impl Default for ShapeGeometryBox {
|
|||
fn is_default_box_for_clip_path(b: &ShapeGeometryBox) -> bool {
|
||||
// Note: for clip-path, ElementDependent is always border-box, so we have to check both of them
|
||||
// for serialization.
|
||||
matches!(b, ShapeGeometryBox::ElementDependent)
|
||||
|| matches!(b, ShapeGeometryBox::ShapeBox(ShapeBox::BorderBox))
|
||||
matches!(b, ShapeGeometryBox::ElementDependent) ||
|
||||
matches!(b, ShapeGeometryBox::ShapeBox(ShapeBox::BorderBox))
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
//! Generic types for font stuff.
|
||||
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::One;
|
||||
use crate::values::animated::ToAnimatedZero;
|
||||
use crate::One;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use cssparser::Parser;
|
||||
use std::fmt::{self, Write};
|
||||
|
|
|
|||
|
|
@ -777,7 +777,7 @@ impl<I: ToCss> ToCss for LineNameListValue<I> {
|
|||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct GenericLineNameList<I>{
|
||||
pub struct GenericLineNameList<I> {
|
||||
/// The pre-computed length of line_names, without the length of repeat(auto-fill, ...).
|
||||
// We precomputed this at parsing time, so we can avoid an extra loop when expanding
|
||||
// repeat(auto-fill).
|
||||
|
|
|
|||
|
|
@ -156,7 +156,9 @@ pub use self::GenericImageSet as ImageSet;
|
|||
pub use self::GenericImageSetItem as ImageSetItem;
|
||||
|
||||
/// State flags stored on each variant of a Gradient.
|
||||
#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Default, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct GradientFlags(u8);
|
||||
bitflags! {
|
||||
|
|
|
|||
|
|
@ -120,7 +120,9 @@ where
|
|||
{
|
||||
use crate::serde::de::Error;
|
||||
// Return Err() so the IPC will catch it and assert this as a fetal error.
|
||||
Err(<D as Deserializer>::Error::custom("we don't support the deserializing for url"))
|
||||
Err(<D as Deserializer>::Error::custom(
|
||||
"we don't support the deserializing for url",
|
||||
))
|
||||
}
|
||||
|
||||
/// The <offset-path> value.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ use std::fmt::{self, Write};
|
|||
use style_traits::{CssWriter, KeywordsCollectFn, ParseError, SpecifiedValueInfo, ToCss};
|
||||
|
||||
/// Constants shared by multiple CSS Box Alignment properties
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct AlignFlags(u8);
|
||||
bitflags! {
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
|
|||
use crate::values::generics::rect::Rect;
|
||||
use crate::values::generics::size::Size2D;
|
||||
use crate::values::specified::length::{Length, NonNegativeLength, NonNegativeLengthPercentage};
|
||||
use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
|
||||
use crate::values::specified::Color;
|
||||
use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
|
||||
use crate::Zero;
|
||||
use app_units::Au;
|
||||
use cssparser::Parser;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError, ToCss, values::SequenceWriter};
|
||||
use style_traits::{values::SequenceWriter, CssWriter, ParseError, ToCss};
|
||||
|
||||
/// A specified value for a single side of a `border-style` property.
|
||||
///
|
||||
|
|
@ -382,7 +382,7 @@ where
|
|||
let has_color = *color != Color::CurrentColor;
|
||||
let has_width = *width != BorderSideWidth::medium();
|
||||
if !has_style && !has_color && !has_width {
|
||||
return width.to_css(dest)
|
||||
return width.to_css(dest);
|
||||
}
|
||||
let mut writer = SequenceWriter::new(dest, " ");
|
||||
if has_width {
|
||||
|
|
|
|||
|
|
@ -1022,7 +1022,19 @@ impl WillChange {
|
|||
}
|
||||
|
||||
/// The change bits that we care about.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Default,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct WillChangeBits(u16);
|
||||
bitflags! {
|
||||
|
|
@ -1134,7 +1146,20 @@ impl Parse for WillChange {
|
|||
}
|
||||
|
||||
/// Values for the `touch-action` property.
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[css(bitflags(single = "none,auto,manipulation", mixed = "pan-x,pan-y,pinch-zoom"))]
|
||||
#[repr(C)]
|
||||
pub struct TouchAction(u8);
|
||||
|
|
@ -1163,8 +1188,25 @@ impl TouchAction {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
|
||||
#[css(bitflags(single = "none,strict,content", mixed="size,layout,style,paint,inline-size", overlapping_bits))]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[css(bitflags(
|
||||
single = "none,strict,content",
|
||||
mixed = "size,layout,style,paint,inline-size",
|
||||
overlapping_bits
|
||||
))]
|
||||
#[repr(C)]
|
||||
/// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
|
||||
pub struct Contain(u8);
|
||||
|
|
@ -1844,9 +1886,26 @@ impl Overflow {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
#[css(bitflags(single = "auto", mixed = "stable,both-edges", validate_mixed="Self::has_stable"))]
|
||||
#[css(bitflags(
|
||||
single = "auto",
|
||||
mixed = "stable,both-edges",
|
||||
validate_mixed = "Self::has_stable"
|
||||
))]
|
||||
/// Values for scrollbar-gutter:
|
||||
/// <https://drafts.csswg.org/css-overflow-3/#scrollbar-gutter-property>
|
||||
pub struct ScrollbarGutter(u8);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//!
|
||||
//! [calc]: https://drafts.csswg.org/css-values/#calc-notation
|
||||
|
||||
use crate::color::parsing::{AngleOrNumber, NumberOrPercentage};
|
||||
use crate::parser::ParserContext;
|
||||
use crate::values::generics::calc::{
|
||||
self as generic, CalcNodeLeaf, CalcUnits, MinMaxOp, ModRemOp, PositivePercentageBasis,
|
||||
|
|
@ -16,7 +17,6 @@ use crate::values::specified::length::{ContainerRelativeLength, ViewportPercenta
|
|||
use crate::values::specified::{self, Angle, Resolution, Time};
|
||||
use crate::values::{serialize_number, serialize_percentage, CSSFloat, CSSInteger};
|
||||
use cssparser::{CowRcStr, Parser, Token};
|
||||
use crate::color::parsing::{AngleOrNumber, NumberOrPercentage};
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp;
|
||||
use std::fmt::{self, Write};
|
||||
|
|
@ -188,11 +188,9 @@ impl generic::CalcNodeLeaf for Leaf {
|
|||
}
|
||||
|
||||
match (self, other) {
|
||||
(&Percentage(ref one), &Percentage(ref other)) => {
|
||||
match basis {
|
||||
PositivePercentageBasis::Yes => one.partial_cmp(other),
|
||||
PositivePercentageBasis::Unknown => None,
|
||||
}
|
||||
(&Percentage(ref one), &Percentage(ref other)) => match basis {
|
||||
PositivePercentageBasis::Yes => one.partial_cmp(other),
|
||||
PositivePercentageBasis::Unknown => None,
|
||||
},
|
||||
(&Length(ref one), &Length(ref other)) => one.partial_cmp(other),
|
||||
(&Angle(ref one), &Angle(ref other)) => one.degrees().partial_cmp(&other.degrees()),
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ use crate::values::generics::font::{
|
|||
use crate::values::generics::NonNegative;
|
||||
use crate::values::specified::length::{FontBaseSize, LineHeightBase, PX_PER_PT};
|
||||
use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage};
|
||||
use crate::values::specified::{FontRelativeLength, NoCalcLength, NonNegativeNumber, NonNegativePercentage, NonNegativeLengthPercentage, Number};
|
||||
use crate::values::specified::{
|
||||
FontRelativeLength, NoCalcLength, NonNegativeLengthPercentage, NonNegativeNumber,
|
||||
NonNegativePercentage, Number,
|
||||
};
|
||||
use crate::values::{serialize_atom_identifier, CustomIdent, SelectorParseErrorKind};
|
||||
use crate::Atom;
|
||||
use cssparser::{Parser, Token};
|
||||
|
|
|
|||
|
|
@ -433,9 +433,9 @@ impl Parse for LineNameList<Integer> {
|
|||
line_names.push(value);
|
||||
}
|
||||
|
||||
Ok(LineNameList{
|
||||
expanded_line_names_length,
|
||||
line_names : line_names.into(),
|
||||
Ok(LineNameList {
|
||||
expanded_line_names_length,
|
||||
line_names: line_names.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ fn gradient_color_interpolation_method_enabled() -> bool {
|
|||
|
||||
/// Specified values for an image according to CSS-IMAGES.
|
||||
/// <https://drafts.csswg.org/css-images/#image-values>
|
||||
pub type Image =
|
||||
generic::Image<Gradient, SpecifiedImageUrl, Color, Percentage, Resolution>;
|
||||
pub type Image = generic::Image<Gradient, SpecifiedImageUrl, Color, Percentage, Resolution>;
|
||||
|
||||
// Images should remain small, see https://github.com/servo/servo/pull/18430
|
||||
size_of_test!(Image, 16);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use super::{CSSFloat, CSSInteger};
|
|||
use crate::context::QuirksMode;
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::values::specified::calc::CalcNode;
|
||||
use crate::values::{AtomString, serialize_atom_identifier, serialize_number};
|
||||
use crate::values::{serialize_atom_identifier, serialize_number, AtomString};
|
||||
use crate::{Atom, Namespace, One, Prefix, Zero};
|
||||
use cssparser::{Parser, Token};
|
||||
use std::fmt::{self, Write};
|
||||
|
|
@ -39,11 +39,11 @@ pub use self::border::{
|
|||
BorderImageWidth, BorderRadius, BorderSideWidth, BorderSpacing, BorderStyle, LineWidth,
|
||||
};
|
||||
pub use self::box_::{
|
||||
Appearance, BreakBetween, BaselineSource, BreakWithin, Contain, ContainerName, ContainerType,
|
||||
Clear, ContainIntrinsicSize, ContentVisibility, Display, Float, LineClamp, Overflow,
|
||||
OverflowAnchor, OverflowClipBox, OverscrollBehavior, Perspective, Resize, ScrollbarGutter,
|
||||
ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop, ScrollSnapStrictness, ScrollSnapType,
|
||||
TouchAction, VerticalAlign, WillChange, Zoom
|
||||
Appearance, BaselineSource, BreakBetween, BreakWithin, Clear, Contain, ContainIntrinsicSize,
|
||||
ContainerName, ContainerType, ContentVisibility, Display, Float, LineClamp, Overflow,
|
||||
OverflowAnchor, OverflowClipBox, OverscrollBehavior, Perspective, Resize, ScrollSnapAlign,
|
||||
ScrollSnapAxis, ScrollSnapStop, ScrollSnapStrictness, ScrollSnapType, ScrollbarGutter,
|
||||
TouchAction, VerticalAlign, WillChange, Zoom,
|
||||
};
|
||||
pub use self::color::{
|
||||
Color, ColorOrAuto, ColorPropertyValue, ColorScheme, ForcedColorAdjust, PrintColorAdjust,
|
||||
|
|
@ -55,7 +55,9 @@ pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
|||
pub use self::flex::FlexBasis;
|
||||
pub use self::font::{FontFamily, FontLanguageOverride, FontPalette, FontStyle};
|
||||
pub use self::font::{FontFeatureSettings, FontVariantLigatures, FontVariantNumeric};
|
||||
pub use self::font::{FontSize, FontSizeAdjust, FontSizeAdjustFactor, FontSizeKeyword, FontStretch, FontSynthesis};
|
||||
pub use self::font::{
|
||||
FontSize, FontSizeAdjust, FontSizeAdjustFactor, FontSizeKeyword, FontStretch, FontSynthesis,
|
||||
};
|
||||
pub use self::font::{FontVariantAlternates, FontWeight};
|
||||
pub use self::font::{FontVariantEastAsian, FontVariationSettings, LineHeight};
|
||||
pub use self::font::{MathDepth, MozScriptMinSize, MozScriptSizeMultiplier, XLang, XTextScale};
|
||||
|
|
@ -878,7 +880,7 @@ pub struct Attr {
|
|||
/// Attribute name
|
||||
pub attribute: Atom,
|
||||
/// Fallback value
|
||||
pub fallback: AtomString
|
||||
pub fallback: AtomString,
|
||||
}
|
||||
|
||||
impl Parse for Attr {
|
||||
|
|
@ -897,7 +899,10 @@ fn get_namespace_for_prefix(prefix: &Prefix, context: &ParserContext) -> Option<
|
|||
}
|
||||
|
||||
/// Try to parse a namespace and return it if parsed, or none if there was not one present
|
||||
fn parse_namespace<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<(Prefix, Namespace), ParseError<'i>> {
|
||||
fn parse_namespace<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<(Prefix, Namespace), ParseError<'i>> {
|
||||
let ns_prefix = match input.next()? {
|
||||
Token::Ident(ref prefix) => Some(Prefix::from(prefix.as_ref())),
|
||||
Token::Delim('|') => None,
|
||||
|
|
@ -927,7 +932,9 @@ impl Attr {
|
|||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Attr, ParseError<'i>> {
|
||||
// Syntax is `[namespace? '|']? ident [',' fallback]?`
|
||||
let namespace = input.try_parse(|input| parse_namespace(context, input)).ok();
|
||||
let namespace = input
|
||||
.try_parse(|input| parse_namespace(context, input))
|
||||
.ok();
|
||||
let namespace_is_some = namespace.is_some();
|
||||
let (namespace_prefix, namespace_url) = namespace.unwrap_or_default();
|
||||
|
||||
|
|
@ -944,10 +951,12 @@ impl Attr {
|
|||
|
||||
// Fallback will always be a string value for now as we do not support
|
||||
// attr() types yet.
|
||||
let fallback = input.try_parse(|input| -> Result<AtomString, ParseError<'i>> {
|
||||
input.expect_comma()?;
|
||||
Ok(input.expect_string()?.as_ref().into())
|
||||
}).unwrap_or_default();
|
||||
let fallback = input
|
||||
.try_parse(|input| -> Result<AtomString, ParseError<'i>> {
|
||||
input.expect_comma()?;
|
||||
Ok(input.expect_string()?.as_ref().into())
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(Attr {
|
||||
namespace_prefix,
|
||||
|
|
|
|||
|
|
@ -197,8 +197,8 @@ impl Parse for OffsetPath {
|
|||
.ok();
|
||||
}
|
||||
|
||||
if static_prefs::pref!("layout.css.motion-path-coord-box.enabled")
|
||||
&& coord_box.is_none()
|
||||
if static_prefs::pref!("layout.css.motion-path-coord-box.enabled") &&
|
||||
coord_box.is_none()
|
||||
{
|
||||
coord_box = input.try_parse(CoordBox::parse).ok();
|
||||
if coord_box.is_some() {
|
||||
|
|
|
|||
|
|
@ -372,7 +372,18 @@ impl Side for VerticalPositionKeyword {
|
|||
|
||||
/// Controls how the auto-placement algorithm works specifying exactly how auto-placed items
|
||||
/// get flowed into the grid.
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[value_info(other_values = "row,column,dense")]
|
||||
#[repr(C)]
|
||||
pub struct GridAutoFlow(u8);
|
||||
|
|
@ -632,7 +643,10 @@ pub struct TemplateAreasParser {
|
|||
|
||||
impl TemplateAreasParser {
|
||||
/// Parse a single string.
|
||||
pub fn try_parse_string<'i>(&mut self, input: &mut Parser<'i, '_>) -> Result<(), ParseError<'i>> {
|
||||
pub fn try_parse_string<'i>(
|
||||
&mut self,
|
||||
input: &mut Parser<'i, '_>,
|
||||
) -> Result<(), ParseError<'i>> {
|
||||
input.try_parse(|input| {
|
||||
self.parse_string(input.expect_string()?)
|
||||
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
|
|
@ -676,12 +690,14 @@ impl TemplateAreasParser {
|
|||
match self.area_indices.entry(name) {
|
||||
Entry::Occupied(ref e) => {
|
||||
let index = *e.get();
|
||||
if self.areas[index].columns.start != column || self.areas[index].rows.end != self.row {
|
||||
if self.areas[index].columns.start != column ||
|
||||
self.areas[index].rows.end != self.row
|
||||
{
|
||||
return Err(());
|
||||
}
|
||||
self.areas[index].rows.end += 1;
|
||||
current_area_index = Some(index);
|
||||
}
|
||||
},
|
||||
Entry::Vacant(v) => {
|
||||
let index = self.areas.len();
|
||||
let name = v.key().clone();
|
||||
|
|
@ -698,7 +714,7 @@ impl TemplateAreasParser {
|
|||
},
|
||||
});
|
||||
current_area_index = Some(index);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
if column == 0 {
|
||||
|
|
@ -725,7 +741,7 @@ impl TemplateAreasParser {
|
|||
/// Return the parsed template areas.
|
||||
pub fn finish(self) -> Result<TemplateAreas, ()> {
|
||||
if self.strings.is_empty() {
|
||||
return Err(())
|
||||
return Err(());
|
||||
}
|
||||
Ok(TemplateAreas {
|
||||
areas: self.areas.into(),
|
||||
|
|
@ -744,7 +760,10 @@ impl TemplateAreas {
|
|||
}
|
||||
|
||||
impl Parse for TemplateAreas {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>,) -> Result<Self, ParseError<'i>> {
|
||||
fn parse<'i, 't>(
|
||||
_: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(input)
|
||||
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,7 +248,19 @@ impl ToCss for SVGPaintOrder {
|
|||
}
|
||||
|
||||
/// The context properties we understand.
|
||||
#[derive(Clone, Copy, Eq, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Eq,
|
||||
Debug,
|
||||
Default,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct ContextPropertyBits(u8);
|
||||
bitflags! {
|
||||
|
|
|
|||
|
|
@ -119,7 +119,9 @@ impl<T> ArcSlice<T> {
|
|||
#[allow(unsafe_code)]
|
||||
pub fn forget(self) -> ForgottenArcSlicePtr<T> {
|
||||
let ret = unsafe {
|
||||
ForgottenArcSlicePtr(NonNull::new_unchecked(self.0.raw_ptr() as *const _ as *mut _))
|
||||
ForgottenArcSlicePtr(NonNull::new_unchecked(
|
||||
self.0.raw_ptr() as *const _ as *mut _
|
||||
))
|
||||
};
|
||||
mem::forget(self);
|
||||
ret
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ extern crate smallvec;
|
|||
extern crate string_cache;
|
||||
extern crate thin_vec;
|
||||
|
||||
use servo_arc::{Arc, ArcUnion, HeaderSlice, ArcUnionBorrow};
|
||||
use servo_arc::{Arc, ArcUnion, ArcUnionBorrow, HeaderSlice};
|
||||
use smallbitvec::{InternalStorage, SmallBitVec};
|
||||
use smallvec::{Array, SmallVec};
|
||||
use std::alloc::Layout;
|
||||
|
|
@ -438,12 +438,12 @@ where
|
|||
{
|
||||
fn to_shmem(&self, builder: &mut SharedMemoryBuilder) -> Result<Self> {
|
||||
Ok(ManuallyDrop::new(match self.borrow() {
|
||||
ArcUnionBorrow::First(first) => Self::from_first(ManuallyDrop::into_inner(first.with_arc(|a| {
|
||||
a.to_shmem(builder)
|
||||
})?)),
|
||||
ArcUnionBorrow::Second(second) => Self::from_second(ManuallyDrop::into_inner(second.with_arc(|a| {
|
||||
a.to_shmem(builder)
|
||||
})?)),
|
||||
ArcUnionBorrow::First(first) => Self::from_first(ManuallyDrop::into_inner(
|
||||
first.with_arc(|a| a.to_shmem(builder))?,
|
||||
)),
|
||||
ArcUnionBorrow::Second(second) => Self::from_second(ManuallyDrop::into_inner(
|
||||
second.with_arc(|a| a.to_shmem(builder))?,
|
||||
)),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -466,8 +466,9 @@ impl ErrorReporter {
|
|||
Some(desugared.to_css_string())
|
||||
},
|
||||
};
|
||||
let selector_list_ptr =
|
||||
desugared_selector_list.as_ref().map_or(ptr::null(), |s| s.as_ptr()) as *const _;
|
||||
let selector_list_ptr = desugared_selector_list
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |s| s.as_ptr()) as *const _;
|
||||
let params = error.error_params();
|
||||
let param = params.main_param;
|
||||
let pre_param = params.prefix_param;
|
||||
|
|
@ -491,7 +492,9 @@ impl ErrorReporter {
|
|||
source.as_ptr() as *const _,
|
||||
source.len() as u32,
|
||||
selector_list_ptr,
|
||||
desugared_selector_list.as_ref().map_or(0, |string| string.len()) as u32,
|
||||
desugared_selector_list
|
||||
.as_ref()
|
||||
.map_or(0, |string| string.len()) as u32,
|
||||
location.line,
|
||||
location.column,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ use selectors::matching::{ElementSelectorFlags, MatchingForInvalidation, Selecto
|
|||
use selectors::{Element, OpaqueElement};
|
||||
use servo_arc::{Arc, ArcBorrow};
|
||||
use smallvec::SmallVec;
|
||||
use style::invalidation::element::element_wrapper::{ElementWrapper, ElementSnapshot};
|
||||
use style::values::generics::color::ColorMixFlags;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt::Write;
|
||||
use std::iter;
|
||||
|
|
@ -45,7 +43,9 @@ use style::gecko::selector_parser::{NonTSPseudoClass, PseudoElement};
|
|||
use style::gecko::snapshot_helpers::classes_changed;
|
||||
use style::gecko::traversal::RecalcStyleOnly;
|
||||
use style::gecko::url;
|
||||
use style::gecko::wrapper::{GeckoElement, GeckoNode, slow_selector_flags_from_node_selector_flags};
|
||||
use style::gecko::wrapper::{
|
||||
slow_selector_flags_from_node_selector_flags, GeckoElement, GeckoNode,
|
||||
};
|
||||
use style::gecko_bindings::bindings;
|
||||
use style::gecko_bindings::bindings::nsACString;
|
||||
use style::gecko_bindings::bindings::nsAString;
|
||||
|
|
@ -58,7 +58,6 @@ use style::gecko_bindings::bindings::Gecko_GetOrCreateInitialKeyframe;
|
|||
use style::gecko_bindings::bindings::Gecko_GetOrCreateKeyframeAtStart;
|
||||
use style::gecko_bindings::bindings::Gecko_HaveSeenPtr;
|
||||
use style::gecko_bindings::structs;
|
||||
use style::gecko_bindings::structs::GeckoFontMetrics;
|
||||
use style::gecko_bindings::structs::gfx::FontPaletteValueSet;
|
||||
use style::gecko_bindings::structs::gfxFontFeatureValueSet;
|
||||
use style::gecko_bindings::structs::ipc::ByteBuf;
|
||||
|
|
@ -74,6 +73,7 @@ use style::gecko_bindings::structs::nsresult;
|
|||
use style::gecko_bindings::structs::CallerType;
|
||||
use style::gecko_bindings::structs::CompositeOperation;
|
||||
use style::gecko_bindings::structs::DeclarationBlockMutationClosure;
|
||||
use style::gecko_bindings::structs::GeckoFontMetrics;
|
||||
use style::gecko_bindings::structs::IterationCompositeOperation;
|
||||
use style::gecko_bindings::structs::Loader;
|
||||
use style::gecko_bindings::structs::LoaderReusableStyleSheets;
|
||||
|
|
@ -97,7 +97,10 @@ use style::gecko_bindings::sugar::refptr::RefPtr;
|
|||
use style::global_style_data::{
|
||||
GlobalStyleData, PlatformThreadHandle, StyleThreadPool, GLOBAL_STYLE_DATA, STYLE_THREAD_POOL,
|
||||
};
|
||||
use style::invalidation::element::invalidation_map::{RelativeSelectorInvalidationMap, TSStateForInvalidation};
|
||||
use style::invalidation::element::element_wrapper::{ElementSnapshot, ElementWrapper};
|
||||
use style::invalidation::element::invalidation_map::{
|
||||
RelativeSelectorInvalidationMap, TSStateForInvalidation,
|
||||
};
|
||||
use style::invalidation::element::invalidator::{InvalidationResult, SiblingTraversalMap};
|
||||
use style::invalidation::element::relative_selector::{
|
||||
DomMutationOperation, RelativeSelectorDependencyCollector, RelativeSelectorInvalidator,
|
||||
|
|
@ -131,8 +134,8 @@ use style::stylesheets::{
|
|||
CssRules, CssRulesHelpers, DocumentRule, FontFaceRule, FontFeatureValuesRule,
|
||||
FontPaletteValuesRule, ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule,
|
||||
MediaRule, NamespaceRule, Origin, OriginSet, PagePseudoClassFlags, PageRule, PropertyRule,
|
||||
SanitizationData, SanitizationKind, StyleRule, StylesheetContents, StylesheetLoader as
|
||||
StyleStylesheetLoader, SupportsRule, UrlExtraData,
|
||||
SanitizationData, SanitizationKind, StyleRule, StylesheetContents,
|
||||
StylesheetLoader as StyleStylesheetLoader, SupportsRule, UrlExtraData,
|
||||
};
|
||||
use style::stylist::{add_size_of_ua_cache, AuthorStylesEnabled, RuleInclusion, Stylist};
|
||||
use style::thread_state;
|
||||
|
|
@ -148,6 +151,7 @@ use style::values::computed::font::{
|
|||
};
|
||||
use style::values::computed::{self, Context, ToComputedValue};
|
||||
use style::values::distance::ComputeSquaredDistance;
|
||||
use style::values::generics::color::ColorMixFlags;
|
||||
use style::values::generics::easing::BeforeFlag;
|
||||
use style::values::specified::gecko::IntersectionObserverRootMargin;
|
||||
use style::values::specified::source_size_list::SourceSizeList;
|
||||
|
|
@ -876,9 +880,7 @@ pub unsafe extern "C" fn Servo_AnimationValue_GetOffsetPosition(
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_AnimationValue_IsOffsetPathUrl(
|
||||
value: &AnimationValue,
|
||||
) -> bool {
|
||||
pub unsafe extern "C" fn Servo_AnimationValue_IsOffsetPathUrl(value: &AnimationValue) -> bool {
|
||||
use style::values::generics::motion::{GenericOffsetPath, GenericOffsetPathFunction};
|
||||
if let AnimationValue::OffsetPath(ref op) = value {
|
||||
if let GenericOffsetPath::OffsetPath { path, coord_box: _ } = op {
|
||||
|
|
@ -1196,22 +1198,28 @@ pub extern "C" fn Servo_ComputedValues_ShouldTransition(
|
|||
start: &mut structs::RefPtr<AnimationValue>,
|
||||
end: &mut structs::RefPtr<AnimationValue>,
|
||||
) -> ShouldTransitionResult {
|
||||
let Ok(prop) = LonghandId::from_nscsspropertyid(prop) else { return Default::default() };
|
||||
let Ok(prop) = LonghandId::from_nscsspropertyid(prop) else {
|
||||
return Default::default();
|
||||
};
|
||||
if prop.is_discrete_animatable() && prop != LonghandId::Visibility {
|
||||
return Default::default();
|
||||
}
|
||||
let Some(new_value) = AnimationValue::from_computed_values(prop, new) else { return Default::default() };
|
||||
let Some(new_value) = AnimationValue::from_computed_values(prop, new) else {
|
||||
return Default::default();
|
||||
};
|
||||
|
||||
if let Some(old_transition_value) = old_transition_value {
|
||||
if *old_transition_value == new_value {
|
||||
return ShouldTransitionResult {
|
||||
should_animate: false,
|
||||
old_transition_value_matches: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let Some(old_value) = AnimationValue::from_computed_values(prop, old) else { return Default::default() };
|
||||
let Some(old_value) = AnimationValue::from_computed_values(prop, old) else {
|
||||
return Default::default();
|
||||
};
|
||||
if old_value == new_value || !old_value.interpolable_with(&new_value) {
|
||||
return Default::default();
|
||||
}
|
||||
|
|
@ -1231,11 +1239,15 @@ pub extern "C" fn Servo_ComputedValues_TransitionValueMatches(
|
|||
prop: nsCSSPropertyID,
|
||||
transition_value: &AnimationValue,
|
||||
) -> bool {
|
||||
let Ok(prop) = LonghandId::from_nscsspropertyid(prop) else { return false };
|
||||
let Ok(prop) = LonghandId::from_nscsspropertyid(prop) else {
|
||||
return false;
|
||||
};
|
||||
if prop.is_discrete_animatable() && prop != LonghandId::Visibility {
|
||||
return false;
|
||||
}
|
||||
let Some(value) = AnimationValue::from_computed_values(prop, style) else { return false };
|
||||
let Some(value) = AnimationValue::from_computed_values(prop, style) else {
|
||||
return false;
|
||||
};
|
||||
value == *transition_value
|
||||
}
|
||||
|
||||
|
|
@ -1631,7 +1643,9 @@ pub unsafe extern "C" fn Servo_ShutdownThreadPool() {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_ThreadPool_GetThreadHandles(handles: &mut ThinVec<PlatformThreadHandle>) {
|
||||
pub unsafe extern "C" fn Servo_ThreadPool_GetThreadHandles(
|
||||
handles: &mut ThinVec<PlatformThreadHandle>,
|
||||
) {
|
||||
StyleThreadPool::get_thread_handles(handles);
|
||||
}
|
||||
|
||||
|
|
@ -2291,7 +2305,10 @@ impl_basic_rule_funcs! { (Style, StyleRule, Locked<StyleRule>),
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleRule_EnsureRules(rule: &LockedStyleRule, read_only: bool) -> Strong<LockedCssRules> {
|
||||
pub extern "C" fn Servo_StyleRule_EnsureRules(
|
||||
rule: &LockedStyleRule,
|
||||
read_only: bool,
|
||||
) -> Strong<LockedCssRules> {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let lock = &global_style_data.shared_lock;
|
||||
if read_only {
|
||||
|
|
@ -2465,7 +2482,9 @@ pub extern "C" fn Servo_StyleRule_GetSelectorDataAtIndex(
|
|||
specificity: Option<&mut u64>,
|
||||
) {
|
||||
let selectors = desugared_selector_list(rules);
|
||||
let Some(selector) = selectors.slice().get(index as usize) else { return };
|
||||
let Some(selector) = selectors.slice().get(index as usize) else {
|
||||
return;
|
||||
};
|
||||
if let Some(text) = text {
|
||||
selector.to_css(text).unwrap();
|
||||
}
|
||||
|
|
@ -2492,7 +2511,9 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(
|
|||
matches_selector, MatchingContext, MatchingMode, NeedsSelectorFlags, VisitedHandlingMode,
|
||||
};
|
||||
let selectors = desugared_selector_list(rules);
|
||||
let Some(selector) = selectors.slice().get(index as usize) else { return false };
|
||||
let Some(selector) = selectors.slice().get(index as usize) else {
|
||||
return false;
|
||||
};
|
||||
let mut matching_mode = MatchingMode::Normal;
|
||||
match PseudoElement::from_pseudo_type(pseudo_type, None) {
|
||||
Some(pseudo) => {
|
||||
|
|
@ -2548,8 +2569,8 @@ pub extern "C" fn Servo_StyleRule_SetSelectorText(
|
|||
let value_str = unsafe { text.as_str_unchecked() };
|
||||
|
||||
write_locked_arc(rule, |rule: &mut StyleRule| {
|
||||
use style::selector_parser::SelectorParser;
|
||||
use selectors::parser::ParseRelative;
|
||||
use style::selector_parser::SelectorParser;
|
||||
|
||||
let namespaces = contents.namespaces.read();
|
||||
let url_data = contents.url_data.read();
|
||||
|
|
@ -2563,7 +2584,11 @@ pub extern "C" fn Servo_StyleRule_SetSelectorText(
|
|||
// TODO: Maybe allow setting relative selectors from the OM, if we're in a nested style
|
||||
// rule?
|
||||
let mut parser_input = ParserInput::new(&value_str);
|
||||
match SelectorList::parse(&parser, &mut Parser::new(&mut parser_input), ParseRelative::No) {
|
||||
match SelectorList::parse(
|
||||
&parser,
|
||||
&mut Parser::new(&mut parser_input),
|
||||
ParseRelative::No,
|
||||
) {
|
||||
Ok(selectors) => {
|
||||
rule.selectors = selectors;
|
||||
true
|
||||
|
|
@ -4024,7 +4049,12 @@ pub extern "C" fn Servo_ResolvePseudoStyle(
|
|||
inherited_style,
|
||||
&doc_data.stylist,
|
||||
is_probe,
|
||||
/* matching_func = */ if pseudo_element.is_highlight() {Some(&matching_fn)} else {None},
|
||||
/* matching_func = */
|
||||
if pseudo_element.is_highlight() {
|
||||
Some(&matching_fn)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
);
|
||||
|
||||
match style {
|
||||
|
|
@ -4198,8 +4228,13 @@ fn get_pseudo_style(
|
|||
}
|
||||
|
||||
Some(style.unwrap_or_else(|| {
|
||||
StyleBuilder::for_inheritance(stylist.device(), Some(stylist), Some(styles.primary()), Some(pseudo))
|
||||
.build()
|
||||
StyleBuilder::for_inheritance(
|
||||
stylist.device(),
|
||||
Some(stylist),
|
||||
Some(styles.primary()),
|
||||
Some(pseudo),
|
||||
)
|
||||
.build()
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -4216,8 +4251,12 @@ pub unsafe extern "C" fn Servo_ComputedValues_Inherit(
|
|||
let pseudo = PseudoElement::from_pseudo_type(pseudo, None).unwrap();
|
||||
debug_assert!(pseudo.is_anon_box());
|
||||
|
||||
let mut style =
|
||||
StyleBuilder::for_inheritance(data.stylist.device(), Some(&data.stylist), parent_style_context, Some(&pseudo));
|
||||
let mut style = StyleBuilder::for_inheritance(
|
||||
data.stylist.device(),
|
||||
Some(&data.stylist),
|
||||
parent_style_context,
|
||||
Some(&pseudo),
|
||||
);
|
||||
|
||||
if for_text {
|
||||
StyleAdjuster::new(&mut style).adjust_for_text();
|
||||
|
|
@ -5207,7 +5246,8 @@ pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(
|
|||
use style::values::generics::box_::{VerticalAlign, VerticalAlignKeyword};
|
||||
use style::values::generics::font::FontStyle;
|
||||
use style::values::specified::{
|
||||
table::CaptionSide, BorderStyle, Clear, Display, Float, TextAlign, TextEmphasisPosition, TextTransform
|
||||
table::CaptionSide, BorderStyle, Clear, Display, Float, TextAlign, TextEmphasisPosition,
|
||||
TextTransform,
|
||||
};
|
||||
|
||||
fn get_from_computed<T>(value: u32) -> T
|
||||
|
|
@ -5407,7 +5447,9 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue(
|
|||
use style::properties::PropertyDeclaration;
|
||||
use style::values::generics::length::{LengthPercentageOrAuto, Size};
|
||||
use style::values::generics::NonNegative;
|
||||
use style::values::specified::length::{FontRelativeLength, LengthPercentage, ViewportPercentageLength};
|
||||
use style::values::specified::length::{
|
||||
FontRelativeLength, LengthPercentage, ViewportPercentageLength,
|
||||
};
|
||||
use style::values::specified::FontSize;
|
||||
|
||||
let long = get_longhand_from_id!(property);
|
||||
|
|
@ -6018,7 +6060,12 @@ fn create_context_for_animation<'a>(
|
|||
container_size_query: ContainerSizeQuery<'a>,
|
||||
) -> Context<'a> {
|
||||
Context::new_for_animation(
|
||||
StyleBuilder::for_animation(per_doc_data.stylist.device(), Some(&per_doc_data.stylist), style, parent_style),
|
||||
StyleBuilder::for_animation(
|
||||
per_doc_data.stylist.device(),
|
||||
Some(&per_doc_data.stylist),
|
||||
style,
|
||||
parent_style,
|
||||
),
|
||||
for_smil_animation,
|
||||
per_doc_data.stylist.quirks_mode(),
|
||||
rule_cache_conditions,
|
||||
|
|
@ -6196,7 +6243,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
|
|||
None
|
||||
} else {
|
||||
Some(&custom_properties)
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
for value in iter {
|
||||
|
|
@ -6224,7 +6271,8 @@ pub extern "C" fn Servo_GetAnimationValues(
|
|||
.map(|d| d.styles.primary())
|
||||
.map(|x| &**x);
|
||||
|
||||
let container_size_query = ContainerSizeQuery::for_element(element, None, /* is_pseudo = */ false);
|
||||
let container_size_query =
|
||||
ContainerSizeQuery::for_element(element, None, /* is_pseudo = */ false);
|
||||
let mut conditions = Default::default();
|
||||
let mut context = create_context_for_animation(
|
||||
&data,
|
||||
|
|
@ -6270,7 +6318,8 @@ pub extern "C" fn Servo_AnimationValue_Compute(
|
|||
.map(|d| d.styles.primary())
|
||||
.map(|x| &**x);
|
||||
|
||||
let container_size_query = ContainerSizeQuery::for_element(element, None, /* is_pseudo = */ false);
|
||||
let container_size_query =
|
||||
ContainerSizeQuery::for_element(element, None, /* is_pseudo = */ false);
|
||||
let mut conditions = Default::default();
|
||||
let mut context = create_context_for_animation(
|
||||
&data,
|
||||
|
|
@ -6930,7 +6979,7 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorIDDependency(
|
|||
scope,
|
||||
quirks_mode,
|
||||
&invalidation_map,
|
||||
collector
|
||||
collector,
|
||||
);
|
||||
add_relative_selector_attribute_dependency(
|
||||
element,
|
||||
|
|
@ -6972,7 +7021,7 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorClassDependency(
|
|||
scope,
|
||||
quirks_mode,
|
||||
invalidation_map,
|
||||
collector
|
||||
collector,
|
||||
);
|
||||
add_relative_selector_attribute_dependency(
|
||||
element,
|
||||
|
|
@ -7185,11 +7234,7 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorNthDependencyFro
|
|||
// Short of doing the actual matching, any of the siblings can match the selector, so we
|
||||
// have to try invalidating against all of them.
|
||||
while let Some(sibling) = element {
|
||||
invalidate_relative_selector_ts_dependency(
|
||||
raw_data,
|
||||
sibling,
|
||||
TSStateForInvalidation::NTH,
|
||||
);
|
||||
invalidate_relative_selector_ts_dependency(raw_data, sibling, TSStateForInvalidation::NTH);
|
||||
element = sibling.next_sibling_element();
|
||||
}
|
||||
}
|
||||
|
|
@ -7219,13 +7264,18 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorForInsertion(
|
|||
// Note that the previous sibling may be the anchor, and not part of the invalidation chain.
|
||||
// Either way, there must be siblings to both sides of the element being inserted
|
||||
// to consider it.
|
||||
match (element.prev_sibling_element(), element.next_sibling_element()) {
|
||||
match (
|
||||
element.prev_sibling_element(),
|
||||
element.next_sibling_element(),
|
||||
) {
|
||||
(Some(prev_sibling), Some(next_sibling)) => 'sibling: {
|
||||
// If the prev sibling is not on the sibling search path, skip.
|
||||
if prev_sibling
|
||||
.relative_selector_search_direction()
|
||||
.map_or(true, |direction| {
|
||||
!direction.intersects(ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING)
|
||||
!direction.intersects(
|
||||
ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
|
||||
)
|
||||
})
|
||||
{
|
||||
break 'sibling;
|
||||
|
|
@ -7257,7 +7307,6 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorForInsertion(
|
|||
_ => (),
|
||||
};
|
||||
|
||||
|
||||
let invalidator = RelativeSelectorInvalidator {
|
||||
element,
|
||||
quirks_mode,
|
||||
|
|
@ -7338,7 +7387,7 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorForRemoval(
|
|||
prev_sibling,
|
||||
quirks_mode,
|
||||
SiblingTraversalMap::default(),
|
||||
&data.stylist
|
||||
&data.stylist,
|
||||
);
|
||||
invalidate_relative_selector_next_sibling_side_effect(
|
||||
next_sibling,
|
||||
|
|
@ -7481,9 +7530,17 @@ pub unsafe extern "C" fn Servo_GetCustomPropertyValue(
|
|||
let stylist = &doc_data.stylist;
|
||||
let custom_registration = stylist.get_custom_property_registration(&name);
|
||||
let computed_value = if custom_registration.map_or(true, |r| r.inherits()) {
|
||||
computed_values.custom_properties.inherited.as_ref().and_then(|m| m.get(&name))
|
||||
computed_values
|
||||
.custom_properties
|
||||
.inherited
|
||||
.as_ref()
|
||||
.and_then(|m| m.get(&name))
|
||||
} else {
|
||||
computed_values.custom_properties.non_inherited.as_ref().and_then(|m| m.get(&name))
|
||||
computed_values
|
||||
.custom_properties
|
||||
.non_inherited
|
||||
.as_ref()
|
||||
.and_then(|m| m.get(&name))
|
||||
};
|
||||
|
||||
if let Some(v) = computed_value {
|
||||
|
|
@ -7508,7 +7565,10 @@ pub extern "C" fn Servo_GetCustomPropertyNameAt(
|
|||
computed_values: &ComputedValues,
|
||||
index: u32,
|
||||
) -> *mut nsAtom {
|
||||
match &computed_values.custom_properties.property_at(index as usize) {
|
||||
match &computed_values
|
||||
.custom_properties
|
||||
.property_at(index as usize)
|
||||
{
|
||||
Some((name, _value)) => name.as_ptr(),
|
||||
None => ptr::null_mut(),
|
||||
}
|
||||
|
|
@ -7528,8 +7588,10 @@ fn relative_selector_dependencies_for_id<'a>(
|
|||
invalidation_map: &'a RelativeSelectorInvalidationMap,
|
||||
collector: &mut RelativeSelectorDependencyCollector<'a, GeckoElement<'a>>,
|
||||
) {
|
||||
[old_id, new_id].iter().filter(|id| !id.is_null()).for_each(|id| {
|
||||
unsafe {
|
||||
[old_id, new_id]
|
||||
.iter()
|
||||
.filter(|id| !id.is_null())
|
||||
.for_each(|id| unsafe {
|
||||
AtomIdent::with(*id, |atom| {
|
||||
match invalidation_map.map.id_to_selector.get(atom, quirks_mode) {
|
||||
Some(v) => {
|
||||
|
|
@ -7540,8 +7602,7 @@ fn relative_selector_dependencies_for_id<'a>(
|
|||
None => (),
|
||||
};
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn relative_selector_dependencies_for_class<'a>(
|
||||
|
|
@ -7594,12 +7655,20 @@ fn process_relative_selector_invalidations(
|
|||
&data.stylist,
|
||||
|element, scope, data, quirks_mode, collector| {
|
||||
let invalidation_map = data.relative_selector_invalidation_map();
|
||||
let states = *states.get_or_insert_with(|| ElementWrapper::new(*element, snapshot_table).state_changes());
|
||||
let states = *states.get_or_insert_with(|| {
|
||||
ElementWrapper::new(*element, snapshot_table).state_changes()
|
||||
});
|
||||
let classes = classes.get_or_insert_with(|| classes_changed(element, snapshot_table));
|
||||
if snapshot.id_changed() {
|
||||
relative_selector_dependencies_for_id(
|
||||
element.id().map(|id| id.as_ptr().cast_const()).unwrap_or(ptr::null()),
|
||||
snapshot.id_attr().map(|id| id.as_ptr().cast_const()).unwrap_or(ptr::null()),
|
||||
element
|
||||
.id()
|
||||
.map(|id| id.as_ptr().cast_const())
|
||||
.unwrap_or(ptr::null()),
|
||||
snapshot
|
||||
.id_attr()
|
||||
.map(|id| id.as_ptr().cast_const())
|
||||
.unwrap_or(ptr::null()),
|
||||
element,
|
||||
scope,
|
||||
quirks_mode,
|
||||
|
|
@ -7607,8 +7676,23 @@ fn process_relative_selector_invalidations(
|
|||
collector,
|
||||
);
|
||||
}
|
||||
relative_selector_dependencies_for_class(&classes, element, scope, quirks_mode, invalidation_map, collector);
|
||||
snapshot.each_attr_changed(|attr| add_relative_selector_attribute_dependency(element, &scope, invalidation_map, attr, collector));
|
||||
relative_selector_dependencies_for_class(
|
||||
&classes,
|
||||
element,
|
||||
scope,
|
||||
quirks_mode,
|
||||
invalidation_map,
|
||||
collector,
|
||||
);
|
||||
snapshot.each_attr_changed(|attr| {
|
||||
add_relative_selector_attribute_dependency(
|
||||
element,
|
||||
&scope,
|
||||
invalidation_map,
|
||||
attr,
|
||||
collector,
|
||||
)
|
||||
});
|
||||
invalidation_map
|
||||
.map
|
||||
.state_affecting_selectors
|
||||
|
|
@ -7960,7 +8044,10 @@ pub extern "C" fn Servo_ParseFilters(
|
|||
|
||||
let mut filters = vec![];
|
||||
|
||||
if parser.try_parse(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
if parser
|
||||
.try_parse(|i| i.expect_ident_matching("none"))
|
||||
.is_ok()
|
||||
{
|
||||
return parser.expect_exhausted().is_ok();
|
||||
}
|
||||
|
||||
|
|
@ -8070,9 +8157,9 @@ pub unsafe extern "C" fn Servo_ParseFontShorthandForMatching(
|
|||
},
|
||||
specified::FontSize::Keyword(info) => {
|
||||
let keyword = if info.kw != specified::FontSizeKeyword::Math {
|
||||
info.kw
|
||||
info.kw
|
||||
} else {
|
||||
specified::FontSizeKeyword::Medium
|
||||
specified::FontSizeKeyword::Medium
|
||||
};
|
||||
// Map absolute-size keywords to sizes.
|
||||
// TODO: Maybe get a meaningful quirks / base size from the caller?
|
||||
|
|
@ -8533,12 +8620,10 @@ pub extern "C" fn Servo_ParseLengthWithoutStyleContext(
|
|||
len: &nsACString,
|
||||
out: &mut f32,
|
||||
get_font_metrics: Option<unsafe extern "C" fn(*mut c_void) -> GeckoFontMetrics>,
|
||||
getter_context: *mut c_void
|
||||
getter_context: *mut c_void,
|
||||
) -> bool {
|
||||
let metrics_getter = if let Some(getter) = get_font_metrics {
|
||||
Some(move || -> GeckoFontMetrics {
|
||||
unsafe { getter(getter_context) }
|
||||
})
|
||||
Some(move || -> GeckoFontMetrics { unsafe { getter(getter_context) } })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -8574,7 +8659,13 @@ pub extern "C" fn Servo_SlowRgbToColorName(r: u8, g: u8, b: u8, result: &mut nsA
|
|||
pub extern "C" fn Servo_ColorNameToRgb(name: &nsACString, out: &mut structs::nscolor) -> bool {
|
||||
match cssparser::color::parse_named_color(unsafe { name.as_str_unchecked() }) {
|
||||
Ok((r, g, b)) => {
|
||||
*out = style::gecko::values::convert_absolute_color_to_nscolor(&AbsoluteColor::new(ColorSpace::Srgb, r, g, b, 1.0));
|
||||
*out = style::gecko::values::convert_absolute_color_to_nscolor(&AbsoluteColor::new(
|
||||
ColorSpace::Srgb,
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
1.0,
|
||||
));
|
||||
true
|
||||
},
|
||||
_ => false,
|
||||
|
|
@ -8621,25 +8712,34 @@ pub extern "C" fn Servo_RegisterCustomProperty(
|
|||
|
||||
// If property set already contains an entry with name as its property name (compared
|
||||
// codepoint-wise), throw an InvalidModificationError and exit this algorithm.
|
||||
if per_doc_data.stylist.custom_property_script_registry().get(&name).is_some() {
|
||||
return AlreadyRegistered
|
||||
if per_doc_data
|
||||
.stylist
|
||||
.custom_property_script_registry()
|
||||
.get(&name)
|
||||
.is_some()
|
||||
{
|
||||
return AlreadyRegistered;
|
||||
}
|
||||
// Attempt to consume a syntax definition from syntax. If it returns failure, throw a
|
||||
// SyntaxError. Otherwise, let syntax definition be the returned syntax definition.
|
||||
let Ok(syntax) = Descriptor::from_str(syntax, /* preserve_specified = */ false) else { return InvalidSyntax };
|
||||
let Ok(syntax) = Descriptor::from_str(syntax, /* preserve_specified = */ false) else {
|
||||
return InvalidSyntax;
|
||||
};
|
||||
|
||||
let initial_value = match initial_value {
|
||||
Some(v) => {
|
||||
let mut input = ParserInput::new(v);
|
||||
let parsed = Parser::new(&mut input).parse_entirely(|input| {
|
||||
input.skip_whitespace();
|
||||
SpecifiedValue::parse(input, url_data)
|
||||
}).ok();
|
||||
let parsed = Parser::new(&mut input)
|
||||
.parse_entirely(|input| {
|
||||
input.skip_whitespace();
|
||||
SpecifiedValue::parse(input, url_data)
|
||||
})
|
||||
.ok();
|
||||
if parsed.is_none() {
|
||||
return InvalidInitialValue
|
||||
return InvalidInitialValue;
|
||||
}
|
||||
parsed
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
|
|
@ -8647,27 +8747,33 @@ pub extern "C" fn Servo_RegisterCustomProperty(
|
|||
PropertyRegistration::validate_initial_value(&syntax, initial_value.as_ref())
|
||||
{
|
||||
return match error {
|
||||
PropertyRegistrationError::InitialValueNotComputationallyIndependent => InitialValueNotComputationallyIndependent,
|
||||
PropertyRegistrationError::InitialValueNotComputationallyIndependent => {
|
||||
InitialValueNotComputationallyIndependent
|
||||
},
|
||||
PropertyRegistrationError::InvalidInitialValue => InvalidInitialValue,
|
||||
PropertyRegistrationError::NoInitialValue=> NoInitialValue,
|
||||
}
|
||||
PropertyRegistrationError::NoInitialValue => NoInitialValue,
|
||||
};
|
||||
}
|
||||
|
||||
per_doc_data
|
||||
.stylist
|
||||
.custom_property_script_registry_mut()
|
||||
.register(
|
||||
PropertyRegistration {
|
||||
name: PropertyRuleName(name),
|
||||
syntax,
|
||||
inherits: if inherits { PropertyInherits::True } else { PropertyInherits::False },
|
||||
initial_value,
|
||||
url_data: url_data.clone(),
|
||||
source_location: SourceLocation { line: 0, column: 0 },
|
||||
.register(PropertyRegistration {
|
||||
name: PropertyRuleName(name),
|
||||
syntax,
|
||||
inherits: if inherits {
|
||||
PropertyInherits::True
|
||||
} else {
|
||||
PropertyInherits::False
|
||||
},
|
||||
);
|
||||
initial_value,
|
||||
url_data: url_data.clone(),
|
||||
source_location: SourceLocation { line: 0, column: 0 },
|
||||
});
|
||||
|
||||
per_doc_data.stylist.rebuild_initial_values_for_custom_properties();
|
||||
per_doc_data
|
||||
.stylist
|
||||
.rebuild_initial_values_for_custom_properties();
|
||||
|
||||
SuccessfullyRegistered
|
||||
}
|
||||
|
|
@ -8686,21 +8792,19 @@ pub struct PropDef {
|
|||
pub from_js: bool,
|
||||
}
|
||||
|
||||
|
||||
impl PropDef {
|
||||
/// Creates a PropDef from a name and a PropertyRegistration.
|
||||
pub fn new(
|
||||
name: Atom,
|
||||
property_registration: &PropertyRegistration,
|
||||
from_js: bool
|
||||
) -> Self {
|
||||
pub fn new(name: Atom, property_registration: &PropertyRegistration, from_js: bool) -> Self {
|
||||
let mut syntax = nsCString::new();
|
||||
if let Some(spec) = property_registration.syntax.specified_string() {
|
||||
syntax.assign(spec);
|
||||
} else {
|
||||
// FIXME: Descriptor::to_css should behave consistently (probably this shouldn't use
|
||||
// the ToCss trait).
|
||||
property_registration.syntax.to_css(&mut CssWriter::new(&mut syntax)).unwrap();
|
||||
property_registration
|
||||
.syntax
|
||||
.to_css(&mut CssWriter::new(&mut syntax))
|
||||
.unwrap();
|
||||
};
|
||||
let initial_value = property_registration.initial_value.to_css_nscstring();
|
||||
|
||||
|
|
@ -8710,7 +8814,7 @@ impl PropDef {
|
|||
inherits: property_registration.inherits(),
|
||||
has_initial_value: property_registration.initial_value.is_some(),
|
||||
initial_value,
|
||||
from_js
|
||||
from_js,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8727,31 +8831,23 @@ pub extern "C" fn Servo_GetRegisteredCustomProperties(
|
|||
.custom_property_script_registry()
|
||||
.get_all()
|
||||
.iter()
|
||||
.map(|(name, property_registration)|
|
||||
.map(|(name, property_registration)| {
|
||||
PropDef::new(name.clone(), property_registration, /* from_js */ true)
|
||||
}),
|
||||
);
|
||||
|
||||
for (cascade_data, _origin) in stylist.iter_origins() {
|
||||
custom_properties.extend(cascade_data.custom_property_registrations().iter().map(
|
||||
|(name, value)| {
|
||||
let property_registration = &value.last().unwrap().0;
|
||||
PropDef::new(
|
||||
name.clone(),
|
||||
property_registration,
|
||||
/* from_js */
|
||||
true
|
||||
false,
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
for (cascade_data, _origin) in stylist.iter_origins() {
|
||||
custom_properties.extend(
|
||||
cascade_data
|
||||
.custom_property_registrations()
|
||||
.iter()
|
||||
.map(|(name, value)| {
|
||||
let property_registration = &value.last().unwrap().0;
|
||||
PropDef::new(
|
||||
name.clone(),
|
||||
property_registration,
|
||||
/* from_js */
|
||||
false
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8768,14 +8864,11 @@ pub extern "C" fn Servo_GetSelectorWarnings(
|
|||
rule: &LockedStyleRule,
|
||||
warnings: &mut ThinVec<SelectorWarningData>,
|
||||
) {
|
||||
read_locked_arc(rule, |r|
|
||||
read_locked_arc(rule, |r| {
|
||||
for (i, selector) in r.selectors.slice().iter().enumerate() {
|
||||
for k in SelectorWarningKind::from_selector(selector) {
|
||||
warnings.push(SelectorWarningData {
|
||||
index: i,
|
||||
kind: k,
|
||||
});
|
||||
warnings.push(SelectorWarningData { index: i, kind: k });
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ pub mod does_not_impl_malloc_size_of {
|
|||
*/
|
||||
pub fn servo_arc() {}
|
||||
|
||||
|
||||
/**
|
||||
```compile_fail,E0277
|
||||
extern crate malloc_size_of;
|
||||
|
|
@ -49,7 +48,6 @@ pub mod does_not_impl_malloc_size_of {
|
|||
*/
|
||||
pub fn std_arc() {}
|
||||
|
||||
|
||||
/**
|
||||
```compile_fail,E0277
|
||||
extern crate malloc_size_of;
|
||||
|
|
@ -79,7 +77,6 @@ pub mod does_not_impl_malloc_shallow_size_of {
|
|||
*/
|
||||
pub fn servo_arc() {}
|
||||
|
||||
|
||||
/**
|
||||
```compile_fail,E0277
|
||||
extern crate malloc_size_of;
|
||||
|
|
@ -93,7 +90,6 @@ pub mod does_not_impl_malloc_shallow_size_of {
|
|||
*/
|
||||
pub fn std_arc() {}
|
||||
|
||||
|
||||
/**
|
||||
```compile_fail,E0277
|
||||
extern crate malloc_size_of;
|
||||
|
|
|
|||
|
|
@ -11,53 +11,76 @@ fn interpolate_rgba(from: RGBA, to: RGBA, progress: f64) -> RGBA {
|
|||
let from = from.to_animated_value();
|
||||
let to = to.to_animated_value();
|
||||
RGBA::from_animated_value(
|
||||
from.animate(&to, Procedure::Interpolate { progress }).unwrap(),
|
||||
from.animate(&to, Procedure::Interpolate { progress })
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
// Color
|
||||
#[test]
|
||||
fn test_rgba_color_interepolation_preserves_transparent() {
|
||||
assert_eq!(interpolate_rgba(RGBA::transparent(),
|
||||
RGBA::transparent(), 0.5),
|
||||
RGBA::transparent());
|
||||
assert_eq!(
|
||||
interpolate_rgba(RGBA::transparent(), RGBA::transparent(), 0.5),
|
||||
RGBA::transparent()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgba_color_interepolation_alpha() {
|
||||
assert_eq!(interpolate_rgba(RGBA::new(200, 0, 0, 100),
|
||||
RGBA::new(0, 200, 0, 200), 0.5),
|
||||
RGBA::new(67, 133, 0, 150));
|
||||
assert_eq!(
|
||||
interpolate_rgba(RGBA::new(200, 0, 0, 100), RGBA::new(0, 200, 0, 200), 0.5),
|
||||
RGBA::new(67, 133, 0, 150)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgba_color_interepolation_out_of_range_1() {
|
||||
// Some cubic-bezier functions produce values that are out of range [0, 1].
|
||||
// Unclamped cases.
|
||||
assert_eq!(interpolate_rgba(RGBA::from_floats(0.3, 0.0, 0.0, 0.4),
|
||||
RGBA::from_floats(0.0, 1.0, 0.0, 0.6), -0.5),
|
||||
RGBA::new(154, 0, 0, 77));
|
||||
assert_eq!(
|
||||
interpolate_rgba(
|
||||
RGBA::from_floats(0.3, 0.0, 0.0, 0.4),
|
||||
RGBA::from_floats(0.0, 1.0, 0.0, 0.6),
|
||||
-0.5
|
||||
),
|
||||
RGBA::new(154, 0, 0, 77)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgba_color_interepolation_out_of_range_2() {
|
||||
assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.6),
|
||||
RGBA::from_floats(0.0, 0.3, 0.0, 0.4), 1.5),
|
||||
RGBA::new(0, 154, 0, 77));
|
||||
assert_eq!(
|
||||
interpolate_rgba(
|
||||
RGBA::from_floats(1.0, 0.0, 0.0, 0.6),
|
||||
RGBA::from_floats(0.0, 0.3, 0.0, 0.4),
|
||||
1.5
|
||||
),
|
||||
RGBA::new(0, 154, 0, 77)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgba_color_interepolation_out_of_range_clamped_1() {
|
||||
assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
|
||||
RGBA::from_floats(0.0, 1.0, 0.0, 0.2), -0.5),
|
||||
RGBA::from_floats(1.0, 0.0, 0.0, 1.0));
|
||||
assert_eq!(
|
||||
interpolate_rgba(
|
||||
RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
|
||||
RGBA::from_floats(0.0, 1.0, 0.0, 0.2),
|
||||
-0.5
|
||||
),
|
||||
RGBA::from_floats(1.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgba_color_interepolation_out_of_range_clamped_2() {
|
||||
assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
|
||||
RGBA::from_floats(0.0, 1.0, 0.0, 0.2), 1.5),
|
||||
RGBA::from_floats(0.0, 0.0, 0.0, 0.0));
|
||||
assert_eq!(
|
||||
interpolate_rgba(
|
||||
RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
|
||||
RGBA::from_floats(0.0, 1.0, 0.0, 0.2),
|
||||
1.5
|
||||
),
|
||||
RGBA::from_floats(0.0, 0.0, 0.0, 0.0)
|
||||
);
|
||||
}
|
||||
|
||||
// Transform
|
||||
|
|
@ -65,16 +88,19 @@ fn test_rgba_color_interepolation_out_of_range_clamped_2() {
|
|||
fn test_transform_interpolation_on_translate() {
|
||||
use style::values::computed::{CalcLengthPercentage, Length, LengthPercentage};
|
||||
|
||||
let from = Transform(vec![
|
||||
TransformOperation::Translate3D(LengthPercentage::Length(Length::new(0.)),
|
||||
LengthPercentage::Length(Length::new(100.)),
|
||||
Length::new(25.))]);
|
||||
let to = Transform(vec![
|
||||
TransformOperation::Translate3D(LengthPercentage::Length(Length::new(100.)),
|
||||
LengthPercentage::Length(Length::new(0.)),
|
||||
Length::new(75.))]);
|
||||
let from = Transform(vec![TransformOperation::Translate3D(
|
||||
LengthPercentage::Length(Length::new(0.)),
|
||||
LengthPercentage::Length(Length::new(100.)),
|
||||
Length::new(25.),
|
||||
)]);
|
||||
let to = Transform(vec![TransformOperation::Translate3D(
|
||||
LengthPercentage::Length(Length::new(100.)),
|
||||
LengthPercentage::Length(Length::new(0.)),
|
||||
Length::new(75.),
|
||||
)]);
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 })
|
||||
.unwrap(),
|
||||
Transform(vec![TransformOperation::Translate3D(
|
||||
LengthPercentage::Length(Length::new(50.)),
|
||||
LengthPercentage::Length(Length::new(50.)),
|
||||
|
|
@ -87,19 +113,25 @@ fn test_transform_interpolation_on_translate() {
|
|||
LengthPercentage::Percentage(Percentage(1.0)),
|
||||
Length::new(25.),
|
||||
)]);
|
||||
let to = Transform(vec![
|
||||
TransformOperation::Translate3D(LengthPercentage::Length(Length::new(100.)),
|
||||
LengthPercentage::Length(Length::new(50.)),
|
||||
Length::new(75.))]);
|
||||
let to = Transform(vec![TransformOperation::Translate3D(
|
||||
LengthPercentage::Length(Length::new(100.)),
|
||||
LengthPercentage::Length(Length::new(50.)),
|
||||
Length::new(75.),
|
||||
)]);
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 })
|
||||
.unwrap(),
|
||||
Transform(vec![TransformOperation::Translate3D(
|
||||
// calc(50px + 25%)
|
||||
LengthPercentage::Calc(CalcLengthPercentage::new(Length::new(50.),
|
||||
Some(Percentage(0.25)))),
|
||||
LengthPercentage::Calc(CalcLengthPercentage::new(
|
||||
Length::new(50.),
|
||||
Some(Percentage(0.25))
|
||||
)),
|
||||
// calc(25px + 50%)
|
||||
LengthPercentage::Calc(CalcLengthPercentage::new(Length::new(25.),
|
||||
Some(Percentage(0.5)))),
|
||||
LengthPercentage::Calc(CalcLengthPercentage::new(
|
||||
Length::new(25.),
|
||||
Some(Percentage(0.5))
|
||||
)),
|
||||
Length::new(50.),
|
||||
)])
|
||||
);
|
||||
|
|
@ -110,7 +142,8 @@ fn test_transform_interpolation_on_scale() {
|
|||
let from = Transform(vec![TransformOperation::Scale3D(1.0, 2.0, 1.0)]);
|
||||
let to = Transform(vec![TransformOperation::Scale3D(2.0, 4.0, 2.0)]);
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 })
|
||||
.unwrap(),
|
||||
Transform(vec![TransformOperation::Scale3D(1.5, 3.0, 1.5)])
|
||||
);
|
||||
}
|
||||
|
|
@ -119,15 +152,27 @@ fn test_transform_interpolation_on_scale() {
|
|||
fn test_transform_interpolation_on_rotate() {
|
||||
use style::values::computed::Angle;
|
||||
|
||||
let from = Transform(vec![TransformOperation::Rotate3D(0.0, 0.0, 1.0,
|
||||
Angle::from_radians(0.0))]);
|
||||
let to = Transform(vec![TransformOperation::Rotate3D(0.0, 0.0, 1.0,
|
||||
Angle::from_radians(100.0))]);
|
||||
let from = Transform(vec![TransformOperation::Rotate3D(
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
Angle::from_radians(0.0),
|
||||
)]);
|
||||
let to = Transform(vec![TransformOperation::Rotate3D(
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
Angle::from_radians(100.0),
|
||||
)]);
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
Transform(vec![
|
||||
TransformOperation::Rotate3D(0.0, 0.0, 1.0, Angle::from_radians(50.0)),
|
||||
])
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 })
|
||||
.unwrap(),
|
||||
Transform(vec![TransformOperation::Rotate3D(
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
Angle::from_radians(50.0)
|
||||
),])
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -135,12 +180,17 @@ fn test_transform_interpolation_on_rotate() {
|
|||
fn test_transform_interpolation_on_skew() {
|
||||
use style::values::computed::Angle;
|
||||
|
||||
let from = Transform(vec![TransformOperation::Skew(Angle::from_radians(0.0),
|
||||
Some(Angle::from_radians(100.0)))]);
|
||||
let to = Transform(vec![TransformOperation::Skew(Angle::from_radians(100.0),
|
||||
Some(Angle::from_radians(0.0)))]);
|
||||
let from = Transform(vec![TransformOperation::Skew(
|
||||
Angle::from_radians(0.0),
|
||||
Some(Angle::from_radians(100.0)),
|
||||
)]);
|
||||
let to = Transform(vec![TransformOperation::Skew(
|
||||
Angle::from_radians(100.0),
|
||||
Some(Angle::from_radians(0.0)),
|
||||
)]);
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 })
|
||||
.unwrap(),
|
||||
Transform(vec![TransformOperation::Skew(
|
||||
Angle::from_radians(50.0),
|
||||
Some(Angle::from_radians(50.0)),
|
||||
|
|
@ -152,14 +202,20 @@ fn test_transform_interpolation_on_skew() {
|
|||
fn test_transform_interpolation_on_mismatched_lists() {
|
||||
use style::values::computed::{Angle, Length, LengthPercentage};
|
||||
|
||||
let from = Transform(vec![TransformOperation::Rotate3D(0.0, 0.0, 1.0,
|
||||
Angle::from_radians(100.0))]);
|
||||
let to = Transform(vec![
|
||||
TransformOperation::Translate3D(LengthPercentage::Length(Length::new(100.)),
|
||||
LengthPercentage::Length(Length::new(0.)),
|
||||
Length::new(0.))]);
|
||||
let from = Transform(vec![TransformOperation::Rotate3D(
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
Angle::from_radians(100.0),
|
||||
)]);
|
||||
let to = Transform(vec![TransformOperation::Translate3D(
|
||||
LengthPercentage::Length(Length::new(100.)),
|
||||
LengthPercentage::Length(Length::new(0.)),
|
||||
Length::new(0.),
|
||||
)]);
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 })
|
||||
.unwrap(),
|
||||
Transform(vec![TransformOperation::InterpolateMatrix {
|
||||
from_list: from.clone(),
|
||||
to_list: to.clone(),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use app_units::Au;
|
||||
use style::attr::{AttrValue, LengthPercentageOrAuto, parse_length};
|
||||
use style::attr::{parse_length, AttrValue, LengthPercentageOrAuto};
|
||||
use style::values::computed::{CalcLengthPercentage, Percentage};
|
||||
|
||||
#[test]
|
||||
|
|
@ -23,7 +23,7 @@ fn test_parse_double() {
|
|||
let value = String::from("432.5e2");
|
||||
match AttrValue::from_double(value, 0.0) {
|
||||
AttrValue::Double(_, num) => assert_eq!(num, 43250f64),
|
||||
_ => panic!("expected a double value")
|
||||
_ => panic!("expected a double value"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ fn test_parse_double_negative_prefix() {
|
|||
let value = String::from("-5.6");
|
||||
match AttrValue::from_double(value, 0.0) {
|
||||
AttrValue::Double(_, num) => assert_eq!(num, -5.6f64),
|
||||
_ => panic!("expected a double value")
|
||||
_ => panic!("expected a double value"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ fn test_parse_double_positive_prefix() {
|
|||
let value = String::from("+5.6");
|
||||
match AttrValue::from_double(value, 0.0) {
|
||||
AttrValue::Double(_, num) => assert_eq!(num, 5.6f64),
|
||||
_ => panic!("expected a double value")
|
||||
_ => panic!("expected a double value"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ fn test_from_limited_i32_should_be_default_when_less_than_0() {
|
|||
let value = String::from("-1");
|
||||
match AttrValue::from_limited_i32(value, 0) {
|
||||
AttrValue::Int(_, 0) => (),
|
||||
_ => panic!("expected an IndexSize error")
|
||||
_ => panic!("expected an IndexSize error"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ fn test_from_limited_i32_should_be_default_when_less_than_0() {
|
|||
fn test_from_limited_i32_should_parse_a_uint_when_value_is_0_or_greater() {
|
||||
match AttrValue::from_limited_i32(String::from("1"), 0) {
|
||||
AttrValue::Int(_, 1) => (),
|
||||
_ => panic!("expected an successful parsing")
|
||||
_ => panic!("expected an successful parsing"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ fn test_from_limited_i32_should_keep_parsed_value_when_not_an_int() {
|
|||
AttrValue::Int(p, 0) => {
|
||||
assert_eq!(p, String::from("parsed-value"))
|
||||
},
|
||||
_ => panic!("expected an successful parsing")
|
||||
_ => panic!("expected an successful parsing"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +82,13 @@ pub fn test_parse_length() {
|
|||
check("0", LengthPercentageOrAuto::Length(Au::from_px(0)));
|
||||
check("0.000%", LengthPercentageOrAuto::Percentage(0.0));
|
||||
check("+5.82%", LengthPercentageOrAuto::Percentage(0.0582));
|
||||
check("5.82", LengthPercentageOrAuto::Length(Au::from_f64_px(5.82)));
|
||||
check(
|
||||
"5.82",
|
||||
LengthPercentageOrAuto::Length(Au::from_f64_px(5.82)),
|
||||
);
|
||||
check("invalid", LengthPercentageOrAuto::Auto);
|
||||
check("12 followed by invalid", LengthPercentageOrAuto::Length(Au::from_px(12)));
|
||||
check(
|
||||
"12 followed by invalid",
|
||||
LengthPercentageOrAuto::Length(Au::from_px(12)),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
use cssparser::{Parser, ParserInput};
|
||||
use servo_arc::Arc;
|
||||
use style::custom_properties::{Name, SpecifiedValue, CustomPropertiesMap, CustomPropertiesBuilder, CssEnvironment};
|
||||
use style::custom_properties::{
|
||||
CssEnvironment, CustomPropertiesBuilder, CustomPropertiesMap, Name, SpecifiedValue,
|
||||
};
|
||||
use style::properties::CustomDeclarationValue;
|
||||
use test::{self, Bencher};
|
||||
|
||||
|
|
@ -12,11 +14,17 @@ fn cascade(
|
|||
name_and_value: &[(&str, &str)],
|
||||
inherited: Option<&Arc<CustomPropertiesMap>>,
|
||||
) -> Option<Arc<CustomPropertiesMap>> {
|
||||
let values = name_and_value.iter().map(|&(name, value)| {
|
||||
let mut input = ParserInput::new(value);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
(Name::from(name), SpecifiedValue::parse(&mut parser).unwrap())
|
||||
}).collect::<Vec<_>>();
|
||||
let values = name_and_value
|
||||
.iter()
|
||||
.map(|&(name, value)| {
|
||||
let mut input = ParserInput::new(value);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
(
|
||||
Name::from(name),
|
||||
SpecifiedValue::parse(&mut parser).unwrap(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let env = CssEnvironment;
|
||||
let mut builder = CustomPropertiesBuilder::new(inherited, &env);
|
||||
|
|
@ -31,14 +39,11 @@ fn cascade(
|
|||
#[bench]
|
||||
fn cascade_custom_simple(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let parent = cascade(&[
|
||||
("foo", "10px"),
|
||||
("bar", "100px"),
|
||||
], None);
|
||||
let parent = cascade(&[("foo", "10px"), ("bar", "100px")], None);
|
||||
|
||||
test::black_box(cascade(&[
|
||||
("baz", "calc(40em + 4px)"),
|
||||
("bazz", "calc(30em + 4px)"),
|
||||
], parent.as_ref()))
|
||||
test::black_box(cascade(
|
||||
&[("baz", "calc(40em + 4px)"), ("bazz", "calc(30em + 4px)")],
|
||||
parent.as_ref(),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use euclid::{Size2D, Point2D, SideOffsets2D, Rect};
|
||||
use style::logical_geometry::{WritingMode, LogicalSize, LogicalPoint, LogicalMargin, LogicalRect};
|
||||
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
|
||||
use style::logical_geometry::{LogicalMargin, LogicalPoint, LogicalRect, LogicalSize, WritingMode};
|
||||
|
||||
#[cfg(test)]
|
||||
fn modes() -> Vec<WritingMode> {
|
||||
|
|
@ -19,8 +19,14 @@ fn modes() -> Vec<WritingMode> {
|
|||
WritingMode::RTL,
|
||||
WritingMode::VERTICAL | WritingMode::RTL,
|
||||
WritingMode::VERTICAL | WritingMode::VERTICAL_LR | WritingMode::RTL,
|
||||
WritingMode::VERTICAL | WritingMode::VERTICAL_LR | WritingMode::VERTICAL_SIDEWAYS | WritingMode::RTL,
|
||||
WritingMode::VERTICAL | WritingMode::VERTICAL_LR | WritingMode::TEXT_SIDEWAYS | WritingMode::RTL,
|
||||
WritingMode::VERTICAL |
|
||||
WritingMode::VERTICAL_LR |
|
||||
WritingMode::VERTICAL_SIDEWAYS |
|
||||
WritingMode::RTL,
|
||||
WritingMode::VERTICAL |
|
||||
WritingMode::VERTICAL_LR |
|
||||
WritingMode::TEXT_SIDEWAYS |
|
||||
WritingMode::RTL,
|
||||
WritingMode::VERTICAL | WritingMode::VERTICAL_LR | WritingMode::UPRIGHT | WritingMode::RTL,
|
||||
WritingMode::VERTICAL | WritingMode::VERTICAL_SIDEWAYS | WritingMode::RTL,
|
||||
WritingMode::VERTICAL | WritingMode::TEXT_SIDEWAYS | WritingMode::RTL,
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ use euclid::Size2D;
|
|||
use servo_arc::Arc;
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::ToOwned;
|
||||
use style::Atom;
|
||||
use style::context::QuirksMode;
|
||||
use style::media_queries::*;
|
||||
use style::servo::media_queries::*;
|
||||
use style::shared_lock::SharedRwLock;
|
||||
use style::stylesheets::{AllRules, Stylesheet, StylesheetInDocument, Origin, CssRule};
|
||||
use style::values::{CustomIdent, specified};
|
||||
use style::stylesheets::{AllRules, CssRule, Origin, Stylesheet, StylesheetInDocument};
|
||||
use style::values::{specified, CustomIdent};
|
||||
use style::Atom;
|
||||
use style_traits::ToCss;
|
||||
|
||||
fn test_media_rule<F>(css: &str, callback: F)
|
||||
|
|
@ -25,9 +25,21 @@ where
|
|||
let lock = SharedRwLock::new();
|
||||
let media_list = Arc::new(lock.wrap(MediaList::empty()));
|
||||
let stylesheet = Stylesheet::from_str(
|
||||
css, url, Origin::Author, media_list, lock,
|
||||
None, None, QuirksMode::NoQuirks, 0);
|
||||
let dummy = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
|
||||
css,
|
||||
url,
|
||||
Origin::Author,
|
||||
media_list,
|
||||
lock,
|
||||
None,
|
||||
None,
|
||||
QuirksMode::NoQuirks,
|
||||
0,
|
||||
);
|
||||
let dummy = Device::new(
|
||||
MediaType::screen(),
|
||||
Size2D::new(200.0, 100.0),
|
||||
Scale::new(1.0),
|
||||
);
|
||||
let mut rule_count = 0;
|
||||
let guard = stylesheet.shared_lock.read();
|
||||
for rule in stylesheet.iter_rules::<AllRules>(&dummy, &guard) {
|
||||
|
|
@ -44,8 +56,16 @@ fn media_query_test(device: &Device, css: &str, expected_rule_count: usize) {
|
|||
let lock = SharedRwLock::new();
|
||||
let media_list = Arc::new(lock.wrap(MediaList::empty()));
|
||||
let ss = Stylesheet::from_str(
|
||||
css, url, Origin::Author, media_list, lock,
|
||||
None, None, QuirksMode::NoQuirks, 0);
|
||||
css,
|
||||
url,
|
||||
Origin::Author,
|
||||
media_list,
|
||||
lock,
|
||||
None,
|
||||
None,
|
||||
QuirksMode::NoQuirks,
|
||||
0,
|
||||
);
|
||||
let mut rule_count = 0;
|
||||
ss.effective_style_rules(device, &ss.shared_lock.read(), |_| rule_count += 1);
|
||||
assert!(rule_count == expected_rule_count, css.to_owned());
|
||||
|
|
@ -64,7 +84,10 @@ fn test_mq_screen() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::screen()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::screen()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
|
||||
|
|
@ -72,7 +95,10 @@ fn test_mq_screen() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::screen()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::screen()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
|
||||
|
|
@ -80,7 +106,10 @@ fn test_mq_screen() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::screen()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::screen()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
}
|
||||
|
|
@ -91,7 +120,10 @@ fn test_mq_print() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::print()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::print()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
|
||||
|
|
@ -99,7 +131,10 @@ fn test_mq_print() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::print()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::print()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
|
||||
|
|
@ -107,7 +142,10 @@ fn test_mq_print() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::print()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::print()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
}
|
||||
|
|
@ -118,8 +156,10 @@ fn test_mq_unknown() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(
|
||||
MediaType(CustomIdent(Atom::from("fridge")))), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType(CustomIdent(Atom::from("fridge")))),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
|
||||
|
|
@ -127,8 +167,10 @@ fn test_mq_unknown() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(
|
||||
MediaType(CustomIdent(Atom::from("glass")))), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType(CustomIdent(Atom::from("glass")))),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
|
||||
|
|
@ -136,8 +178,10 @@ fn test_mq_unknown() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(
|
||||
MediaType(CustomIdent(Atom::from("wood")))), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType(CustomIdent(Atom::from("wood")))),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
}
|
||||
|
|
@ -175,12 +219,18 @@ fn test_mq_or() {
|
|||
assert!(list.media_queries.len() == 2, css.to_owned());
|
||||
let q0 = &list.media_queries[0];
|
||||
assert!(q0.qualifier == None, css.to_owned());
|
||||
assert!(q0.media_type == MediaQueryType::Concrete(MediaType::screen()), css.to_owned());
|
||||
assert!(
|
||||
q0.media_type == MediaQueryType::Concrete(MediaType::screen()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q0.expressions.len() == 0, css.to_owned());
|
||||
|
||||
let q1 = &list.media_queries[1];
|
||||
assert!(q1.qualifier == None, css.to_owned());
|
||||
assert!(q1.media_type == MediaQueryType::Concrete(MediaType::print()), css.to_owned());
|
||||
assert!(
|
||||
q1.media_type == MediaQueryType::Concrete(MediaType::print()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q1.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
}
|
||||
|
|
@ -194,7 +244,9 @@ fn test_mq_default_expressions() {
|
|||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||
assert!(q.expressions.len() == 1, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::from_px(100.)),
|
||||
ExpressionKind::Width(Range::Min(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(100.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
|
@ -206,7 +258,9 @@ fn test_mq_default_expressions() {
|
|||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||
assert!(q.expressions.len() == 1, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(43.)),
|
||||
ExpressionKind::Width(Range::Max(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(43.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
|
@ -218,10 +272,15 @@ fn test_mq_expressions() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::screen()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::screen()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 1, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::from_px(100.)),
|
||||
ExpressionKind::Width(Range::Min(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(100.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
|
@ -230,10 +289,15 @@ fn test_mq_expressions() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::print()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::print()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 1, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(43.)),
|
||||
ExpressionKind::Width(Range::Max(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(43.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
|
@ -242,10 +306,15 @@ fn test_mq_expressions() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::print()), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::print()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 1, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Eq(ref w)) => assert!(*w == specified::Length::from_px(43.)),
|
||||
ExpressionKind::Width(Range::Eq(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(43.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
|
@ -254,11 +323,15 @@ fn test_mq_expressions() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(
|
||||
MediaType(CustomIdent(Atom::from("fridge")))), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType(CustomIdent(Atom::from("fridge")))),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 1, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(52.)),
|
||||
ExpressionKind::Width(Range::Max(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(52.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
|
|
@ -275,37 +348,54 @@ fn test_to_css() {
|
|||
|
||||
#[test]
|
||||
fn test_mq_multiple_expressions() {
|
||||
test_media_rule("@media (min-width: 100px) and (max-width: 200px) { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||
assert!(q.expressions.len() == 2, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::from_px(100.)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
match *q.expressions[1].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(200.)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
test_media_rule(
|
||||
"@media (min-width: 100px) and (max-width: 200px) { }",
|
||||
|list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||
assert!(q.expressions.len() == 2, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Min(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(100.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
match *q.expressions[1].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Max(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(200.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
test_media_rule("@media not screen and (min-width: 100px) and (max-width: 200px) { }", |list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::Concrete(MediaType::screen()), css.to_owned());
|
||||
assert!(q.expressions.len() == 2, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Min(ref w)) => assert!(*w == specified::Length::from_px(100.)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
match *q.expressions[1].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Max(ref w)) => assert!(*w == specified::Length::from_px(200.)),
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
});
|
||||
test_media_rule(
|
||||
"@media not screen and (min-width: 100px) and (max-width: 200px) { }",
|
||||
|list, css| {
|
||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||
assert!(
|
||||
q.media_type == MediaQueryType::Concrete(MediaType::screen()),
|
||||
css.to_owned()
|
||||
);
|
||||
assert!(q.expressions.len() == 2, css.to_owned());
|
||||
match *q.expressions[0].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Min(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(100.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
match *q.expressions[1].kind_for_testing() {
|
||||
ExpressionKind::Width(Range::Max(ref w)) => {
|
||||
assert!(*w == specified::Length::from_px(200.))
|
||||
},
|
||||
_ => panic!("wrong expression type"),
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -333,7 +423,11 @@ fn test_mq_malformed_expressions() {
|
|||
|
||||
#[test]
|
||||
fn test_matching_simple() {
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
|
||||
let device = Device::new(
|
||||
MediaType::screen(),
|
||||
Size2D::new(200.0, 100.0),
|
||||
Scale::new(1.0),
|
||||
);
|
||||
|
||||
media_query_test(&device, "@media not all { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media not screen { a { color: red; } }", 0);
|
||||
|
|
@ -349,50 +443,136 @@ fn test_matching_simple() {
|
|||
|
||||
#[test]
|
||||
fn test_matching_width() {
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
|
||||
let device = Device::new(
|
||||
MediaType::screen(),
|
||||
Size2D::new(200.0, 100.0),
|
||||
Scale::new(1.0),
|
||||
);
|
||||
|
||||
media_query_test(&device, "@media { a { color: red; } }", 1);
|
||||
|
||||
media_query_test(&device, "@media (min-width: 50px) { a { color: red; } }", 1);
|
||||
media_query_test(&device, "@media (min-width: 150px) { a { color: red; } }", 1);
|
||||
media_query_test(&device, "@media (min-width: 300px) { a { color: red; } }", 0);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media (min-width: 150px) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media (min-width: 300px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
|
||||
media_query_test(&device, "@media screen and (min-width: 50px) { a { color: red; } }", 1);
|
||||
media_query_test(&device, "@media screen and (min-width: 150px) { a { color: red; } }", 1);
|
||||
media_query_test(&device, "@media screen and (min-width: 300px) { a { color: red; } }", 0);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media screen and (min-width: 50px) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media screen and (min-width: 150px) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media screen and (min-width: 300px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
|
||||
media_query_test(&device, "@media not screen and (min-width: 50px) { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media not screen and (min-width: 150px) { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media not screen and (min-width: 300px) { a { color: red; } }", 1);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media not screen and (min-width: 50px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media not screen and (min-width: 150px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media not screen and (min-width: 300px) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
|
||||
media_query_test(&device, "@media (max-width: 50px) { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media (max-width: 150px) { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media (max-width: 300px) { a { color: red; } }", 1);
|
||||
|
||||
media_query_test(&device, "@media screen and (min-width: 50px) and (max-width: 100px) { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media screen and (min-width: 250px) and (max-width: 300px) { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media screen and (min-width: 50px) and (max-width: 250px) { a { color: red; } }", 1);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media (max-width: 150px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media (max-width: 300px) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
|
||||
media_query_test(
|
||||
&device, "@media not screen and (min-width: 50px) and (max-width: 100px) { a { color: red; } }", 1);
|
||||
&device,
|
||||
"@media screen and (min-width: 50px) and (max-width: 100px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
media_query_test(
|
||||
&device, "@media not screen and (min-width: 250px) and (max-width: 300px) { a { color: red; } }", 1);
|
||||
&device,
|
||||
"@media screen and (min-width: 250px) and (max-width: 300px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
media_query_test(
|
||||
&device, "@media not screen and (min-width: 50px) and (max-width: 250px) { a { color: red; } }", 0);
|
||||
&device,
|
||||
"@media screen and (min-width: 50px) and (max-width: 250px) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
|
||||
media_query_test(
|
||||
&device, "@media not screen and (min-width: 3.1em) and (max-width: 6em) { a { color: red; } }", 1);
|
||||
&device,
|
||||
"@media not screen and (min-width: 50px) and (max-width: 100px) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
media_query_test(
|
||||
&device, "@media not screen and (min-width: 16em) and (max-width: 19.75em) { a { color: red; } }", 1);
|
||||
&device,
|
||||
"@media not screen and (min-width: 250px) and (max-width: 300px) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
media_query_test(
|
||||
&device, "@media not screen and (min-width: 3em) and (max-width: 250px) { a { color: red; } }", 0);
|
||||
&device,
|
||||
"@media not screen and (min-width: 50px) and (max-width: 250px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media not screen and (min-width: 3.1em) and (max-width: 6em) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media not screen and (min-width: 16em) and (max-width: 19.75em) { a { color: red; } }",
|
||||
1,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media not screen and (min-width: 3em) and (max-width: 250px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_matching_invalid() {
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
|
||||
let device = Device::new(
|
||||
MediaType::screen(),
|
||||
Size2D::new(200.0, 100.0),
|
||||
Scale::new(1.0),
|
||||
);
|
||||
|
||||
media_query_test(&device, "@media fridge { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media screen and (height: 100px) { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media not print and (width: 100) { a { color: red; } }", 0);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media screen and (height: 100px) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
media_query_test(
|
||||
&device,
|
||||
"@media not print and (width: 100) { a { color: red; } }",
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use parsing::parse;
|
|||
use servo_atoms::Atom;
|
||||
use style::parser::Parse;
|
||||
use style::properties::longhands::animation_name;
|
||||
use style::values::{KeyframesName, CustomIdent};
|
||||
use style::values::specified::AnimationIterationCount;
|
||||
use style::values::{CustomIdent, KeyframesName};
|
||||
use style_traits::ToCss;
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -3,9 +3,13 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use parsing::parse;
|
||||
use style::properties::longhands::{background_attachment, background_clip, background_color, background_image};
|
||||
use style::properties::longhands::{background_origin, background_position_x, background_position_y, background_repeat};
|
||||
use style::properties::longhands::background_size;
|
||||
use style::properties::longhands::{
|
||||
background_attachment, background_clip, background_color, background_image,
|
||||
};
|
||||
use style::properties::longhands::{
|
||||
background_origin, background_position_x, background_position_y, background_repeat,
|
||||
};
|
||||
use style::properties::shorthands::background;
|
||||
|
||||
#[test]
|
||||
|
|
@ -13,72 +17,179 @@ fn background_shorthand_should_parse_all_available_properties_when_specified() {
|
|||
let input = "url(\"http://servo/test.png\") top center / 200px 200px repeat-x fixed padding-box content-box red";
|
||||
let result = parse(background::parse_value, input).unwrap();
|
||||
|
||||
assert_eq!(result.background_image, parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
|
||||
assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "center"));
|
||||
assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "top"));
|
||||
assert_eq!(result.background_size, parse_longhand!(background_size, "200px 200px"));
|
||||
assert_eq!(result.background_repeat, parse_longhand!(background_repeat, "repeat-x"));
|
||||
assert_eq!(result.background_attachment, parse_longhand!(background_attachment, "fixed"));
|
||||
assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
|
||||
assert_eq!(result.background_clip, parse_longhand!(background_clip, "content-box"));
|
||||
assert_eq!(result.background_color, parse_longhand!(background_color, "red"));
|
||||
assert_eq!(
|
||||
result.background_image,
|
||||
parse_longhand!(background_image, "url(\"http://servo/test.png\")")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_position_x,
|
||||
parse_longhand!(background_position_x, "center")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_position_y,
|
||||
parse_longhand!(background_position_y, "top")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_size,
|
||||
parse_longhand!(background_size, "200px 200px")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_repeat,
|
||||
parse_longhand!(background_repeat, "repeat-x")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_attachment,
|
||||
parse_longhand!(background_attachment, "fixed")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_origin,
|
||||
parse_longhand!(background_origin, "padding-box")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_clip,
|
||||
parse_longhand!(background_clip, "content-box")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_color,
|
||||
parse_longhand!(background_color, "red")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn background_shorthand_should_parse_when_some_fields_set() {
|
||||
let result = parse(background::parse_value, "14px 40px repeat-y").unwrap();
|
||||
|
||||
assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "14px"));
|
||||
assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "40px"));
|
||||
assert_eq!(result.background_repeat, parse_longhand!(background_repeat, "repeat-y"));
|
||||
assert_eq!(
|
||||
result.background_position_x,
|
||||
parse_longhand!(background_position_x, "14px")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_position_y,
|
||||
parse_longhand!(background_position_y, "40px")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_repeat,
|
||||
parse_longhand!(background_repeat, "repeat-y")
|
||||
);
|
||||
|
||||
let result = parse(background::parse_value, "url(\"http://servo/test.png\") repeat blue").unwrap();
|
||||
let result = parse(
|
||||
background::parse_value,
|
||||
"url(\"http://servo/test.png\") repeat blue",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.background_image, parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
|
||||
assert_eq!(result.background_repeat, parse_longhand!(background_repeat, "repeat"));
|
||||
assert_eq!(result.background_color, parse_longhand!(background_color, "blue"));
|
||||
assert_eq!(
|
||||
result.background_image,
|
||||
parse_longhand!(background_image, "url(\"http://servo/test.png\")")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_repeat,
|
||||
parse_longhand!(background_repeat, "repeat")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_color,
|
||||
parse_longhand!(background_color, "blue")
|
||||
);
|
||||
|
||||
let result = parse(background::parse_value, "padding-box").unwrap();
|
||||
|
||||
assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
|
||||
assert_eq!(result.background_clip, parse_longhand!(background_clip, "padding-box"));
|
||||
assert_eq!(
|
||||
result.background_origin,
|
||||
parse_longhand!(background_origin, "padding-box")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_clip,
|
||||
parse_longhand!(background_clip, "padding-box")
|
||||
);
|
||||
|
||||
let result = parse(background::parse_value, "url(\"http://servo/test.png\")").unwrap();
|
||||
|
||||
assert_eq!(result.background_image, parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
|
||||
assert_eq!(
|
||||
result.background_image,
|
||||
parse_longhand!(background_image, "url(\"http://servo/test.png\")")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn background_shorthand_should_parse_comma_separated_declarations() {
|
||||
let input = "url(\"http://servo/test.png\") top left no-repeat, url(\"http://servo/test.png\") \
|
||||
let input =
|
||||
"url(\"http://servo/test.png\") top left no-repeat, url(\"http://servo/test.png\") \
|
||||
center / 100% 100% no-repeat, white";
|
||||
let result = parse(background::parse_value, input).unwrap();
|
||||
|
||||
assert_eq!(result.background_image, parse_longhand!(background_image, "url(\"http://servo/test.png\"), \
|
||||
url(\"http://servo/test.png\"), none"));
|
||||
assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "left, center, 0%"));
|
||||
assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "top, center, 0%"));
|
||||
assert_eq!(result.background_repeat, parse_longhand!(background_repeat, "no-repeat, no-repeat, repeat"));
|
||||
assert_eq!(result.background_clip, parse_longhand!(background_clip, "border-box, border-box, border-box"));
|
||||
assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box, padding-box, \
|
||||
padding-box"));
|
||||
assert_eq!(result.background_size, parse_longhand!(background_size, "auto auto, 100% 100%, auto auto"));
|
||||
assert_eq!(result.background_attachment, parse_longhand!(background_attachment, "scroll, scroll, scroll"));
|
||||
assert_eq!(result.background_color, parse_longhand!(background_color, "white"));
|
||||
assert_eq!(
|
||||
result.background_image,
|
||||
parse_longhand!(
|
||||
background_image,
|
||||
"url(\"http://servo/test.png\"), \
|
||||
url(\"http://servo/test.png\"), none"
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_position_x,
|
||||
parse_longhand!(background_position_x, "left, center, 0%")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_position_y,
|
||||
parse_longhand!(background_position_y, "top, center, 0%")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_repeat,
|
||||
parse_longhand!(background_repeat, "no-repeat, no-repeat, repeat")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_clip,
|
||||
parse_longhand!(background_clip, "border-box, border-box, border-box")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_origin,
|
||||
parse_longhand!(
|
||||
background_origin,
|
||||
"padding-box, padding-box, \
|
||||
padding-box"
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_size,
|
||||
parse_longhand!(background_size, "auto auto, 100% 100%, auto auto")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_attachment,
|
||||
parse_longhand!(background_attachment, "scroll, scroll, scroll")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_color,
|
||||
parse_longhand!(background_color, "white")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn background_shorthand_should_parse_position_and_size_correctly() {
|
||||
let result = parse(background::parse_value, "7px 4px").unwrap();
|
||||
|
||||
assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "7px"));
|
||||
assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "4px"));
|
||||
assert_eq!(
|
||||
result.background_position_x,
|
||||
parse_longhand!(background_position_x, "7px")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_position_y,
|
||||
parse_longhand!(background_position_y, "4px")
|
||||
);
|
||||
|
||||
let result = parse(background::parse_value, "7px 4px / 30px 20px").unwrap();
|
||||
|
||||
assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "7px"));
|
||||
assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "4px"));
|
||||
assert_eq!(result.background_size, parse_longhand!(background_size, "30px 20px"));
|
||||
assert_eq!(
|
||||
result.background_position_x,
|
||||
parse_longhand!(background_position_x, "7px")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_position_y,
|
||||
parse_longhand!(background_position_y, "4px")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_size,
|
||||
parse_longhand!(background_size, "30px 20px")
|
||||
);
|
||||
|
||||
assert!(parse(background::parse_value, "/ 30px 20px").is_err());
|
||||
|
||||
|
|
@ -89,16 +200,34 @@ fn background_shorthand_should_parse_position_and_size_correctly() {
|
|||
fn background_shorthand_should_parse_origin_and_clip_correctly() {
|
||||
let result = parse(background::parse_value, "padding-box content-box").unwrap();
|
||||
|
||||
assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
|
||||
assert_eq!(result.background_clip, parse_longhand!(background_clip, "content-box"));
|
||||
assert_eq!(
|
||||
result.background_origin,
|
||||
parse_longhand!(background_origin, "padding-box")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_clip,
|
||||
parse_longhand!(background_clip, "content-box")
|
||||
);
|
||||
|
||||
let result = parse(background::parse_value, "padding-box padding-box").unwrap();
|
||||
|
||||
assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
|
||||
assert_eq!(result.background_clip, parse_longhand!(background_clip, "padding-box"));
|
||||
assert_eq!(
|
||||
result.background_origin,
|
||||
parse_longhand!(background_origin, "padding-box")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_clip,
|
||||
parse_longhand!(background_clip, "padding-box")
|
||||
);
|
||||
|
||||
let result = parse(background::parse_value, "padding-box").unwrap();
|
||||
|
||||
assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
|
||||
assert_eq!(result.background_clip, parse_longhand!(background_clip, "padding-box"));
|
||||
assert_eq!(
|
||||
result.background_origin,
|
||||
parse_longhand!(background_origin, "padding-box")
|
||||
);
|
||||
assert_eq!(
|
||||
result.background_clip,
|
||||
parse_longhand!(background_clip, "padding-box")
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,40 +4,69 @@
|
|||
|
||||
use parsing::parse;
|
||||
use style::parser::Parse;
|
||||
use style::properties::MaybeBoxed;
|
||||
use style::properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
|
||||
use style::properties::longhands::{border_image_source, border_image_width};
|
||||
use style::properties::shorthands::border_image;
|
||||
use style::properties::MaybeBoxed;
|
||||
use style::values::specified::BorderRadius;
|
||||
use style_traits::ToCss;
|
||||
|
||||
macro_rules! assert_longhand {
|
||||
($parsed_shorthand: expr, $prop: ident, $value_string: expr) => {
|
||||
assert_eq!($parsed_shorthand.$prop, parse_longhand!($prop, $value_string).maybe_boxed())
|
||||
}
|
||||
assert_eq!(
|
||||
$parsed_shorthand.$prop,
|
||||
parse_longhand!($prop, $value_string).maybe_boxed()
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_initial {
|
||||
($parsed_shorthand: expr, $prop: ident) => {
|
||||
assert_eq!($parsed_shorthand.$prop, $prop::get_initial_specified_value().maybe_boxed())
|
||||
}
|
||||
assert_eq!(
|
||||
$parsed_shorthand.$prop,
|
||||
$prop::get_initial_specified_value().maybe_boxed()
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_border_radius_values {
|
||||
($input:expr; $tlw:expr, $trw:expr, $brw:expr, $blw:expr ;
|
||||
$tlh:expr, $trh:expr, $brh:expr, $blh:expr) => {
|
||||
let input = parse(BorderRadius::parse, $input)
|
||||
.expect(&format!("Failed parsing {} as border radius",
|
||||
$input));
|
||||
assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.width()), $tlw);
|
||||
assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.width()), $trw);
|
||||
assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.width()), $brw);
|
||||
assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.width()), $blw);
|
||||
assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.height()), $tlh);
|
||||
assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.height()), $trh);
|
||||
assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.height()), $brh);
|
||||
assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.height()), $blh);
|
||||
}
|
||||
.expect(&format!("Failed parsing {} as border radius", $input));
|
||||
assert_eq!(
|
||||
::style_traits::ToCss::to_css_string(&input.top_left.0.width()),
|
||||
$tlw
|
||||
);
|
||||
assert_eq!(
|
||||
::style_traits::ToCss::to_css_string(&input.top_right.0.width()),
|
||||
$trw
|
||||
);
|
||||
assert_eq!(
|
||||
::style_traits::ToCss::to_css_string(&input.bottom_right.0.width()),
|
||||
$brw
|
||||
);
|
||||
assert_eq!(
|
||||
::style_traits::ToCss::to_css_string(&input.bottom_left.0.width()),
|
||||
$blw
|
||||
);
|
||||
assert_eq!(
|
||||
::style_traits::ToCss::to_css_string(&input.top_left.0.height()),
|
||||
$tlh
|
||||
);
|
||||
assert_eq!(
|
||||
::style_traits::ToCss::to_css_string(&input.top_right.0.height()),
|
||||
$trh
|
||||
);
|
||||
assert_eq!(
|
||||
::style_traits::ToCss::to_css_string(&input.bottom_right.0.height()),
|
||||
$brh
|
||||
);
|
||||
assert_eq!(
|
||||
::style_traits::ToCss::to_css_string(&input.bottom_left.0.height()),
|
||||
$blh
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -16,18 +16,26 @@ fn test_clip() {
|
|||
assert_roundtrip_with_context!(clip::parse, "rect(auto, auto, auto, auto)");
|
||||
|
||||
// Non-standard syntax
|
||||
assert_roundtrip_with_context!(clip::parse,
|
||||
"rect(1px 2px 3px 4px)",
|
||||
"rect(1px, 2px, 3px, 4px)");
|
||||
assert_roundtrip_with_context!(clip::parse,
|
||||
"rect(auto 2px 3px auto)",
|
||||
"rect(auto, 2px, 3px, auto)");
|
||||
assert_roundtrip_with_context!(clip::parse,
|
||||
"rect(1px auto auto 4px)",
|
||||
"rect(1px, auto, auto, 4px)");
|
||||
assert_roundtrip_with_context!(clip::parse,
|
||||
"rect(auto auto auto auto)",
|
||||
"rect(auto, auto, auto, auto)");
|
||||
assert_roundtrip_with_context!(
|
||||
clip::parse,
|
||||
"rect(1px 2px 3px 4px)",
|
||||
"rect(1px, 2px, 3px, 4px)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
clip::parse,
|
||||
"rect(auto 2px 3px auto)",
|
||||
"rect(auto, 2px, 3px, auto)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
clip::parse,
|
||||
"rect(1px auto auto 4px)",
|
||||
"rect(1px, auto, auto, 4px)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
clip::parse,
|
||||
"rect(auto auto auto auto)",
|
||||
"rect(auto, auto, auto, auto)"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -85,7 +93,7 @@ fn test_parse_factor() {
|
|||
#[test]
|
||||
fn blur_radius_should_not_accept_negavite_values() {
|
||||
use style::properties::longhands::box_shadow;
|
||||
assert!(parse(box_shadow::parse, "1px 1px -1px").is_err());// for -ve values
|
||||
assert!(parse(box_shadow::parse, "1px 1px 0").is_ok());// for zero
|
||||
assert!(parse(box_shadow::parse, "1px 1px 1px").is_ok());// for +ve value
|
||||
assert!(parse(box_shadow::parse, "1px 1px -1px").is_err()); // for -ve values
|
||||
assert!(parse(box_shadow::parse, "1px 1px 0").is_ok()); // for zero
|
||||
assert!(parse(box_shadow::parse, "1px 1px 1px").is_ok()); // for +ve value
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,72 +33,122 @@ fn test_linear_gradient() {
|
|||
#[test]
|
||||
fn test_radial_gradient() {
|
||||
// Parsing with all values
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(circle closest-side at 20px 30px, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(ellipse closest-side at 20px 30px, red, green)",
|
||||
"radial-gradient(closest-side at 20px 30px, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side circle at 20px 30px, red, green)",
|
||||
"radial-gradient(circle closest-side at 20px 30px, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side ellipse at 20px 30px, red, green)",
|
||||
"radial-gradient(closest-side at 20px 30px, red, green)");
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(circle closest-side at 20px 30px, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(ellipse closest-side at 20px 30px, red, green)",
|
||||
"radial-gradient(closest-side at 20px 30px, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(closest-side circle at 20px 30px, red, green)",
|
||||
"radial-gradient(circle closest-side at 20px 30px, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(closest-side ellipse at 20px 30px, red, green)",
|
||||
"radial-gradient(closest-side at 20px 30px, red, green)"
|
||||
);
|
||||
|
||||
// Parsing with <shape-keyword> and <size> reversed
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-side circle at 20px 30px, red, green)",
|
||||
"radial-gradient(circle closest-side at 20px 30px, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(closest-corner ellipse at 20px 30px, red, green)",
|
||||
"radial-gradient(closest-corner at 20px 30px, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(30px circle, red, green)",
|
||||
"radial-gradient(30px at center center, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(30px 40px ellipse, red, green)",
|
||||
"radial-gradient(30px 40px at center center, red, green)");
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(closest-side circle at 20px 30px, red, green)",
|
||||
"radial-gradient(circle closest-side at 20px 30px, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(closest-corner ellipse at 20px 30px, red, green)",
|
||||
"radial-gradient(closest-corner at 20px 30px, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(30px circle, red, green)",
|
||||
"radial-gradient(30px at center center, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(30px 40px ellipse, red, green)",
|
||||
"radial-gradient(30px 40px at center center, red, green)"
|
||||
);
|
||||
|
||||
// Parsing without <size>
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(circle, red, green)",
|
||||
"radial-gradient(circle at center center, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(ellipse, red, green)",
|
||||
"radial-gradient(at center center, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(circle at 20px 30px, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(ellipse at 20px 30px, red, green)",
|
||||
"radial-gradient(at 20px 30px, red, green)");
|
||||
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(circle, red, green)",
|
||||
"radial-gradient(circle at center center, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(ellipse, red, green)",
|
||||
"radial-gradient(at center center, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(circle at 20px 30px, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(ellipse at 20px 30px, red, green)",
|
||||
"radial-gradient(at 20px 30px, red, green)"
|
||||
);
|
||||
|
||||
// Parsing without <shape-keyword>
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(20px at 20px 30px, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(20px 30px at left center, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(closest-side at center, red, green)",
|
||||
"radial-gradient(closest-side at center center, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(20px, red, green)",
|
||||
"radial-gradient(20px at center center, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(20px 30px, red, green)",
|
||||
"radial-gradient(20px 30px at center center, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(closest-side, red, green)",
|
||||
"radial-gradient(closest-side at center center, red, green)");
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(20px at 20px 30px, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(20px 30px at left center, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(closest-side at center, red, green)",
|
||||
"radial-gradient(closest-side at center center, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(20px, red, green)",
|
||||
"radial-gradient(20px at center center, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(20px 30px, red, green)",
|
||||
"radial-gradient(20px 30px at center center, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(closest-side, red, green)",
|
||||
"radial-gradient(closest-side at center center, red, green)"
|
||||
);
|
||||
|
||||
// Parsing without <shape-keyword> and <size>
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(at center, red, green)",
|
||||
"radial-gradient(at center center, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(at center bottom, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(at 40px 50px, red, green)");
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(at center, red, green)",
|
||||
"radial-gradient(at center center, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(at center bottom, red, green)"
|
||||
);
|
||||
assert_roundtrip_with_context!(Image::parse, "radial-gradient(at 40px 50px, red, green)");
|
||||
|
||||
// Parsing with just color stops
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"radial-gradient(red, green)",
|
||||
"radial-gradient(at center center, red, green)");
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"radial-gradient(red, green)",
|
||||
"radial-gradient(at center center, red, green)"
|
||||
);
|
||||
|
||||
// Parsing repeating radial gradient
|
||||
assert_roundtrip_with_context!(Image::parse,
|
||||
"repeating-radial-gradient(red, green)",
|
||||
"repeating-radial-gradient(at center center, red, green)");
|
||||
assert_roundtrip_with_context!(
|
||||
Image::parse,
|
||||
"repeating-radial-gradient(red, green)",
|
||||
"repeating-radial-gradient(at center center, red, green)"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,22 +8,24 @@ use style::values::generics::text::Spacing;
|
|||
#[test]
|
||||
fn negative_letter_spacing_should_parse_properly() {
|
||||
use style::properties::longhands::letter_spacing;
|
||||
use style::values::specified::length::{Length, NoCalcLength, FontRelativeLength};
|
||||
use style::values::specified::length::{FontRelativeLength, Length, NoCalcLength};
|
||||
|
||||
let negative_value = parse_longhand!(letter_spacing, "-0.5em");
|
||||
let expected = Spacing::Value(Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(-0.5))));
|
||||
let expected = Spacing::Value(Length::NoCalc(NoCalcLength::FontRelative(
|
||||
FontRelativeLength::Em(-0.5),
|
||||
)));
|
||||
assert_eq!(negative_value, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_word_spacing_should_parse_properly() {
|
||||
use style::properties::longhands::word_spacing;
|
||||
use style::values::specified::length::{NoCalcLength, LengthPercentage, FontRelativeLength};
|
||||
use style::values::specified::length::{FontRelativeLength, LengthPercentage, NoCalcLength};
|
||||
|
||||
let negative_value = parse_longhand!(word_spacing, "-0.5em");
|
||||
let expected = Spacing::Value(LengthPercentage::Length(
|
||||
NoCalcLength::FontRelative(FontRelativeLength::Em(-0.5))
|
||||
));
|
||||
let expected = Spacing::Value(LengthPercentage::Length(NoCalcLength::FontRelative(
|
||||
FontRelativeLength::Em(-0.5),
|
||||
)));
|
||||
assert_eq!(negative_value, expected);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,16 +8,20 @@ use cssparser::{Parser, ParserInput};
|
|||
use style::context::QuirksMode;
|
||||
use style::parser::ParserContext;
|
||||
use style::stylesheets::{CssRuleType, Origin};
|
||||
use style_traits::{ParsingMode, ParseError};
|
||||
use style_traits::{ParseError, ParsingMode};
|
||||
|
||||
fn parse<T, F>(f: F, s: &'static str) -> Result<T, ParseError<'static>>
|
||||
where F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>> {
|
||||
where
|
||||
F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>>,
|
||||
{
|
||||
let mut input = ParserInput::new(s);
|
||||
parse_input(f, &mut input)
|
||||
}
|
||||
|
||||
fn parse_input<'i: 't, 't, T, F>(f: F, input: &'t mut ParserInput<'i>) -> Result<T, ParseError<'i>>
|
||||
where F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>> {
|
||||
where
|
||||
F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
|
||||
{
|
||||
let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap();
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
|
|
@ -33,14 +37,24 @@ where F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>> {
|
|||
}
|
||||
|
||||
fn parse_entirely<T, F>(f: F, s: &'static str) -> Result<T, ParseError<'static>>
|
||||
where F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>> {
|
||||
where
|
||||
F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>>,
|
||||
{
|
||||
let mut input = ParserInput::new(s);
|
||||
parse_entirely_input(f, &mut input)
|
||||
}
|
||||
|
||||
fn parse_entirely_input<'i: 't, 't, T, F>(f: F, input: &'t mut ParserInput<'i>) -> Result<T, ParseError<'i>>
|
||||
where F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>> {
|
||||
parse_input(|context, parser| parser.parse_entirely(|p| f(context, p)), input)
|
||||
fn parse_entirely_input<'i: 't, 't, T, F>(
|
||||
f: F,
|
||||
input: &'t mut ParserInput<'i>,
|
||||
) -> Result<T, ParseError<'i>>
|
||||
where
|
||||
F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
|
||||
{
|
||||
parse_input(
|
||||
|context, parser| parser.parse_entirely(|p| f(context, p)),
|
||||
input,
|
||||
)
|
||||
}
|
||||
|
||||
// This is a macro so that the file/line information
|
||||
|
|
@ -51,24 +65,31 @@ macro_rules! assert_roundtrip_with_context {
|
|||
};
|
||||
($fun:expr, $input:expr, $output:expr) => {{
|
||||
let mut input = ::cssparser::ParserInput::new($input);
|
||||
let serialized = super::parse_input(|context, i| {
|
||||
let parsed = $fun(context, i)
|
||||
.expect(&format!("Failed to parse {}", $input));
|
||||
let serialized = ToCss::to_css_string(&parsed);
|
||||
assert_eq!(serialized, $output);
|
||||
Ok(serialized)
|
||||
}, &mut input).unwrap();
|
||||
let serialized = super::parse_input(
|
||||
|context, i| {
|
||||
let parsed = $fun(context, i).expect(&format!("Failed to parse {}", $input));
|
||||
let serialized = ToCss::to_css_string(&parsed);
|
||||
assert_eq!(serialized, $output);
|
||||
Ok(serialized)
|
||||
},
|
||||
&mut input,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut input = ::cssparser::ParserInput::new(&serialized);
|
||||
let unwrapped = super::parse_input(|context, i| {
|
||||
let re_parsed = $fun(context, i)
|
||||
.expect(&format!("Failed to parse serialization {}", $input));
|
||||
let re_serialized = ToCss::to_css_string(&re_parsed);
|
||||
assert_eq!(serialized, re_serialized);
|
||||
Ok(())
|
||||
}, &mut input).unwrap();
|
||||
let unwrapped = super::parse_input(
|
||||
|context, i| {
|
||||
let re_parsed =
|
||||
$fun(context, i).expect(&format!("Failed to parse serialization {}", $input));
|
||||
let re_serialized = ToCss::to_css_string(&re_parsed);
|
||||
assert_eq!(serialized, re_serialized);
|
||||
Ok(())
|
||||
},
|
||||
&mut input,
|
||||
)
|
||||
.unwrap();
|
||||
unwrapped
|
||||
}}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! assert_roundtrip {
|
||||
|
|
@ -78,34 +99,37 @@ macro_rules! assert_roundtrip {
|
|||
($fun:expr, $input:expr, $output:expr) => {
|
||||
let mut input = ParserInput::new($input);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let parsed = $fun(&mut parser)
|
||||
.expect(&format!("Failed to parse {}", $input));
|
||||
let parsed = $fun(&mut parser).expect(&format!("Failed to parse {}", $input));
|
||||
let serialized = ToCss::to_css_string(&parsed);
|
||||
assert_eq!(serialized, $output);
|
||||
|
||||
let mut input = ParserInput::new(&serialized);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let re_parsed = $fun(&mut parser)
|
||||
.expect(&format!("Failed to parse serialization {}", $input));
|
||||
let re_parsed =
|
||||
$fun(&mut parser).expect(&format!("Failed to parse serialization {}", $input));
|
||||
let re_serialized = ToCss::to_css_string(&re_parsed);
|
||||
assert_eq!(serialized, re_serialized)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_parser_exhausted {
|
||||
($fun:expr, $string:expr, $should_exhausted:expr) => {{
|
||||
parse(|context, input| {
|
||||
let parsed = $fun(context, input);
|
||||
assert_eq!(parsed.is_ok(), true);
|
||||
assert_eq!(input.is_exhausted(), $should_exhausted);
|
||||
Ok(())
|
||||
}, $string).unwrap()
|
||||
}}
|
||||
parse(
|
||||
|context, input| {
|
||||
let parsed = $fun(context, input);
|
||||
assert_eq!(parsed.is_ok(), true);
|
||||
assert_eq!(input.is_exhausted(), $should_exhausted);
|
||||
Ok(())
|
||||
},
|
||||
$string,
|
||||
)
|
||||
.unwrap()
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! parse_longhand {
|
||||
($name:ident, $s:expr) => {
|
||||
parse($name::parse, $s).unwrap()
|
||||
parse($name::parse, $s).unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@
|
|||
use cssparser::{Parser, ParserInput, ToCss};
|
||||
use selectors::parser::SelectorList;
|
||||
use style::selector_parser::{SelectorImpl, SelectorParser};
|
||||
use style::stylesheets::{Origin, Namespaces};
|
||||
use style::stylesheets::{Namespaces, Origin};
|
||||
use style_traits::ParseError;
|
||||
|
||||
fn parse_selector<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SelectorList<SelectorImpl>, ParseError<'i>> {
|
||||
fn parse_selector<'i, 't>(
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<SelectorList<SelectorImpl>, ParseError<'i>> {
|
||||
let mut ns = Namespaces::default();
|
||||
ns.prefixes.insert("svg".into(), ns!(svg));
|
||||
let parser = SelectorParser {
|
||||
|
|
@ -24,7 +26,10 @@ fn test_selectors() {
|
|||
assert_roundtrip!(parse_selector, "div");
|
||||
assert_roundtrip!(parse_selector, "svg|circle");
|
||||
assert_roundtrip!(parse_selector, "p:before", "p::before");
|
||||
assert_roundtrip!(parse_selector, "[border=\"0\"]:-servo-nonzero-border ~ ::-servo-details-summary");
|
||||
assert_roundtrip!(
|
||||
parse_selector,
|
||||
"[border=\"0\"]:-servo-nonzero-border ~ ::-servo-details-summary"
|
||||
);
|
||||
assert_roundtrip!(parse_selector, "* > *");
|
||||
assert_roundtrip!(parse_selector, "*|* + *", "* + *");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ use style_traits::ToCss;
|
|||
fn test_supports_condition() {
|
||||
assert_roundtrip!(SupportsCondition::parse, "(margin: 1px)");
|
||||
assert_roundtrip!(SupportsCondition::parse, "not (--be: to be)");
|
||||
assert_roundtrip!(SupportsCondition::parse, "(color: blue) and future-extension(4)");
|
||||
assert_roundtrip!(
|
||||
SupportsCondition::parse,
|
||||
"(color: blue) and future-extension(4)"
|
||||
);
|
||||
assert_roundtrip!(SupportsCondition::parse, "future-\\1 extension(4)");
|
||||
assert_roundtrip!(SupportsCondition::parse, "((test))");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,35 @@ use style_traits::ToCss;
|
|||
|
||||
#[test]
|
||||
fn test_cubic_bezier() {
|
||||
assert_roundtrip_with_context!(transition_timing_function::parse, "cubic-bezier(0, 0, 0, 0)");
|
||||
assert_roundtrip_with_context!(transition_timing_function::parse, "cubic-bezier(0.25, 0, 0.5, 0)");
|
||||
assert_roundtrip_with_context!(transition_timing_function::parse, "cubic-bezier(1, 1, 1, 1)");
|
||||
assert_roundtrip_with_context!(
|
||||
transition_timing_function::parse,
|
||||
"cubic-bezier(0, 0, 0, 0)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
transition_timing_function::parse,
|
||||
"cubic-bezier(0.25, 0, 0.5, 0)"
|
||||
);
|
||||
assert_roundtrip_with_context!(
|
||||
transition_timing_function::parse,
|
||||
"cubic-bezier(1, 1, 1, 1)"
|
||||
);
|
||||
|
||||
// p1x and p2x values must be in range [0, 1]
|
||||
assert!(parse(transition_timing_function::parse, "cubic-bezier(-1, 0, 0, 0").is_err());
|
||||
assert!(parse(transition_timing_function::parse, "cubic-bezier(0, 0, -1, 0").is_err());
|
||||
assert!(parse(transition_timing_function::parse, "cubic-bezier(-1, 0, -1, 0").is_err());
|
||||
assert!(parse(
|
||||
transition_timing_function::parse,
|
||||
"cubic-bezier(-1, 0, 0, 0"
|
||||
)
|
||||
.is_err());
|
||||
assert!(parse(
|
||||
transition_timing_function::parse,
|
||||
"cubic-bezier(0, 0, -1, 0"
|
||||
)
|
||||
.is_err());
|
||||
assert!(parse(
|
||||
transition_timing_function::parse,
|
||||
"cubic-bezier(-1, 0, -1, 0"
|
||||
)
|
||||
.is_err());
|
||||
|
||||
assert!(parse(transition_timing_function::parse, "cubic-bezier(2, 0, 0, 0").is_err());
|
||||
assert!(parse(transition_timing_function::parse, "cubic-bezier(0, 0, 2, 0").is_err());
|
||||
|
|
@ -27,7 +48,11 @@ fn test_steps() {
|
|||
assert_roundtrip_with_context!(transition_timing_function::parse, "steps(1)");
|
||||
assert_roundtrip_with_context!(transition_timing_function::parse, "steps( 1)", "steps(1)");
|
||||
assert_roundtrip_with_context!(transition_timing_function::parse, "steps(1, start)");
|
||||
assert_roundtrip_with_context!(transition_timing_function::parse, "steps(2, end) ", "steps(2)");
|
||||
assert_roundtrip_with_context!(
|
||||
transition_timing_function::parse,
|
||||
"steps(2, end) ",
|
||||
"steps(2)"
|
||||
);
|
||||
|
||||
// Step interval value must be an integer greater than 0
|
||||
assert!(parse(transition_timing_function::parse, "steps(0)").is_err());
|
||||
|
|
|
|||
|
|
@ -6,14 +6,11 @@ use cssparser::{Parser, ParserInput};
|
|||
use style::context::QuirksMode;
|
||||
use style::parser::ParserContext;
|
||||
use style::stylesheets::{CssRuleType, Origin};
|
||||
use style_traits::{ParsingMode, ParseError};
|
||||
use style_traits::{ParseError, ParsingMode};
|
||||
|
||||
fn parse<T, F>(f: F, s: &'static str) -> Result<T, ParseError<'static>>
|
||||
where
|
||||
F: for<'t> Fn(
|
||||
&ParserContext,
|
||||
&mut Parser<'static, 't>,
|
||||
) -> Result<T, ParseError<'static>>
|
||||
F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>>,
|
||||
{
|
||||
let mut input = ParserInput::new(s);
|
||||
parse_input(f, &mut input)
|
||||
|
|
@ -42,24 +39,31 @@ macro_rules! assert_roundtrip_with_context {
|
|||
assert_roundtrip_with_context!($fun, $string, $string);
|
||||
};
|
||||
($fun:expr, $input:expr, $output:expr) => {{
|
||||
let serialized = parse(|context, i| {
|
||||
let parsed = $fun(context, i)
|
||||
.expect(&format!("Failed to parse {}", $input));
|
||||
let serialized = ToCss::to_css_string(&parsed);
|
||||
assert_eq!(serialized, $output);
|
||||
Ok(serialized)
|
||||
}, $input).unwrap();
|
||||
let serialized = parse(
|
||||
|context, i| {
|
||||
let parsed = $fun(context, i).expect(&format!("Failed to parse {}", $input));
|
||||
let serialized = ToCss::to_css_string(&parsed);
|
||||
assert_eq!(serialized, $output);
|
||||
Ok(serialized)
|
||||
},
|
||||
$input,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut input = ::cssparser::ParserInput::new(&serialized);
|
||||
let unwrapped = parse_input(|context, i| {
|
||||
let re_parsed = $fun(context, i)
|
||||
.expect(&format!("Failed to parse serialization {}", $input));
|
||||
let re_serialized = ToCss::to_css_string(&re_parsed);
|
||||
assert_eq!(serialized, re_serialized);
|
||||
Ok(())
|
||||
}, &mut input).unwrap();
|
||||
let unwrapped = parse_input(
|
||||
|context, i| {
|
||||
let re_parsed =
|
||||
$fun(context, i).expect(&format!("Failed to parse serialization {}", $input));
|
||||
let re_serialized = ToCss::to_css_string(&re_parsed);
|
||||
assert_eq!(serialized, re_serialized);
|
||||
Ok(())
|
||||
},
|
||||
&mut input,
|
||||
)
|
||||
.unwrap();
|
||||
unwrapped
|
||||
}}
|
||||
}};
|
||||
}
|
||||
|
||||
mod scaffolding;
|
||||
|
|
|
|||
|
|
@ -4,19 +4,30 @@
|
|||
|
||||
use serde_json::{self, Value};
|
||||
use std::env;
|
||||
use std::fs::{File, remove_file};
|
||||
use std::fs::{remove_file, File};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
#[test]
|
||||
fn properties_list_json() {
|
||||
let top = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("..").join("..").join("..");
|
||||
let json = top.join("target").join("doc").join("servo").join("css-properties.json");
|
||||
let top = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
|
||||
.join("..")
|
||||
.join("..")
|
||||
.join("..");
|
||||
let json = top
|
||||
.join("target")
|
||||
.join("doc")
|
||||
.join("servo")
|
||||
.join("css-properties.json");
|
||||
if json.exists() {
|
||||
remove_file(&json).unwrap()
|
||||
}
|
||||
let python = env::var("PYTHON").ok().unwrap_or_else(find_python);
|
||||
let script = top.join("components").join("style").join("properties").join("build.py");
|
||||
let script = top
|
||||
.join("components")
|
||||
.join("style")
|
||||
.join("properties")
|
||||
.join("build.py");
|
||||
let status = Command::new(python)
|
||||
.arg(&script)
|
||||
.arg("servo")
|
||||
|
|
@ -34,11 +45,19 @@ fn properties_list_json() {
|
|||
|
||||
#[cfg(windows)]
|
||||
fn find_python() -> String {
|
||||
if Command::new("python2.7.exe").arg("--version").output().is_ok() {
|
||||
if Command::new("python2.7.exe")
|
||||
.arg("--version")
|
||||
.output()
|
||||
.is_ok()
|
||||
{
|
||||
return "python2.7.exe".to_owned();
|
||||
}
|
||||
|
||||
if Command::new("python27.exe").arg("--version").output().is_ok() {
|
||||
if Command::new("python27.exe")
|
||||
.arg("--version")
|
||||
.output()
|
||||
.is_ok()
|
||||
{
|
||||
return "python27.exe".to_owned();
|
||||
}
|
||||
|
||||
|
|
@ -51,9 +70,16 @@ fn find_python() -> String {
|
|||
|
||||
#[cfg(not(windows))]
|
||||
fn find_python() -> String {
|
||||
if Command::new("python2.7").arg("--version").output().unwrap().status.success() {
|
||||
if Command::new("python2.7")
|
||||
.arg("--version")
|
||||
.output()
|
||||
.unwrap()
|
||||
.status
|
||||
.success()
|
||||
{
|
||||
"python2.7"
|
||||
} else {
|
||||
"python"
|
||||
}.to_owned()
|
||||
}
|
||||
.to_owned()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@
|
|||
|
||||
use properties::{parse, parse_input};
|
||||
use style::computed_values::display::T as Display;
|
||||
use style::properties::{PropertyDeclaration, Importance};
|
||||
use style::properties::declaration_block::PropertyDeclarationBlock;
|
||||
use style::properties::parse_property_declaration_list;
|
||||
use style::values::RGBA;
|
||||
use style::values::specified::{BorderStyle, BorderSideWidth, Color};
|
||||
use style::values::specified::{Length, LengthPercentage, LengthPercentageOrAuto};
|
||||
use style::values::specified::NoCalcLength;
|
||||
use style::properties::{Importance, PropertyDeclaration};
|
||||
use style::values::specified::url::SpecifiedUrl;
|
||||
use style::values::specified::NoCalcLength;
|
||||
use style::values::specified::{BorderSideWidth, BorderStyle, Color};
|
||||
use style::values::specified::{Length, LengthPercentage, LengthPercentageOrAuto};
|
||||
use style::values::RGBA;
|
||||
use style_traits::ToCss;
|
||||
use stylesheets::block_from;
|
||||
|
||||
|
|
@ -32,28 +32,34 @@ fn property_declaration_block_should_serialize_correctly() {
|
|||
use style::properties::longhands::overflow_x::SpecifiedValue as OverflowValue;
|
||||
|
||||
let declarations = vec![
|
||||
(PropertyDeclaration::Width(
|
||||
LengthPercentageOrAuto::Length(NoCalcLength::from_px(70f32))),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::MinHeight(
|
||||
LengthPercentage::Length(NoCalcLength::from_px(20f32))),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::Height(
|
||||
LengthPercentageOrAuto::Length(NoCalcLength::from_px(20f32))),
|
||||
Importance::Important),
|
||||
|
||||
(PropertyDeclaration::Display(Display::InlineBlock),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::OverflowX(
|
||||
OverflowValue::Auto),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::OverflowY(
|
||||
OverflowValue::Auto),
|
||||
Importance::Normal),
|
||||
(
|
||||
PropertyDeclaration::Width(LengthPercentageOrAuto::Length(NoCalcLength::from_px(
|
||||
70f32,
|
||||
))),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::MinHeight(LengthPercentage::Length(NoCalcLength::from_px(20f32))),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::Height(LengthPercentageOrAuto::Length(NoCalcLength::from_px(
|
||||
20f32,
|
||||
))),
|
||||
Importance::Important,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::Display(Display::InlineBlock),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::OverflowX(OverflowValue::Auto),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::OverflowY(OverflowValue::Auto),
|
||||
Importance::Normal,
|
||||
),
|
||||
];
|
||||
|
||||
let block = block_from(declarations);
|
||||
|
|
@ -147,62 +153,65 @@ mod shorthand_serialization {
|
|||
|
||||
#[test]
|
||||
fn different_longhands_should_serialize_to_long_form() {
|
||||
let mut properties = Vec::new();
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let solid = BorderStyle::Solid;
|
||||
let solid = BorderStyle::Solid;
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderTopStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftStyle(solid.clone()));
|
||||
|
||||
let px_30 = BorderSideWidth::Length(Length::from_px(30f32));
|
||||
let px_10 = BorderSideWidth::Length(Length::from_px(10f32));
|
||||
let px_30 = BorderSideWidth::Length(Length::from_px(30f32));
|
||||
let px_10 = BorderSideWidth::Length(Length::from_px(10f32));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone()));
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone()));
|
||||
|
||||
let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
|
||||
let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftColor(blue.clone()));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization,
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization,
|
||||
"border-style: solid; border-width: 30px 30px 30px 10px; border-color: rgb(0, 0, 255);");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_longhands_should_serialize_correctly() {
|
||||
let mut properties = Vec::new();
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let solid = BorderStyle::Solid;
|
||||
let solid = BorderStyle::Solid;
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderTopStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomStyle(solid.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftStyle(solid.clone()));
|
||||
|
||||
let px_30 = BorderSideWidth::Length(Length::from_px(30f32));
|
||||
let px_30 = BorderSideWidth::Length(Length::from_px(30f32));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone()));
|
||||
|
||||
let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
|
||||
let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomColor(blue.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftColor(blue.clone()));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization, "border-style: solid; border-width: 30px; border-color: rgb(0, 0, 255);");
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(
|
||||
serialization,
|
||||
"border-style: solid; border-width: 30px; border-color: rgb(0, 0, 255);"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -274,7 +283,10 @@ mod shorthand_serialization {
|
|||
let serialization = shorthand_properties_to_string(properties);
|
||||
|
||||
// TODO: Make the rgb test show border-color as blue red instead of below tuples
|
||||
assert_eq!(serialization, "border-color: rgb(0, 0, 255) rgb(255, 0, 0);");
|
||||
assert_eq!(
|
||||
serialization,
|
||||
"border-color: rgb(0, 0, 255) rgb(255, 0, 0);"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -297,41 +309,42 @@ mod shorthand_serialization {
|
|||
#[test]
|
||||
fn border_radius_should_serialize_correctly() {
|
||||
let mut properties = Vec::new();
|
||||
properties.push(PropertyDeclaration::BorderTopLeftRadius(Box::new(BorderCornerRadius::new(
|
||||
Percentage::new(0.01).into(), Percentage::new(0.05).into()
|
||||
))));
|
||||
properties.push(PropertyDeclaration::BorderTopRightRadius(Box::new(BorderCornerRadius::new(
|
||||
Percentage::new(0.02).into(), Percentage::new(0.06).into()
|
||||
))));
|
||||
properties.push(PropertyDeclaration::BorderBottomRightRadius(Box::new(BorderCornerRadius::new(
|
||||
Percentage::new(0.03).into(), Percentage::new(0.07).into()
|
||||
))));
|
||||
properties.push(PropertyDeclaration::BorderBottomLeftRadius(Box::new(BorderCornerRadius::new(
|
||||
Percentage::new(0.04).into(), Percentage::new(0.08).into()
|
||||
))));
|
||||
properties.push(PropertyDeclaration::BorderTopLeftRadius(Box::new(
|
||||
BorderCornerRadius::new(Percentage::new(0.01).into(), Percentage::new(0.05).into()),
|
||||
)));
|
||||
properties.push(PropertyDeclaration::BorderTopRightRadius(Box::new(
|
||||
BorderCornerRadius::new(Percentage::new(0.02).into(), Percentage::new(0.06).into()),
|
||||
)));
|
||||
properties.push(PropertyDeclaration::BorderBottomRightRadius(Box::new(
|
||||
BorderCornerRadius::new(Percentage::new(0.03).into(), Percentage::new(0.07).into()),
|
||||
)));
|
||||
properties.push(PropertyDeclaration::BorderBottomLeftRadius(Box::new(
|
||||
BorderCornerRadius::new(Percentage::new(0.04).into(), Percentage::new(0.08).into()),
|
||||
)));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization, "border-radius: 1% 2% 3% 4% / 5% 6% 7% 8%;");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mod border_shorthands {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn border_top_and_color() {
|
||||
let mut properties = Vec::new();
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(BorderSideWidth::Length(Length::from_px(1.))));
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(
|
||||
BorderSideWidth::Length(Length::from_px(1.)),
|
||||
));
|
||||
properties.push(PropertyDeclaration::BorderTopStyle(BorderStyle::Solid));
|
||||
let c = Color::Numeric {
|
||||
parsed: RGBA::new(255, 0, 0, 255),
|
||||
authored: Some("green".to_string().into_boxed_str())
|
||||
authored: Some("green".to_string().into_boxed_str()),
|
||||
};
|
||||
properties.push(PropertyDeclaration::BorderTopColor(c));
|
||||
let c = Color::Numeric {
|
||||
parsed: RGBA::new(0, 255, 0, 255),
|
||||
authored: Some("red".to_string().into_boxed_str())
|
||||
authored: Some("red".to_string().into_boxed_str()),
|
||||
};
|
||||
properties.push(PropertyDeclaration::BorderTopColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomColor(c.clone()));
|
||||
|
|
@ -339,31 +352,39 @@ mod shorthand_serialization {
|
|||
properties.push(PropertyDeclaration::BorderRightColor(c.clone()));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization, "border-top: 1px solid red; border-color: red;");
|
||||
assert_eq!(
|
||||
serialization,
|
||||
"border-top: 1px solid red; border-color: red;"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn border_color_and_top() {
|
||||
let mut properties = Vec::new();
|
||||
let c = Color::Numeric {
|
||||
let c = Color::Numeric {
|
||||
parsed: RGBA::new(0, 255, 0, 255),
|
||||
authored: Some("red".to_string().into_boxed_str())
|
||||
authored: Some("red".to_string().into_boxed_str()),
|
||||
};
|
||||
properties.push(PropertyDeclaration::BorderTopColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightColor(c.clone()));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(BorderSideWidth::Length(Length::from_px(1.))));
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(
|
||||
BorderSideWidth::Length(Length::from_px(1.)),
|
||||
));
|
||||
properties.push(PropertyDeclaration::BorderTopStyle(BorderStyle::Solid));
|
||||
let c = Color::Numeric {
|
||||
parsed: RGBA::new(255, 0, 0, 255),
|
||||
authored: Some("green".to_string().into_boxed_str())
|
||||
authored: Some("green".to_string().into_boxed_str()),
|
||||
};
|
||||
properties.push(PropertyDeclaration::BorderTopColor(c));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization, "border-color: green red red; border-top: 1px solid green;");
|
||||
assert_eq!(
|
||||
serialization,
|
||||
"border-color: green red red; border-top: 1px solid green;"
|
||||
);
|
||||
}
|
||||
|
||||
// we can use border-top as a base to test out the different combinations
|
||||
|
|
@ -386,9 +407,11 @@ mod shorthand_serialization {
|
|||
}
|
||||
|
||||
fn get_border_property_values() -> (BorderSideWidth, BorderStyle, Color) {
|
||||
(BorderSideWidth::Length(Length::from_px(4f32)),
|
||||
BorderStyle::Solid,
|
||||
Color::currentcolor())
|
||||
(
|
||||
BorderSideWidth::Length(Length::from_px(4f32)),
|
||||
BorderStyle::Solid,
|
||||
Color::currentcolor(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -451,7 +474,8 @@ mod shorthand_serialization {
|
|||
border-left: 4px solid; \
|
||||
border-image: none;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
|
|
@ -475,7 +499,8 @@ mod shorthand_serialization {
|
|||
background-origin: border-box; \
|
||||
background-clip: padding-box;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
|
|
@ -499,7 +524,8 @@ mod shorthand_serialization {
|
|||
background-origin: padding-box; \
|
||||
background-clip: padding-box;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
|
|
@ -523,7 +549,8 @@ mod shorthand_serialization {
|
|||
background-origin: border-box, padding-box; \
|
||||
background-clip: padding-box, padding-box;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
|
|
@ -554,7 +581,8 @@ mod shorthand_serialization {
|
|||
background-origin: border-box; \
|
||||
background-clip: padding-box, padding-box;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
|
|
@ -568,7 +596,8 @@ mod shorthand_serialization {
|
|||
let block_text = "\
|
||||
background-position-x: 30px;\
|
||||
background-position-y: bottom 20px;";
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let serialization = block.to_css_string();
|
||||
assert_eq!(serialization, "background-position: left 30px bottom 20px;");
|
||||
|
||||
|
|
@ -577,7 +606,8 @@ mod shorthand_serialization {
|
|||
let block_text = "\
|
||||
background-position-x: center;\
|
||||
background-position-y: 20px;";
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let serialization = block.to_css_string();
|
||||
assert_eq!(serialization, "background-position: center 20px;");
|
||||
}
|
||||
|
|
@ -609,11 +639,15 @@ mod shorthand_serialization {
|
|||
animation-iteration-count: infinite;\
|
||||
animation-play-state: paused;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
assert_eq!(serialization, "animation: 1s ease-in 0s infinite normal forwards paused bounce;")
|
||||
assert_eq!(
|
||||
serialization,
|
||||
"animation: 1s ease-in 0s infinite normal forwards paused bounce;"
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -628,13 +662,16 @@ mod shorthand_serialization {
|
|||
animation-iteration-count: infinite, 2;\
|
||||
animation-play-state: paused, running;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
assert_eq!(serialization,
|
||||
"animation: 1s ease-in 0s infinite normal forwards paused bounce, \
|
||||
0.2s linear 1s 2 reverse backwards running roll;");
|
||||
assert_eq!(
|
||||
serialization,
|
||||
"animation: 1s ease-in 0s infinite normal forwards paused bounce, \
|
||||
0.2s linear 1s 2 reverse backwards running roll;"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -654,7 +691,8 @@ mod shorthand_serialization {
|
|||
animation-iteration-count: infinite, 2; \
|
||||
animation-play-state: paused, running;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
|
|
@ -671,7 +709,8 @@ mod shorthand_serialization {
|
|||
animation-iteration-count: infinite, 2; \
|
||||
animation-play-state: paused, running;";
|
||||
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
|
||||
|
|
@ -684,7 +723,8 @@ mod shorthand_serialization {
|
|||
#[test]
|
||||
fn css_wide_keywords_should_be_parsed() {
|
||||
let block_text = "--a:inherit;";
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
assert_eq!(serialization, "--a: inherit;");
|
||||
|
|
@ -693,7 +733,8 @@ mod shorthand_serialization {
|
|||
#[test]
|
||||
fn non_keyword_custom_property_should_be_unparsed() {
|
||||
let block_text = "--main-color: #06c;";
|
||||
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
let block =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
|
||||
|
||||
let serialization = block.to_css_string();
|
||||
assert_eq!(serialization, block_text);
|
||||
|
|
@ -723,7 +764,8 @@ mod shorthand_serialization {
|
|||
let shadow_decl = BoxShadowList(vec![shadow_val]);
|
||||
properties.push(PropertyDeclaration::BoxShadow(shadow_decl));
|
||||
let shadow_css = "box-shadow: 1px 2px 3px 4px;";
|
||||
let shadow = parse(|c, i| Ok(parse_property_declaration_list(c, i)), shadow_css).unwrap();
|
||||
let shadow =
|
||||
parse(|c, i| Ok(parse_property_declaration_list(c, i)), shadow_css).unwrap();
|
||||
|
||||
assert_eq!(shadow.to_css_string(), shadow_css);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,22 +7,25 @@ use rayon;
|
|||
use servo_arc::Arc;
|
||||
use servo_url::ServoUrl;
|
||||
use style::context::QuirksMode;
|
||||
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
use style::error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use style::media_queries::MediaList;
|
||||
use style::properties::{longhands, Importance, PropertyDeclaration, PropertyDeclarationBlock};
|
||||
use style::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
|
||||
use style::shared_lock::SharedRwLock;
|
||||
use style::stylesheets::{Origin, Stylesheet, CssRule};
|
||||
use style::stylesheets::{CssRule, Origin, Stylesheet};
|
||||
use style::thread_state::{self, ThreadState};
|
||||
use test::{self, Bencher};
|
||||
|
||||
struct ErrorringErrorReporter;
|
||||
impl ParseErrorReporter for ErrorringErrorReporter {
|
||||
fn report_error(&self,
|
||||
url: &ServoUrl,
|
||||
location: SourceLocation,
|
||||
error: ContextualParseError) {
|
||||
panic!("CSS error: {}\t\n{}:{} {}", url.as_str(), location.line, location.column, error);
|
||||
fn report_error(&self, url: &ServoUrl, location: SourceLocation, error: ContextualParseError) {
|
||||
panic!(
|
||||
"CSS error: {}\t\n{}:{} {}",
|
||||
url.as_str(),
|
||||
location.line,
|
||||
location.column,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -38,9 +41,10 @@ impl<'a> Drop for AutoGCRuleTree<'a> {
|
|||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.0.gc();
|
||||
assert!(::std::thread::panicking() ||
|
||||
!self.0.root().has_children_for_testing(),
|
||||
"No rule nodes other than the root shall remain!");
|
||||
assert!(
|
||||
::std::thread::panicking() || !self.0.root().has_children_for_testing(),
|
||||
"No rule nodes other than the root shall remain!"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,41 +53,51 @@ fn parse_rules(css: &str) -> Vec<(StyleSource, CascadeLevel)> {
|
|||
let lock = SharedRwLock::new();
|
||||
let media = Arc::new(lock.wrap(MediaList::empty()));
|
||||
|
||||
let s = Stylesheet::from_str(css,
|
||||
ServoUrl::parse("http://localhost").unwrap(),
|
||||
Origin::Author,
|
||||
media,
|
||||
lock,
|
||||
None,
|
||||
Some(&ErrorringErrorReporter),
|
||||
QuirksMode::NoQuirks,
|
||||
0);
|
||||
let s = Stylesheet::from_str(
|
||||
css,
|
||||
ServoUrl::parse("http://localhost").unwrap(),
|
||||
Origin::Author,
|
||||
media,
|
||||
lock,
|
||||
None,
|
||||
Some(&ErrorringErrorReporter),
|
||||
QuirksMode::NoQuirks,
|
||||
0,
|
||||
);
|
||||
let guard = s.shared_lock.read();
|
||||
let rules = s.contents.rules.read_with(&guard);
|
||||
rules.0.iter().filter_map(|rule| {
|
||||
match *rule {
|
||||
rules
|
||||
.0
|
||||
.iter()
|
||||
.filter_map(|rule| match *rule {
|
||||
CssRule::Style(ref style_rule) => Some((
|
||||
StyleSource::from_rule(style_rule.clone()),
|
||||
CascadeLevel::UserNormal,
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
}).collect()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn test_insertion(rule_tree: &RuleTree, rules: Vec<(StyleSource, CascadeLevel)>) -> StrongRuleNode {
|
||||
rule_tree.insert_ordered_rules(rules.into_iter())
|
||||
}
|
||||
|
||||
fn test_insertion_style_attribute(rule_tree: &RuleTree, rules: &[(StyleSource, CascadeLevel)],
|
||||
shared_lock: &SharedRwLock)
|
||||
-> StrongRuleNode {
|
||||
fn test_insertion_style_attribute(
|
||||
rule_tree: &RuleTree,
|
||||
rules: &[(StyleSource, CascadeLevel)],
|
||||
shared_lock: &SharedRwLock,
|
||||
) -> StrongRuleNode {
|
||||
let mut rules = rules.to_vec();
|
||||
rules.push((StyleSource::from_declarations(Arc::new(shared_lock.wrap(PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::Display(
|
||||
longhands::display::SpecifiedValue::Block),
|
||||
Importance::Normal
|
||||
)))), CascadeLevel::UserNormal));
|
||||
rules.push((
|
||||
StyleSource::from_declarations(Arc::new(shared_lock.wrap(
|
||||
PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::Display(longhands::display::SpecifiedValue::Block),
|
||||
Importance::Normal,
|
||||
),
|
||||
))),
|
||||
CascadeLevel::UserNormal,
|
||||
));
|
||||
test_insertion(rule_tree, rules)
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +109,8 @@ fn bench_insertion_basic(b: &mut Bencher) {
|
|||
let rules_matched = parse_rules(
|
||||
".foo { width: 200px; } \
|
||||
.bar { height: 500px; } \
|
||||
.baz { display: block; }");
|
||||
.baz { display: block; }",
|
||||
);
|
||||
|
||||
b.iter(|| {
|
||||
let _gc = AutoGCRuleTree::new(&r);
|
||||
|
|
@ -114,7 +129,8 @@ fn bench_insertion_basic_per_element(b: &mut Bencher) {
|
|||
let rules_matched = parse_rules(
|
||||
".foo { width: 200px; } \
|
||||
.bar { height: 500px; } \
|
||||
.baz { display: block; }");
|
||||
.baz { display: block; }",
|
||||
);
|
||||
|
||||
b.iter(|| {
|
||||
let _gc = AutoGCRuleTree::new(&r);
|
||||
|
|
@ -134,14 +150,19 @@ fn bench_expensive_insertion(b: &mut Bencher) {
|
|||
let rules_matched = parse_rules(
|
||||
".foo { width: 200px; } \
|
||||
.bar { height: 500px; } \
|
||||
.baz { display: block; }");
|
||||
.baz { display: block; }",
|
||||
);
|
||||
|
||||
let shared_lock = SharedRwLock::new();
|
||||
b.iter(|| {
|
||||
let _gc = AutoGCRuleTree::new(&r);
|
||||
|
||||
for _ in 0..(4000 + 400) {
|
||||
test::black_box(test_insertion_style_attribute(&r, &rules_matched, &shared_lock));
|
||||
test::black_box(test_insertion_style_attribute(
|
||||
&r,
|
||||
&rules_matched,
|
||||
&shared_lock,
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -154,7 +175,8 @@ fn bench_insertion_basic_parallel(b: &mut Bencher) {
|
|||
let rules_matched = parse_rules(
|
||||
".foo { width: 200px; } \
|
||||
.bar { height: 500px; } \
|
||||
.baz { display: block; }");
|
||||
.baz { display: block; }",
|
||||
);
|
||||
|
||||
b.iter(|| {
|
||||
let _gc = AutoGCRuleTree::new(&r);
|
||||
|
|
@ -163,13 +185,11 @@ fn bench_insertion_basic_parallel(b: &mut Bencher) {
|
|||
for _ in 0..4 {
|
||||
s.spawn(|s| {
|
||||
for _ in 0..1000 {
|
||||
test::black_box(test_insertion(&r,
|
||||
rules_matched.clone()));
|
||||
test::black_box(test_insertion(&r, rules_matched.clone()));
|
||||
}
|
||||
s.spawn(|_| {
|
||||
for _ in 0..100 {
|
||||
test::black_box(test_insertion(&r,
|
||||
rules_matched.clone()));
|
||||
test::black_box(test_insertion(&r, rules_matched.clone()));
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -186,7 +206,8 @@ fn bench_expensive_insertion_parallel(b: &mut Bencher) {
|
|||
let rules_matched = parse_rules(
|
||||
".foo { width: 200px; } \
|
||||
.bar { height: 500px; } \
|
||||
.baz { display: block; }");
|
||||
.baz { display: block; }",
|
||||
);
|
||||
|
||||
let shared_lock = SharedRwLock::new();
|
||||
b.iter(|| {
|
||||
|
|
@ -196,15 +217,19 @@ fn bench_expensive_insertion_parallel(b: &mut Bencher) {
|
|||
for _ in 0..4 {
|
||||
s.spawn(|s| {
|
||||
for _ in 0..1000 {
|
||||
test::black_box(test_insertion_style_attribute(&r,
|
||||
&rules_matched,
|
||||
&shared_lock));
|
||||
test::black_box(test_insertion_style_attribute(
|
||||
&r,
|
||||
&rules_matched,
|
||||
&shared_lock,
|
||||
));
|
||||
}
|
||||
s.spawn(|_| {
|
||||
for _ in 0..100 {
|
||||
test::black_box(test_insertion_style_attribute(&r,
|
||||
&rules_matched,
|
||||
&shared_lock));
|
||||
test::black_box(test_insertion_style_attribute(
|
||||
&r,
|
||||
&rules_matched,
|
||||
&shared_lock,
|
||||
));
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,16 +8,44 @@ use style::properties;
|
|||
|
||||
size_of_test!(test_size_of_dependency, Dependency, 16);
|
||||
|
||||
size_of_test!(test_size_of_property_declaration, properties::PropertyDeclaration, 32);
|
||||
size_of_test!(
|
||||
test_size_of_property_declaration,
|
||||
properties::PropertyDeclaration,
|
||||
32
|
||||
);
|
||||
|
||||
// This is huge, but we allocate it on the stack and then never move it,
|
||||
// we only pass `&mut SourcePropertyDeclaration` references around.
|
||||
size_of_test!(test_size_of_parsed_declaration, properties::SourcePropertyDeclaration, 568);
|
||||
size_of_test!(
|
||||
test_size_of_parsed_declaration,
|
||||
properties::SourcePropertyDeclaration,
|
||||
568
|
||||
);
|
||||
|
||||
size_of_test!(test_size_of_selector_parse_error_kind, SelectorParseErrorKind, 40);
|
||||
size_of_test!(test_size_of_style_parse_error_kind, ::style_traits::StyleParseErrorKind, 56);
|
||||
size_of_test!(test_size_of_value_parse_error_kind, ::style_traits::ValueParseErrorKind, 40);
|
||||
size_of_test!(
|
||||
test_size_of_selector_parse_error_kind,
|
||||
SelectorParseErrorKind,
|
||||
40
|
||||
);
|
||||
size_of_test!(
|
||||
test_size_of_style_parse_error_kind,
|
||||
::style_traits::StyleParseErrorKind,
|
||||
56
|
||||
);
|
||||
size_of_test!(
|
||||
test_size_of_value_parse_error_kind,
|
||||
::style_traits::ValueParseErrorKind,
|
||||
40
|
||||
);
|
||||
|
||||
size_of_test!(test_size_of_selector_parse_error, SelectorParseError, 56);
|
||||
size_of_test!(test_size_of_style_traits_parse_error, ::style_traits::ParseError, 72);
|
||||
size_of_test!(test_size_of_value_parse_error, ::style_traits::ValueParseError, 56);
|
||||
size_of_test!(
|
||||
test_size_of_style_traits_parse_error,
|
||||
::style_traits::ParseError,
|
||||
72
|
||||
);
|
||||
size_of_test!(
|
||||
test_size_of_value_parse_error,
|
||||
::style_traits::ValueParseError,
|
||||
56
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,12 +2,16 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use style::str::{split_html_space_chars, str_join, starts_with_ignore_ascii_case};
|
||||
use style::str::{split_html_space_chars, starts_with_ignore_ascii_case, str_join};
|
||||
|
||||
#[test]
|
||||
pub fn split_html_space_chars_whitespace() {
|
||||
assert!(split_html_space_chars("").collect::<Vec<_>>().is_empty());
|
||||
assert!(split_html_space_chars("\u{0020}\u{0009}\u{000a}\u{000c}\u{000d}").collect::<Vec<_>>().is_empty());
|
||||
assert!(
|
||||
split_html_space_chars("\u{0020}\u{0009}\u{000a}\u{000c}\u{000d}")
|
||||
.collect::<Vec<_>>()
|
||||
.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -3,35 +3,39 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::{self, SourceLocation};
|
||||
use html5ever::{Namespace as NsAtom};
|
||||
use html5ever::Namespace as NsAtom;
|
||||
use parking_lot::RwLock;
|
||||
use selectors::attr::*;
|
||||
use selectors::parser::*;
|
||||
use servo_arc::Arc;
|
||||
use servo_atoms::Atom;
|
||||
use servo_config::prefs::{PREFS, PrefValue};
|
||||
use servo_config::prefs::{PrefValue, PREFS};
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::RefCell;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use style::context::QuirksMode;
|
||||
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
use style::error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use style::media_queries::MediaList;
|
||||
use style::properties::longhands::{self, animation_timing_function};
|
||||
use style::properties::{CSSWideKeyword, CustomDeclaration};
|
||||
use style::properties::{CustomDeclarationValue, Importance};
|
||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
||||
use style::properties::longhands::{self, animation_timing_function};
|
||||
use style::shared_lock::SharedRwLock;
|
||||
use style::stylesheets::{Origin, Namespaces};
|
||||
use style::stylesheets::{Stylesheet, StylesheetContents, NamespaceRule, CssRule, CssRules, StyleRule, KeyframesRule};
|
||||
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframePercentage};
|
||||
use style::values::{KeyframesName, CustomIdent};
|
||||
use style::stylesheets::keyframes_rule::{Keyframe, KeyframePercentage, KeyframeSelector};
|
||||
use style::stylesheets::{
|
||||
CssRule, CssRules, KeyframesRule, NamespaceRule, StyleRule, Stylesheet, StylesheetContents,
|
||||
};
|
||||
use style::stylesheets::{Namespaces, Origin};
|
||||
use style::values::computed::Percentage;
|
||||
use style::values::specified::{LengthPercentageOrAuto, PositionComponent};
|
||||
use style::values::specified::TimingFunction;
|
||||
use style::values::specified::{LengthPercentageOrAuto, PositionComponent};
|
||||
use style::values::{CustomIdent, KeyframesName};
|
||||
|
||||
pub fn block_from<I>(iterable: I) -> PropertyDeclarationBlock
|
||||
where I: IntoIterator<Item=(PropertyDeclaration, Importance)> {
|
||||
where
|
||||
I: IntoIterator<Item = (PropertyDeclaration, Importance)>,
|
||||
{
|
||||
let mut block = PropertyDeclarationBlock::new();
|
||||
for (d, i) in iterable {
|
||||
block.push(d, i);
|
||||
|
|
@ -69,8 +73,17 @@ fn test_parse_stylesheet() {
|
|||
let url = ServoUrl::parse("about::test").unwrap();
|
||||
let lock = SharedRwLock::new();
|
||||
let media = Arc::new(lock.wrap(MediaList::empty()));
|
||||
let stylesheet = Stylesheet::from_str(css, url.clone(), Origin::UserAgent, media, lock,
|
||||
None, None, QuirksMode::NoQuirks, 0);
|
||||
let stylesheet = Stylesheet::from_str(
|
||||
css,
|
||||
url.clone(),
|
||||
Origin::UserAgent,
|
||||
media,
|
||||
lock,
|
||||
None,
|
||||
None,
|
||||
QuirksMode::NoQuirks,
|
||||
0,
|
||||
);
|
||||
let mut namespaces = Namespaces::default();
|
||||
namespaces.default = Some(ns!(html));
|
||||
let expected = Stylesheet {
|
||||
|
|
@ -79,180 +92,245 @@ fn test_parse_stylesheet() {
|
|||
namespaces: RwLock::new(namespaces),
|
||||
url_data: RwLock::new(url),
|
||||
quirks_mode: QuirksMode::NoQuirks,
|
||||
rules: CssRules::new(vec![
|
||||
CssRule::Namespace(Arc::new(stylesheet.shared_lock.wrap(NamespaceRule {
|
||||
prefix: None,
|
||||
url: NsAtom::from("http://www.w3.org/1999/xhtml"),
|
||||
source_location: SourceLocation {
|
||||
line: 1,
|
||||
column: 19,
|
||||
},
|
||||
}))),
|
||||
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||
selectors: SelectorList::from_vec(vec!(
|
||||
Selector::from_vec(vec!(
|
||||
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
|
||||
Component::LocalName(LocalName {
|
||||
name: local_name!("input"),
|
||||
lower_name: local_name!("input"),
|
||||
}),
|
||||
Component::AttributeInNoNamespace {
|
||||
local_name: local_name!("type"),
|
||||
operator: AttrSelectorOperator::Equal,
|
||||
value: "hidden".to_owned(),
|
||||
case_sensitivity: ParsedCaseSensitivity::AsciiCaseInsensitive,
|
||||
never_matches: false,
|
||||
}
|
||||
), (0 << 20) + (1 << 10) + (1 << 0))
|
||||
)),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||
(
|
||||
PropertyDeclaration::Display(longhands::display::SpecifiedValue::None),
|
||||
Importance::Important,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::Custom(CustomDeclaration {
|
||||
name: Atom::from("a"),
|
||||
value: CustomDeclarationValue::CSSWideKeyword(CSSWideKeyword::Inherit),
|
||||
}),
|
||||
Importance::Important,
|
||||
),
|
||||
]))),
|
||||
source_location: SourceLocation {
|
||||
line: 3,
|
||||
column: 9,
|
||||
},
|
||||
}))),
|
||||
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||
selectors: SelectorList::from_vec(vec!(
|
||||
Selector::from_vec(vec!(
|
||||
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
|
||||
rules: CssRules::new(
|
||||
vec![
|
||||
CssRule::Namespace(Arc::new(stylesheet.shared_lock.wrap(NamespaceRule {
|
||||
prefix: None,
|
||||
url: NsAtom::from("http://www.w3.org/1999/xhtml"),
|
||||
source_location: SourceLocation {
|
||||
line: 1,
|
||||
column: 19,
|
||||
},
|
||||
}))),
|
||||
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||
selectors: SelectorList::from_vec(vec![Selector::from_vec(
|
||||
vec![
|
||||
Component::DefaultNamespace(NsAtom::from(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
)),
|
||||
Component::LocalName(LocalName {
|
||||
name: local_name!("html"),
|
||||
lower_name: local_name!("html"),
|
||||
name: local_name!("input"),
|
||||
lower_name: local_name!("input"),
|
||||
}),
|
||||
), (0 << 20) + (0 << 10) + (1 << 0)),
|
||||
Selector::from_vec(vec!(
|
||||
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
|
||||
Component::LocalName(LocalName {
|
||||
name: local_name!("body"),
|
||||
lower_name: local_name!("body"),
|
||||
})
|
||||
), (0 << 20) + (0 << 10) + (1 << 0)
|
||||
),
|
||||
)),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||
(PropertyDeclaration::Display(longhands::display::SpecifiedValue::Block),
|
||||
Importance::Normal),
|
||||
]))),
|
||||
source_location: SourceLocation {
|
||||
line: 11,
|
||||
column: 9,
|
||||
},
|
||||
}))),
|
||||
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||
selectors: SelectorList::from_vec(vec!(
|
||||
Selector::from_vec(vec!(
|
||||
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
|
||||
Component::ID(Atom::from("d1")),
|
||||
Component::Combinator(Combinator::Child),
|
||||
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
|
||||
Component::Class(Atom::from("ok"))
|
||||
), (1 << 20) + (1 << 10) + (0 << 0))
|
||||
)),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||
(PropertyDeclaration::BackgroundColor(
|
||||
longhands::background_color::SpecifiedValue::Numeric {
|
||||
authored: Some("blue".to_owned().into_boxed_str()),
|
||||
parsed: cssparser::RGBA::new(0, 0, 255, 255),
|
||||
}
|
||||
),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::BackgroundPositionX(
|
||||
longhands::background_position_x::SpecifiedValue(
|
||||
vec![PositionComponent::zero()])),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::BackgroundPositionY(
|
||||
longhands::background_position_y::SpecifiedValue(
|
||||
vec![PositionComponent::zero()])),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::BackgroundRepeat(
|
||||
longhands::background_repeat::SpecifiedValue(
|
||||
vec![longhands::background_repeat::single_value
|
||||
::get_initial_specified_value()])),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::BackgroundAttachment(
|
||||
longhands::background_attachment::SpecifiedValue(
|
||||
vec![longhands::background_attachment::single_value
|
||||
::get_initial_specified_value()])),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::BackgroundImage(
|
||||
longhands::background_image::SpecifiedValue(
|
||||
vec![longhands::background_image::single_value
|
||||
::get_initial_specified_value()])),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::BackgroundSize(
|
||||
longhands::background_size::SpecifiedValue(
|
||||
vec![longhands::background_size::single_value
|
||||
::get_initial_specified_value()])),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::BackgroundOrigin(
|
||||
longhands::background_origin::SpecifiedValue(
|
||||
vec![longhands::background_origin::single_value
|
||||
::get_initial_specified_value()])),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::BackgroundClip(
|
||||
longhands::background_clip::SpecifiedValue(
|
||||
vec![longhands::background_clip::single_value
|
||||
::get_initial_specified_value()])),
|
||||
Importance::Normal),
|
||||
]))),
|
||||
source_location: SourceLocation {
|
||||
line: 15,
|
||||
column: 9,
|
||||
},
|
||||
}))),
|
||||
CssRule::Keyframes(Arc::new(stylesheet.shared_lock.wrap(KeyframesRule {
|
||||
name: KeyframesName::Ident(CustomIdent("foo".into())),
|
||||
keyframes: vec![
|
||||
Arc::new(stylesheet.shared_lock.wrap(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(
|
||||
vec![KeyframePercentage::new(0.)]),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||
(PropertyDeclaration::Width(
|
||||
LengthPercentageOrAuto::Percentage(Percentage(0.))),
|
||||
Importance::Normal),
|
||||
]))),
|
||||
source_location: SourceLocation {
|
||||
line: 17,
|
||||
column: 13,
|
||||
},
|
||||
})),
|
||||
Arc::new(stylesheet.shared_lock.wrap(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(
|
||||
vec![KeyframePercentage::new(1.)]),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||
(PropertyDeclaration::Width(
|
||||
LengthPercentageOrAuto::Percentage(Percentage(1.))),
|
||||
Importance::Normal),
|
||||
(PropertyDeclaration::AnimationTimingFunction(
|
||||
animation_timing_function::SpecifiedValue(
|
||||
vec![TimingFunction::ease()])),
|
||||
Importance::Normal),
|
||||
]))),
|
||||
source_location: SourceLocation {
|
||||
line: 18,
|
||||
column: 13,
|
||||
},
|
||||
})),
|
||||
],
|
||||
vendor_prefix: None,
|
||||
source_location: SourceLocation {
|
||||
line: 16,
|
||||
column: 19,
|
||||
},
|
||||
})))
|
||||
], &stylesheet.shared_lock),
|
||||
Component::AttributeInNoNamespace {
|
||||
local_name: local_name!("type"),
|
||||
operator: AttrSelectorOperator::Equal,
|
||||
value: "hidden".to_owned(),
|
||||
case_sensitivity: ParsedCaseSensitivity::AsciiCaseInsensitive,
|
||||
never_matches: false,
|
||||
},
|
||||
],
|
||||
(0 << 20) + (1 << 10) + (1 << 0),
|
||||
)]),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||
(
|
||||
PropertyDeclaration::Display(
|
||||
longhands::display::SpecifiedValue::None,
|
||||
),
|
||||
Importance::Important,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::Custom(CustomDeclaration {
|
||||
name: Atom::from("a"),
|
||||
value: CustomDeclarationValue::CSSWideKeyword(
|
||||
CSSWideKeyword::Inherit,
|
||||
),
|
||||
}),
|
||||
Importance::Important,
|
||||
),
|
||||
]))),
|
||||
source_location: SourceLocation { line: 3, column: 9 },
|
||||
}))),
|
||||
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||
selectors: SelectorList::from_vec(vec![
|
||||
Selector::from_vec(
|
||||
vec![
|
||||
Component::DefaultNamespace(NsAtom::from(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
)),
|
||||
Component::LocalName(LocalName {
|
||||
name: local_name!("html"),
|
||||
lower_name: local_name!("html"),
|
||||
}),
|
||||
],
|
||||
(0 << 20) + (0 << 10) + (1 << 0),
|
||||
),
|
||||
Selector::from_vec(
|
||||
vec![
|
||||
Component::DefaultNamespace(NsAtom::from(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
)),
|
||||
Component::LocalName(LocalName {
|
||||
name: local_name!("body"),
|
||||
lower_name: local_name!("body"),
|
||||
}),
|
||||
],
|
||||
(0 << 20) + (0 << 10) + (1 << 0),
|
||||
),
|
||||
]),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![(
|
||||
PropertyDeclaration::Display(longhands::display::SpecifiedValue::Block),
|
||||
Importance::Normal,
|
||||
)]))),
|
||||
source_location: SourceLocation {
|
||||
line: 11,
|
||||
column: 9,
|
||||
},
|
||||
}))),
|
||||
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||
selectors: SelectorList::from_vec(vec![Selector::from_vec(
|
||||
vec![
|
||||
Component::DefaultNamespace(NsAtom::from(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
)),
|
||||
Component::ID(Atom::from("d1")),
|
||||
Component::Combinator(Combinator::Child),
|
||||
Component::DefaultNamespace(NsAtom::from(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
)),
|
||||
Component::Class(Atom::from("ok")),
|
||||
],
|
||||
(1 << 20) + (1 << 10) + (0 << 0),
|
||||
)]),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||
(
|
||||
PropertyDeclaration::BackgroundColor(
|
||||
longhands::background_color::SpecifiedValue::Numeric {
|
||||
authored: Some("blue".to_owned().into_boxed_str()),
|
||||
parsed: cssparser::RGBA::new(0, 0, 255, 255),
|
||||
},
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::BackgroundPositionX(
|
||||
longhands::background_position_x::SpecifiedValue(vec![
|
||||
PositionComponent::zero(),
|
||||
]),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::BackgroundPositionY(
|
||||
longhands::background_position_y::SpecifiedValue(vec![
|
||||
PositionComponent::zero(),
|
||||
]),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::BackgroundRepeat(
|
||||
longhands::background_repeat::SpecifiedValue(
|
||||
vec![longhands::background_repeat::single_value
|
||||
::get_initial_specified_value()],
|
||||
),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::BackgroundAttachment(
|
||||
longhands::background_attachment::SpecifiedValue(
|
||||
vec![longhands::background_attachment::single_value
|
||||
::get_initial_specified_value()],
|
||||
),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::BackgroundImage(
|
||||
longhands::background_image::SpecifiedValue(
|
||||
vec![longhands::background_image::single_value
|
||||
::get_initial_specified_value()],
|
||||
),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::BackgroundSize(
|
||||
longhands::background_size::SpecifiedValue(
|
||||
vec![longhands::background_size::single_value
|
||||
::get_initial_specified_value()],
|
||||
),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::BackgroundOrigin(
|
||||
longhands::background_origin::SpecifiedValue(
|
||||
vec![longhands::background_origin::single_value
|
||||
::get_initial_specified_value()],
|
||||
),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::BackgroundClip(
|
||||
longhands::background_clip::SpecifiedValue(
|
||||
vec![longhands::background_clip::single_value
|
||||
::get_initial_specified_value()],
|
||||
),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
]))),
|
||||
source_location: SourceLocation {
|
||||
line: 15,
|
||||
column: 9,
|
||||
},
|
||||
}))),
|
||||
CssRule::Keyframes(Arc::new(stylesheet.shared_lock.wrap(KeyframesRule {
|
||||
name: KeyframesName::Ident(CustomIdent("foo".into())),
|
||||
keyframes: vec![
|
||||
Arc::new(stylesheet.shared_lock.wrap(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![
|
||||
KeyframePercentage::new(0.),
|
||||
]),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![(
|
||||
PropertyDeclaration::Width(LengthPercentageOrAuto::Percentage(
|
||||
Percentage(0.),
|
||||
)),
|
||||
Importance::Normal,
|
||||
)]))),
|
||||
source_location: SourceLocation {
|
||||
line: 17,
|
||||
column: 13,
|
||||
},
|
||||
})),
|
||||
Arc::new(stylesheet.shared_lock.wrap(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![
|
||||
KeyframePercentage::new(1.),
|
||||
]),
|
||||
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
|
||||
(
|
||||
PropertyDeclaration::Width(
|
||||
LengthPercentageOrAuto::Percentage(Percentage(1.)),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
(
|
||||
PropertyDeclaration::AnimationTimingFunction(
|
||||
animation_timing_function::SpecifiedValue(vec![
|
||||
TimingFunction::ease(),
|
||||
]),
|
||||
),
|
||||
Importance::Normal,
|
||||
),
|
||||
]))),
|
||||
source_location: SourceLocation {
|
||||
line: 18,
|
||||
column: 13,
|
||||
},
|
||||
})),
|
||||
],
|
||||
vendor_prefix: None,
|
||||
source_location: SourceLocation {
|
||||
line: 16,
|
||||
column: 19,
|
||||
},
|
||||
}))),
|
||||
],
|
||||
&stylesheet.shared_lock,
|
||||
),
|
||||
source_map_url: RwLock::new(None),
|
||||
source_url: RwLock::new(None),
|
||||
},
|
||||
|
|
@ -266,10 +344,10 @@ fn test_parse_stylesheet() {
|
|||
|
||||
#[derive(Debug)]
|
||||
struct CSSError {
|
||||
pub url : ServoUrl,
|
||||
pub url: ServoUrl,
|
||||
pub line: u32,
|
||||
pub column: u32,
|
||||
pub message: String
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
struct TestingErrorReporter {
|
||||
|
|
@ -285,11 +363,21 @@ impl TestingErrorReporter {
|
|||
|
||||
fn assert_messages_contain(&self, expected_errors: &[(u32, u32, &str)]) {
|
||||
let errors = self.errors.borrow();
|
||||
for (i, (error, &(line, column, message))) in errors.iter().zip(expected_errors).enumerate() {
|
||||
assert_eq!((error.line, error.column), (line, column),
|
||||
"line/column numbers of the {}th error: {:?}", i + 1, error.message);
|
||||
assert!(error.message.contains(message),
|
||||
"{:?} does not contain {:?}", error.message, message);
|
||||
for (i, (error, &(line, column, message))) in errors.iter().zip(expected_errors).enumerate()
|
||||
{
|
||||
assert_eq!(
|
||||
(error.line, error.column),
|
||||
(line, column),
|
||||
"line/column numbers of the {}th error: {:?}",
|
||||
i + 1,
|
||||
error.message
|
||||
);
|
||||
assert!(
|
||||
error.message.contains(message),
|
||||
"{:?} does not contain {:?}",
|
||||
error.message,
|
||||
message
|
||||
);
|
||||
}
|
||||
if errors.len() < expected_errors.len() {
|
||||
panic!("Missing errors: {:#?}", &expected_errors[errors.len()..]);
|
||||
|
|
@ -301,22 +389,16 @@ impl TestingErrorReporter {
|
|||
}
|
||||
|
||||
impl ParseErrorReporter for TestingErrorReporter {
|
||||
fn report_error(&self,
|
||||
url: &ServoUrl,
|
||||
location: SourceLocation,
|
||||
error: ContextualParseError) {
|
||||
self.errors.borrow_mut().push(
|
||||
CSSError{
|
||||
url: url.clone(),
|
||||
line: location.line,
|
||||
column: location.column,
|
||||
message: error.to_string(),
|
||||
}
|
||||
)
|
||||
fn report_error(&self, url: &ServoUrl, location: SourceLocation, error: ContextualParseError) {
|
||||
self.errors.borrow_mut().push(CSSError {
|
||||
url: url.clone(),
|
||||
line: location.line,
|
||||
column: location.column,
|
||||
message: error.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_report_error_stylesheet() {
|
||||
PREFS.set("layout.viewport.enabled", PrefValue::Boolean(true));
|
||||
|
|
@ -342,29 +424,50 @@ fn test_report_error_stylesheet() {
|
|||
|
||||
let lock = SharedRwLock::new();
|
||||
let media = Arc::new(lock.wrap(MediaList::empty()));
|
||||
Stylesheet::from_str(css, url.clone(), Origin::UserAgent, media, lock,
|
||||
None, Some(&error_reporter), QuirksMode::NoQuirks, 5);
|
||||
Stylesheet::from_str(
|
||||
css,
|
||||
url.clone(),
|
||||
Origin::UserAgent,
|
||||
media,
|
||||
lock,
|
||||
None,
|
||||
Some(&error_reporter),
|
||||
QuirksMode::NoQuirks,
|
||||
5,
|
||||
);
|
||||
|
||||
error_reporter.assert_messages_contain(&[
|
||||
(8, 18, "Unsupported property declaration: 'display: invalid;'"),
|
||||
(9, 27, "Unsupported property declaration: 'background-image:"), // FIXME: column should be around 56
|
||||
(
|
||||
8,
|
||||
18,
|
||||
"Unsupported property declaration: 'display: invalid;'",
|
||||
),
|
||||
(
|
||||
9,
|
||||
27,
|
||||
"Unsupported property declaration: 'background-image:",
|
||||
), // FIXME: column should be around 56
|
||||
(10, 17, "Unsupported property declaration: 'invalid: true;'"),
|
||||
(12, 28, "Invalid media rule"),
|
||||
(13, 30, "Unsupported @font-face descriptor declaration"),
|
||||
|
||||
// When @counter-style is supported, this should be replaced with two errors
|
||||
(14, 19, "Invalid rule: '@counter-style "),
|
||||
|
||||
// When @font-feature-values is supported, this should be replaced with two errors
|
||||
(15, 25, "Invalid rule: '@font-feature-values "),
|
||||
|
||||
(16, 13, "Invalid rule: '@invalid'"),
|
||||
(17, 29, "Invalid rule: '@invalid'"),
|
||||
|
||||
(18, 34, "Invalid rule: '@supports "),
|
||||
(19, 26, "Invalid keyframe rule: 'from invalid '"),
|
||||
(19, 52, "Unsupported keyframe property declaration: 'margin: 0 invalid 0;'"),
|
||||
(20, 29, "Unsupported @viewport descriptor declaration: 'width: 320px invalid auto;'"),
|
||||
(
|
||||
19,
|
||||
52,
|
||||
"Unsupported keyframe property declaration: 'margin: 0 invalid 0;'",
|
||||
),
|
||||
(
|
||||
20,
|
||||
29,
|
||||
"Unsupported @viewport descriptor declaration: 'width: 320px invalid auto;'",
|
||||
),
|
||||
]);
|
||||
|
||||
assert_eq!(error_reporter.errors.borrow()[0].url, url);
|
||||
|
|
@ -384,28 +487,50 @@ fn test_no_report_unrecognized_vendor_properties() {
|
|||
|
||||
let lock = SharedRwLock::new();
|
||||
let media = Arc::new(lock.wrap(MediaList::empty()));
|
||||
Stylesheet::from_str(css, url, Origin::UserAgent, media, lock,
|
||||
None, Some(&error_reporter), QuirksMode::NoQuirks, 0);
|
||||
Stylesheet::from_str(
|
||||
css,
|
||||
url,
|
||||
Origin::UserAgent,
|
||||
media,
|
||||
lock,
|
||||
None,
|
||||
Some(&error_reporter),
|
||||
QuirksMode::NoQuirks,
|
||||
0,
|
||||
);
|
||||
|
||||
error_reporter.assert_messages_contain(&[
|
||||
(4, 31, "Unsupported property declaration: '-moz-background-color: red;'"),
|
||||
]);
|
||||
error_reporter.assert_messages_contain(&[(
|
||||
4,
|
||||
31,
|
||||
"Unsupported property declaration: '-moz-background-color: red;'",
|
||||
)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_source_map_url() {
|
||||
let tests = vec![
|
||||
("", None),
|
||||
("/*# sourceMappingURL=something */", Some("something".to_string())),
|
||||
(
|
||||
"/*# sourceMappingURL=something */",
|
||||
Some("something".to_string()),
|
||||
),
|
||||
];
|
||||
|
||||
for test in tests {
|
||||
let url = ServoUrl::parse("about::test").unwrap();
|
||||
let lock = SharedRwLock::new();
|
||||
let media = Arc::new(lock.wrap(MediaList::empty()));
|
||||
let stylesheet = Stylesheet::from_str(test.0, url.clone(), Origin::UserAgent, media, lock,
|
||||
None, None, QuirksMode::NoQuirks,
|
||||
0);
|
||||
let stylesheet = Stylesheet::from_str(
|
||||
test.0,
|
||||
url.clone(),
|
||||
Origin::UserAgent,
|
||||
media,
|
||||
lock,
|
||||
None,
|
||||
None,
|
||||
QuirksMode::NoQuirks,
|
||||
0,
|
||||
);
|
||||
let url_opt = stylesheet.contents.source_map_url.read();
|
||||
assert_eq!(*url_opt, test.1);
|
||||
}
|
||||
|
|
@ -422,9 +547,17 @@ fn test_source_url() {
|
|||
let url = ServoUrl::parse("about::test").unwrap();
|
||||
let lock = SharedRwLock::new();
|
||||
let media = Arc::new(lock.wrap(MediaList::empty()));
|
||||
let stylesheet = Stylesheet::from_str(test.0, url.clone(), Origin::UserAgent, media, lock,
|
||||
None, None, QuirksMode::NoQuirks,
|
||||
0);
|
||||
let stylesheet = Stylesheet::from_str(
|
||||
test.0,
|
||||
url.clone(),
|
||||
Origin::UserAgent,
|
||||
media,
|
||||
lock,
|
||||
None,
|
||||
None,
|
||||
QuirksMode::NoQuirks,
|
||||
0,
|
||||
);
|
||||
let url_opt = stylesheet.contents.source_url.read();
|
||||
assert_eq!(*url_opt, test.1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,51 +10,69 @@ use servo_arc::Arc;
|
|||
use servo_atoms::Atom;
|
||||
use style::context::QuirksMode;
|
||||
use style::media_queries::{Device, MediaType};
|
||||
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration};
|
||||
use style::properties::{longhands, Importance};
|
||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
||||
use style::selector_map::SelectorMap;
|
||||
use style::selector_parser::{SelectorImpl, SelectorParser};
|
||||
use style::shared_lock::SharedRwLock;
|
||||
use style::stylesheets::StyleRule;
|
||||
use style::stylist::{Stylist, Rule};
|
||||
use style::stylist::needs_revalidation_for_testing;
|
||||
use style::stylist::{Rule, Stylist};
|
||||
use style::thread_state::{self, ThreadState};
|
||||
|
||||
/// Helper method to get some Rules from selector strings.
|
||||
/// Each sublist of the result contains the Rules for one StyleRule.
|
||||
fn get_mock_rules(css_selectors: &[&str]) -> (Vec<Vec<Rule>>, SharedRwLock) {
|
||||
let shared_lock = SharedRwLock::new();
|
||||
(css_selectors.iter().enumerate().map(|(i, selectors)| {
|
||||
let selectors = SelectorParser::parse_author_origin_no_namespace(selectors).unwrap();
|
||||
(
|
||||
css_selectors
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, selectors)| {
|
||||
let selectors =
|
||||
SelectorParser::parse_author_origin_no_namespace(selectors).unwrap();
|
||||
|
||||
let locked = Arc::new(shared_lock.wrap(StyleRule {
|
||||
selectors: selectors,
|
||||
block: Arc::new(shared_lock.wrap(PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::Display(
|
||||
longhands::display::SpecifiedValue::Block),
|
||||
Importance::Normal
|
||||
))),
|
||||
source_location: SourceLocation {
|
||||
line: 0,
|
||||
column: 0,
|
||||
},
|
||||
}));
|
||||
let locked = Arc::new(shared_lock.wrap(StyleRule {
|
||||
selectors: selectors,
|
||||
block: Arc::new(shared_lock.wrap(PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::Display(longhands::display::SpecifiedValue::Block),
|
||||
Importance::Normal,
|
||||
))),
|
||||
source_location: SourceLocation { line: 0, column: 0 },
|
||||
}));
|
||||
|
||||
let guard = shared_lock.read();
|
||||
let rule = locked.read_with(&guard);
|
||||
rule.selectors.0.iter().map(|s| {
|
||||
Rule::new(s.clone(), AncestorHashes::new(s, QuirksMode::NoQuirks), locked.clone(), i as u32)
|
||||
}).collect()
|
||||
}).collect(), shared_lock)
|
||||
let guard = shared_lock.read();
|
||||
let rule = locked.read_with(&guard);
|
||||
rule.selectors
|
||||
.0
|
||||
.iter()
|
||||
.map(|s| {
|
||||
Rule::new(
|
||||
s.clone(),
|
||||
AncestorHashes::new(s, QuirksMode::NoQuirks),
|
||||
locked.clone(),
|
||||
i as u32,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect(),
|
||||
shared_lock,
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_selectors(selectors: &[&str]) -> Vec<Selector<SelectorImpl>> {
|
||||
selectors.iter()
|
||||
.map(|x| SelectorParser::parse_author_origin_no_namespace(x).unwrap().0
|
||||
.into_iter()
|
||||
.nth(0)
|
||||
.unwrap())
|
||||
.collect()
|
||||
selectors
|
||||
.iter()
|
||||
.map(|x| {
|
||||
SelectorParser::parse_author_origin_no_namespace(x)
|
||||
.unwrap()
|
||||
.0
|
||||
.into_iter()
|
||||
.nth(0)
|
||||
.unwrap()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -65,14 +83,13 @@ fn test_revalidation_selectors() {
|
|||
"div:not(.foo)",
|
||||
"div span",
|
||||
"div > span",
|
||||
|
||||
// ID selectors.
|
||||
"#foo1",
|
||||
"#foo2::before",
|
||||
"#foo3 > span",
|
||||
"#foo1 > span", // FIXME(bz): This one should not be a
|
||||
// revalidation selector, since #foo1 should be in the
|
||||
// rule hash.
|
||||
// revalidation selector, since #foo1 should be in the
|
||||
// rule hash.
|
||||
|
||||
// Attribute selectors.
|
||||
"div[foo]",
|
||||
|
|
@ -84,7 +101,6 @@ fn test_revalidation_selectors() {
|
|||
"div[foo $= \"bar\"]",
|
||||
"div[foo *= \"bar\"]",
|
||||
"*|div[foo][bar = \"baz\"]",
|
||||
|
||||
// Non-state-based pseudo-classes.
|
||||
"div:empty",
|
||||
"div:first-child",
|
||||
|
|
@ -97,7 +113,6 @@ fn test_revalidation_selectors() {
|
|||
"div:first-of-type",
|
||||
"div:last-of-type",
|
||||
"div:only-of-type",
|
||||
|
||||
// Note: it would be nice to test :moz-any and the various other non-TS
|
||||
// pseudo classes supported by gecko, but we don't have access to those
|
||||
// in these unit tests. :-(
|
||||
|
|
@ -105,18 +120,17 @@ fn test_revalidation_selectors() {
|
|||
// Sibling combinators.
|
||||
"span + div",
|
||||
"span ~ div",
|
||||
|
||||
// Selectors in the ancestor chain (needed for cousin sharing).
|
||||
"p:first-child span",
|
||||
]).into_iter()
|
||||
.filter(|s| needs_revalidation_for_testing(&s))
|
||||
.collect::<Vec<_>>();
|
||||
])
|
||||
.into_iter()
|
||||
.filter(|s| needs_revalidation_for_testing(&s))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let reference = parse_selectors(&[
|
||||
// ID selectors.
|
||||
"#foo3 > span",
|
||||
"#foo1 > span",
|
||||
|
||||
// Attribute selectors.
|
||||
"div[foo]",
|
||||
"div:not([foo])",
|
||||
|
|
@ -127,7 +141,6 @@ fn test_revalidation_selectors() {
|
|||
"div[foo $= \"bar\"]",
|
||||
"div[foo *= \"bar\"]",
|
||||
"*|div[foo][bar = \"baz\"]",
|
||||
|
||||
// Non-state-based pseudo-classes.
|
||||
"div:empty",
|
||||
"div:first-child",
|
||||
|
|
@ -140,15 +153,14 @@ fn test_revalidation_selectors() {
|
|||
"div:first-of-type",
|
||||
"div:last-of-type",
|
||||
"div:only-of-type",
|
||||
|
||||
// Sibling combinators.
|
||||
"span + div",
|
||||
"span ~ div",
|
||||
|
||||
// Selectors in the ancestor chain (needed for cousin sharing).
|
||||
"p:first-child span",
|
||||
]).into_iter()
|
||||
.collect::<Vec<_>>();
|
||||
])
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(test.len(), reference.len());
|
||||
for (t, r) in test.into_iter().zip(reference.into_iter()) {
|
||||
|
|
@ -161,25 +173,50 @@ fn test_rule_ordering_same_specificity() {
|
|||
let (rules_list, _) = get_mock_rules(&["a.intro", "img.sidebar"]);
|
||||
let a = &rules_list[0][0];
|
||||
let b = &rules_list[1][0];
|
||||
assert!((a.specificity(), a.source_order) < ((b.specificity(), b.source_order)),
|
||||
"The rule that comes later should win.");
|
||||
assert!(
|
||||
(a.specificity(), a.source_order) < ((b.specificity(), b.source_order)),
|
||||
"The rule that comes later should win."
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
let (rules_list, _) = get_mock_rules(&[".intro.foo", "#top"]);
|
||||
let mut selector_map = SelectorMap::new();
|
||||
selector_map.insert(rules_list[1][0].clone(), QuirksMode::NoQuirks)
|
||||
.expect("OOM");
|
||||
assert_eq!(1, selector_map.id_hash.get(&Atom::from("top"), QuirksMode::NoQuirks).unwrap()[0].source_order);
|
||||
selector_map.insert(rules_list[0][0].clone(), QuirksMode::NoQuirks)
|
||||
.expect("OOM");
|
||||
assert_eq!(0, selector_map.class_hash.get(&Atom::from("foo"), QuirksMode::NoQuirks).unwrap()[0].source_order);
|
||||
assert!(selector_map.class_hash.get(&Atom::from("intro"), QuirksMode::NoQuirks).is_none());
|
||||
selector_map
|
||||
.insert(rules_list[1][0].clone(), QuirksMode::NoQuirks)
|
||||
.expect("OOM");
|
||||
assert_eq!(
|
||||
1,
|
||||
selector_map
|
||||
.id_hash
|
||||
.get(&Atom::from("top"), QuirksMode::NoQuirks)
|
||||
.unwrap()[0]
|
||||
.source_order
|
||||
);
|
||||
selector_map
|
||||
.insert(rules_list[0][0].clone(), QuirksMode::NoQuirks)
|
||||
.expect("OOM");
|
||||
assert_eq!(
|
||||
0,
|
||||
selector_map
|
||||
.class_hash
|
||||
.get(&Atom::from("foo"), QuirksMode::NoQuirks)
|
||||
.unwrap()[0]
|
||||
.source_order
|
||||
);
|
||||
assert!(selector_map
|
||||
.class_hash
|
||||
.get(&Atom::from("intro"), QuirksMode::NoQuirks)
|
||||
.is_none());
|
||||
}
|
||||
|
||||
fn mock_stylist() -> Stylist {
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(0f32, 0f32), Scale::new(1.0));
|
||||
let device = Device::new(
|
||||
MediaType::screen(),
|
||||
Size2D::new(0f32, 0f32),
|
||||
Scale::new(1.0),
|
||||
);
|
||||
Stylist::new(device, QuirksMode::NoQuirks)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue