1#![deny(missing_docs)]
8
9use super::{
10 property_counts, AllShorthand, ComputedValues, LogicalGroupSet, LonghandIdSet,
11 LonghandIdSetIterator, NonCustomPropertyIdSet, PropertyDeclaration, PropertyDeclarationId,
12 PropertyId, ShorthandId, SourcePropertyDeclaration, SourcePropertyDeclarationDrain,
13 SubpropertiesVec,
14};
15use crate::context::QuirksMode;
16use crate::custom_properties;
17use crate::derives::*;
18use crate::dom::AttributeTracker;
19use crate::error_reporting::{ContextualParseError, ParseErrorReporter};
20use crate::parser::ParserContext;
21use crate::properties::{
22 animated_properties::{AnimationValue, AnimationValueMap},
23 StyleBuilder,
24};
25use crate::rule_cache::RuleCacheConditions;
26use crate::rule_tree::RuleCascadeFlags;
27use crate::selector_map::PrecomputedHashSet;
28use crate::selector_parser::SelectorImpl;
29use crate::shared_lock::Locked;
30use crate::stylesheets::container_rule::ContainerSizeQuery;
31use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
32use crate::stylist::Stylist;
33use crate::values::computed::Context;
34use cssparser::{
35 parse_important, AtRuleParser, CowRcStr, DeclarationParser, Delimiter, ParseErrorKind, Parser,
36 ParserInput, ParserState, QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser,
37 SourceLocation,
38};
39use itertools::Itertools;
40use selectors::SelectorList;
41use servo_arc::Arc;
42use smallbitvec::SmallBitVec;
43use smallvec::SmallVec;
44use std::fmt::{self, Write};
45use std::iter::Zip;
46use std::slice::Iter;
47use style_traits::{
48 CssString, CssStringWriter, CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss,
49 TypedValueList,
50};
51use thin_vec::ThinVec;
52
53#[derive(Default)]
55pub struct AnimationDeclarations {
56 pub animations: Option<Arc<Locked<PropertyDeclarationBlock>>>,
58 pub transitions: Option<Arc<Locked<PropertyDeclarationBlock>>>,
60}
61
62impl AnimationDeclarations {
63 pub fn is_empty(&self) -> bool {
65 self.animations.is_none() && self.transitions.is_none()
66 }
67}
68
69#[derive(Clone, Copy, Debug, Eq, PartialEq)]
72enum DeclarationUpdate {
73 None,
75 Append,
77 UpdateInPlace { pos: usize },
79 AppendAndRemove { pos: usize },
82}
83
84#[derive(Default)]
87pub struct SourcePropertyDeclarationUpdate {
88 updates: SubpropertiesVec<DeclarationUpdate>,
89 new_count: usize,
90 any_removal: bool,
91}
92
93#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
97pub enum Importance {
98 Normal,
100
101 Important,
103}
104
105impl Default for Importance {
106 fn default() -> Self {
107 Self::Normal
108 }
109}
110
111impl Importance {
112 pub fn important(self) -> bool {
114 match self {
115 Self::Normal => false,
116 Self::Important => true,
117 }
118 }
119}
120
121#[derive(Clone, Debug, ToShmem, Default, MallocSizeOf)]
123pub struct PropertyDeclarationIdSet {
124 longhands: LonghandIdSet,
125 custom: PrecomputedHashSet<custom_properties::Name>,
126}
127
128impl PropertyDeclarationIdSet {
129 pub fn insert(&mut self, id: PropertyDeclarationId) -> bool {
131 match id {
132 PropertyDeclarationId::Longhand(id) => {
133 if self.longhands.contains(id) {
134 return false;
135 }
136 self.longhands.insert(id);
137 return true;
138 },
139 PropertyDeclarationId::Custom(name) => self.custom.insert((*name).clone()),
140 }
141 }
142
143 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
145 match id {
146 PropertyDeclarationId::Longhand(id) => self.longhands.contains(id),
147 PropertyDeclarationId::Custom(name) => self.custom.contains(name),
148 }
149 }
150
151 pub fn remove(&mut self, id: PropertyDeclarationId) {
153 match id {
154 PropertyDeclarationId::Longhand(id) => self.longhands.remove(id),
155 PropertyDeclarationId::Custom(name) => {
156 self.custom.remove(name);
157 },
158 }
159 }
160
161 pub fn clear(&mut self) {
163 self.longhands.clear();
164 self.custom.clear();
165 }
166
167 #[inline]
169 pub fn is_empty(&self) -> bool {
170 self.longhands.is_empty() && self.custom.is_empty()
171 }
172 #[inline]
174 pub fn contains_any_reset(&self) -> bool {
175 self.longhands.contains_any_reset()
176 }
177
178 #[inline]
180 pub fn contains_all_longhands(&self, longhands: &LonghandIdSet) -> bool {
181 self.longhands.contains_all(longhands)
182 }
183
184 #[inline]
186 pub fn contains_all(&self, properties: &PropertyDeclarationIdSet) -> bool {
187 if !self.longhands.contains_all(&properties.longhands) {
188 return false;
189 }
190 if properties.custom.len() > self.custom.len() {
191 return false;
192 }
193 properties
194 .custom
195 .iter()
196 .all(|item| self.custom.contains(item))
197 }
198
199 pub fn iter(&self) -> PropertyDeclarationIdSetIterator<'_> {
201 PropertyDeclarationIdSetIterator {
202 longhands: self.longhands.iter(),
203 custom: self.custom.iter(),
204 }
205 }
206}
207
208pub struct PropertyDeclarationIdSetIterator<'a> {
210 longhands: LonghandIdSetIterator<'a>,
211 custom: std::collections::hash_set::Iter<'a, custom_properties::Name>,
212}
213
214impl<'a> Iterator for PropertyDeclarationIdSetIterator<'a> {
215 type Item = PropertyDeclarationId<'a>;
216
217 fn next(&mut self) -> Option<Self::Item> {
218 match self.longhands.next() {
222 Some(id) => Some(PropertyDeclarationId::Longhand(id)),
223 None => match self.custom.next() {
224 Some(a) => Some(PropertyDeclarationId::Custom(a)),
225 None => None,
226 },
227 }
228 }
229}
230
231#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
233#[derive(Clone, ToShmem, Default)]
234pub struct PropertyDeclarationBlock {
235 declarations: ThinVec<PropertyDeclaration>,
239
240 declarations_importance: SmallBitVec,
242
243 property_ids: PropertyDeclarationIdSet,
245}
246
247impl PartialEq for PropertyDeclarationBlock {
248 fn eq(&self, other: &Self) -> bool {
249 self.declarations == other.declarations
252 && self.declarations_importance == other.declarations_importance
253 }
254}
255
256pub struct DeclarationImportanceIterator<'a> {
258 iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
259}
260
261impl<'a> Default for DeclarationImportanceIterator<'a> {
262 fn default() -> Self {
263 Self {
264 iter: [].iter().zip(smallbitvec::Iter::default()),
265 }
266 }
267}
268
269impl<'a> DeclarationImportanceIterator<'a> {
270 fn new(declarations: &'a [PropertyDeclaration], important: &'a SmallBitVec) -> Self {
272 DeclarationImportanceIterator {
273 iter: declarations.iter().zip(important.iter()),
274 }
275 }
276}
277
278impl<'a> Iterator for DeclarationImportanceIterator<'a> {
279 type Item = (&'a PropertyDeclaration, Importance);
280
281 #[inline]
282 fn next(&mut self) -> Option<Self::Item> {
283 self.iter.next().map(|(decl, important)| {
284 (
285 decl,
286 if important {
287 Importance::Important
288 } else {
289 Importance::Normal
290 },
291 )
292 })
293 }
294
295 #[inline]
296 fn size_hint(&self) -> (usize, Option<usize>) {
297 self.iter.size_hint()
298 }
299}
300
301impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
302 #[inline(always)]
303 fn next_back(&mut self) -> Option<Self::Item> {
304 self.iter.next_back().map(|(decl, important)| {
305 (
306 decl,
307 if important {
308 Importance::Important
309 } else {
310 Importance::Normal
311 },
312 )
313 })
314 }
315}
316
317pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> {
319 iter: DeclarationImportanceIterator<'a>,
320 context: &'cx mut Context<'cx_a>,
321 style: &'a ComputedValues,
322 default_values: &'a ComputedValues,
323}
324
325impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
326 fn new(
327 declarations: &'a PropertyDeclarationBlock,
328 context: &'cx mut Context<'cx_a>,
329 style: &'a ComputedValues,
330 default_values: &'a ComputedValues,
331 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
332 AnimationValueIterator {
333 iter: declarations.declaration_importance_iter(),
334 context,
335 style,
336 default_values,
337 }
338 }
339}
340
341impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
342 type Item = AnimationValue;
343 #[inline]
344 fn next(&mut self) -> Option<Self::Item> {
345 loop {
346 let (decl, importance) = self.iter.next()?;
347
348 if importance.important() {
349 continue;
350 }
351
352 let animation = AnimationValue::from_declaration(
353 decl,
354 &mut self.context,
355 self.style,
356 self.default_values,
357 &mut AttributeTracker::new_dummy(),
359 );
360
361 if let Some(anim) = animation {
362 return Some(anim);
363 }
364 }
365 }
366}
367
368impl fmt::Debug for PropertyDeclarationBlock {
369 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
370 self.declarations.fmt(f)
371 }
372}
373
374impl PropertyDeclarationBlock {
375 #[inline]
377 pub fn len(&self) -> usize {
378 self.declarations.len()
379 }
380
381 #[inline]
383 pub fn is_empty(&self) -> bool {
384 self.declarations.is_empty()
385 }
386
387 #[inline]
389 pub fn new() -> Self {
390 PropertyDeclarationBlock {
391 declarations: ThinVec::new(),
392 declarations_importance: SmallBitVec::new(),
393 property_ids: PropertyDeclarationIdSet::default(),
394 }
395 }
396
397 pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
399 let mut property_ids = PropertyDeclarationIdSet::default();
400 property_ids.insert(declaration.id());
401 let mut declarations = ThinVec::with_capacity(1);
402 declarations.push(declaration);
403 PropertyDeclarationBlock {
404 declarations,
405 declarations_importance: SmallBitVec::from_elem(1, importance.important()),
406 property_ids,
407 }
408 }
409
410 #[inline]
412 pub fn declarations(&self) -> &[PropertyDeclaration] {
413 &self.declarations
414 }
415
416 #[inline]
418 pub fn declarations_importance(&self) -> &SmallBitVec {
419 &self.declarations_importance
420 }
421
422 #[inline]
424 pub fn declaration_importance_iter(&self) -> DeclarationImportanceIterator<'_> {
425 DeclarationImportanceIterator::new(&self.declarations, &self.declarations_importance)
426 }
427
428 #[inline]
430 pub fn normal_declaration_iter<'a>(
431 &'a self,
432 ) -> impl DoubleEndedIterator<Item = &'a PropertyDeclaration> {
433 self.declaration_importance_iter()
434 .filter(|(_, importance)| !importance.important())
435 .map(|(declaration, _)| declaration)
436 }
437
438 #[inline]
440 pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>(
441 &'a self,
442 context: &'cx mut Context<'cx_a>,
443 style: &'a ComputedValues,
444 default_values: &'a ComputedValues,
445 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
446 AnimationValueIterator::new(self, context, style, default_values)
447 }
448
449 #[inline]
454 pub fn any_important(&self) -> bool {
455 !self.declarations_importance.all_false()
456 }
457
458 #[inline]
463 pub fn any_normal(&self) -> bool {
464 !self.declarations_importance.all_true()
465 }
466
467 #[inline]
470 pub fn property_ids(&self) -> &PropertyDeclarationIdSet {
471 &self.property_ids
472 }
473
474 #[inline]
476 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
477 self.property_ids.contains(id)
478 }
479
480 #[inline]
482 pub fn contains_any_reset(&self) -> bool {
483 self.property_ids.contains_any_reset()
484 }
485
486 #[inline]
491 pub fn get(
492 &self,
493 property: PropertyDeclarationId,
494 ) -> Option<(&PropertyDeclaration, Importance)> {
495 if !self.contains(property) {
496 return None;
497 }
498 self.declaration_importance_iter()
499 .find(|(declaration, _)| declaration.id() == property)
500 }
501
502 pub fn shorthand_to_css(
505 &self,
506 shorthand: ShorthandId,
507 dest: &mut CssStringWriter,
508 ) -> fmt::Result {
509 let mut list = SmallVec::<[&_; 10]>::new();
512 let mut important_count = 0;
513
514 for longhand in shorthand.longhands() {
516 let declaration = self.get(PropertyDeclarationId::Longhand(longhand));
518
519 match declaration {
521 Some((declaration, importance)) => {
522 list.push(declaration);
523 if importance.important() {
524 important_count += 1;
525 }
526 },
527 None => return Ok(()),
528 }
529 }
530
531 if important_count > 0 && important_count != list.len() {
534 return Ok(());
535 }
536
537 match shorthand.get_shorthand_appendable_value(&list) {
541 Some(appendable_value) => append_declaration_value(dest, appendable_value),
542 None => return Ok(()),
543 }
544 }
545
546 pub fn property_value_to_css(
550 &self,
551 property: &PropertyId,
552 dest: &mut CssStringWriter,
553 ) -> fmt::Result {
554 let longhand_or_custom = match property.as_shorthand() {
558 Ok(shorthand) => return self.shorthand_to_css(shorthand, dest),
559 Err(longhand_or_custom) => longhand_or_custom,
560 };
561
562 if let Some((value, _importance)) = self.get(longhand_or_custom) {
563 value.to_css(dest)
565 } else {
566 Ok(())
568 }
569 }
570
571 pub fn property_priority(&self, property: &PropertyId) -> Importance {
573 match property.as_shorthand() {
577 Ok(shorthand) => {
578 if shorthand.longhands().all(|l| {
580 self.get(PropertyDeclarationId::Longhand(l))
581 .map_or(false, |(_, importance)| importance.important())
582 }) {
583 Importance::Important
584 } else {
585 Importance::Normal
586 }
587 },
588 Err(longhand_or_custom) => {
589 self.get(longhand_or_custom)
591 .map_or(Importance::Normal, |(_, importance)| importance)
592 },
593 }
594 }
595
596 pub fn property_value_to_typed_value_list(
600 &self,
601 property: &PropertyId,
602 ) -> Result<Option<TypedValueList>, ()> {
603 match property.as_shorthand() {
604 Ok(shorthand) => {
605 if shorthand
606 .longhands()
607 .all(|longhand| self.contains(PropertyDeclarationId::Longhand(longhand)))
608 {
609 Ok(None)
610 } else {
611 Err(())
612 }
613 },
614 Err(longhand_or_custom) => match self.get(longhand_or_custom) {
615 Some((value, _importance)) => Ok(value.to_typed_value_list()),
616 None => Err(()),
617 },
618 }
619 }
620
621 pub fn extend(
626 &mut self,
627 mut drain: SourcePropertyDeclarationDrain,
628 importance: Importance,
629 ) -> bool {
630 let all_shorthand_len = match drain.all_shorthand {
631 AllShorthand::NotSet => 0,
632 AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
633 property_counts::ALL_SHORTHAND_EXPANDED
634 },
635 };
636 let push_calls_count = drain.declarations.len() + all_shorthand_len;
637
638 self.declarations.reserve(push_calls_count);
640
641 let mut changed = false;
642 for decl in &mut drain.declarations {
643 changed |= self.push(decl, importance);
644 }
645 drain
646 .all_shorthand
647 .declarations()
648 .fold(changed, |changed, decl| {
649 changed | self.push(decl, importance)
650 })
651 }
652
653 pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
659 let id = declaration.id();
660 if !self.property_ids.insert(id) {
661 let mut index_to_remove = None;
662 for (i, slot) in self.declarations.iter_mut().enumerate() {
663 if slot.id() != id {
664 continue;
665 }
666
667 let important = self.declarations_importance[i];
668
669 if important && !importance.important() {
672 return false;
673 }
674
675 index_to_remove = Some(i);
676 break;
677 }
678
679 if let Some(index) = index_to_remove {
680 self.declarations.remove(index);
681 self.declarations_importance.remove(index);
682 self.declarations.push(declaration);
683 self.declarations_importance.push(importance.important());
684 return true;
685 }
686 }
687
688 self.declarations.push(declaration);
689 self.declarations_importance.push(importance.important());
690 true
691 }
692
693 pub fn prepare_for_update(
697 &self,
698 source_declarations: &SourcePropertyDeclaration,
699 importance: Importance,
700 updates: &mut SourcePropertyDeclarationUpdate,
701 ) -> bool {
702 debug_assert!(updates.updates.is_empty());
703 if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
705 debug_assert!(source_declarations.declarations.is_empty());
706 return source_declarations
707 .all_shorthand
708 .declarations()
709 .any(|decl| {
710 !self.contains(decl.id())
711 || self
712 .declarations
713 .iter()
714 .enumerate()
715 .find(|&(_, ref d)| d.id() == decl.id())
716 .map_or(true, |(i, d)| {
717 let important = self.declarations_importance[i];
718 *d != decl || important != importance.important()
719 })
720 });
721 }
722 let mut any_update = false;
724 let new_count = &mut updates.new_count;
725 let any_removal = &mut updates.any_removal;
726 let updates = &mut updates.updates;
727 updates.extend(
728 source_declarations
729 .declarations
730 .iter()
731 .map(|declaration| {
732 if !self.contains(declaration.id()) {
733 return DeclarationUpdate::Append;
734 }
735 let longhand_id = declaration.id().as_longhand();
736 if let Some(longhand_id) = longhand_id {
737 if let Some(logical_group) = longhand_id.logical_group() {
738 let mut needs_append = false;
739 for (pos, decl) in self.declarations.iter().enumerate().rev() {
740 let id = match decl.id().as_longhand() {
741 Some(id) => id,
742 None => continue,
743 };
744 if id == longhand_id {
745 if needs_append {
746 return DeclarationUpdate::AppendAndRemove { pos };
747 }
748 let important = self.declarations_importance[pos];
749 if decl == declaration && important == importance.important() {
750 return DeclarationUpdate::None;
751 }
752 return DeclarationUpdate::UpdateInPlace { pos };
753 }
754 if !needs_append
755 && id.logical_group() == Some(logical_group)
756 && id.is_logical() != longhand_id.is_logical()
757 {
758 needs_append = true;
759 }
760 }
761 unreachable!("Longhand should be found in loop above");
762 }
763 }
764 self.declarations
765 .iter()
766 .enumerate()
767 .find(|&(_, ref decl)| decl.id() == declaration.id())
768 .map_or(DeclarationUpdate::Append, |(pos, decl)| {
769 let important = self.declarations_importance[pos];
770 if decl == declaration && important == importance.important() {
771 DeclarationUpdate::None
772 } else {
773 DeclarationUpdate::UpdateInPlace { pos }
774 }
775 })
776 })
777 .inspect(|update| {
778 if matches!(update, DeclarationUpdate::None) {
779 return;
780 }
781 any_update = true;
782 match update {
783 DeclarationUpdate::Append => {
784 *new_count += 1;
785 },
786 DeclarationUpdate::AppendAndRemove { .. } => {
787 *any_removal = true;
788 },
789 _ => {},
790 }
791 }),
792 );
793 any_update
794 }
795
796 pub fn update(
798 &mut self,
799 drain: SourcePropertyDeclarationDrain,
800 importance: Importance,
801 updates: &mut SourcePropertyDeclarationUpdate,
802 ) {
803 let important = importance.important();
804 if !matches!(drain.all_shorthand, AllShorthand::NotSet) {
805 debug_assert!(updates.updates.is_empty());
806 for decl in drain.all_shorthand.declarations() {
807 let id = decl.id();
808 if self.property_ids.insert(id) {
809 self.declarations.push(decl);
810 self.declarations_importance.push(important);
811 } else {
812 let (idx, slot) = self
813 .declarations
814 .iter_mut()
815 .enumerate()
816 .find(|&(_, ref d)| d.id() == decl.id())
817 .unwrap();
818 *slot = decl;
819 self.declarations_importance.set(idx, important);
820 }
821 }
822 return;
823 }
824
825 self.declarations.reserve(updates.new_count);
826 if updates.any_removal {
827 struct UpdateOrRemoval<'a> {
829 item: &'a mut DeclarationUpdate,
830 pos: usize,
831 remove: bool,
832 }
833 let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
834 .updates
835 .iter_mut()
836 .filter_map(|item| {
837 let (pos, remove) = match *item {
838 DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
839 DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
840 _ => return None,
841 };
842 Some(UpdateOrRemoval { item, pos, remove })
843 })
844 .collect();
845 updates_and_removals.sort_unstable_by_key(|update| update.pos);
848 updates_and_removals
849 .iter()
850 .rev()
851 .filter(|update| update.remove)
852 .for_each(|update| {
853 self.declarations.remove(update.pos);
854 self.declarations_importance.remove(update.pos);
855 });
856 let mut removed_count = 0;
858 for update in updates_and_removals.iter_mut() {
859 if update.remove {
860 removed_count += 1;
861 continue;
862 }
863 debug_assert_eq!(
864 *update.item,
865 DeclarationUpdate::UpdateInPlace { pos: update.pos }
866 );
867 *update.item = DeclarationUpdate::UpdateInPlace {
868 pos: update.pos - removed_count,
869 };
870 }
871 }
872 for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
874 match *update {
875 DeclarationUpdate::None => {},
876 DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
877 self.property_ids.insert(decl.id());
878 self.declarations.push(decl);
879 self.declarations_importance.push(important);
880 },
881 DeclarationUpdate::UpdateInPlace { pos } => {
882 self.declarations[pos] = decl;
883 self.declarations_importance.set(pos, important);
884 },
885 }
886 }
887 updates.updates.clear();
888 }
889
890 #[inline]
893 pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
894 if let Err(longhand_or_custom) = property.as_shorthand() {
895 if !self.contains(longhand_or_custom) {
896 return None;
897 }
898 }
899
900 self.declarations
901 .iter()
902 .position(|declaration| declaration.id().is_or_is_longhand_of(property))
903 }
904
905 #[inline]
907 fn remove_declaration_at(&mut self, i: usize) {
908 self.property_ids.remove(self.declarations[i].id());
909 self.declarations_importance.remove(i);
910 self.declarations.remove(i);
911 }
912
913 #[inline]
915 pub fn clear(&mut self) {
916 self.declarations_importance.clear();
917 self.declarations.clear();
918 self.property_ids.clear();
919 }
920
921 #[inline]
926 pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
927 debug_assert_eq!(
928 Some(first_declaration),
929 self.first_declaration_to_remove(property)
930 );
931 debug_assert!(self.declarations[first_declaration]
932 .id()
933 .is_or_is_longhand_of(property));
934
935 self.remove_declaration_at(first_declaration);
936
937 let shorthand = match property.as_shorthand() {
938 Ok(s) => s,
939 Err(_longhand_or_custom) => return,
940 };
941
942 let mut i = first_declaration;
943 let mut len = self.len();
944 while i < len {
945 if !self.declarations[i].id().is_longhand_of(shorthand) {
946 i += 1;
947 continue;
948 }
949
950 self.remove_declaration_at(i);
951 len -= 1;
952 }
953 }
954
955 pub fn single_value_to_css(
957 &self,
958 property: &PropertyId,
959 dest: &mut CssStringWriter,
960 computed_values: Option<&ComputedValues>,
961 stylist: &Stylist,
962 ) -> fmt::Result {
963 if let Ok(shorthand) = property.as_shorthand() {
964 return self.shorthand_to_css(shorthand, dest);
965 }
966
967 let declaration = match self.declarations.get(0) {
970 Some(d) => d,
971 None => return Err(fmt::Error),
972 };
973
974 let mut rule_cache_conditions = RuleCacheConditions::default();
975 let mut context = Context::new(
976 StyleBuilder::new(
977 stylist.device(),
978 Some(stylist),
979 computed_values,
980 None,
981 None,
982 false,
983 ),
984 stylist.quirks_mode(),
985 &mut rule_cache_conditions,
986 ContainerSizeQuery::none(),
987 RuleCascadeFlags::empty(),
988 );
989
990 if let Some(cv) = computed_values {
991 context.builder.substitution_functions.custom_properties =
992 cv.custom_properties().clone();
993 };
994
995 match (declaration, computed_values) {
996 (&PropertyDeclaration::WithVariables(ref declaration), Some(_)) => declaration
1004 .value
1005 .substitute_variables(
1006 declaration.id,
1007 &context.builder.substitution_functions,
1008 stylist,
1009 &context,
1010 &mut Default::default(),
1011 &mut AttributeTracker::new_dummy(),
1012 )
1013 .to_css(dest),
1014 (ref d, _) => d.to_css(dest),
1015 }
1016 }
1017
1018 pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
1020 let len = animation_value_map.len();
1021 let mut declarations = ThinVec::with_capacity(len);
1022 let mut property_ids = PropertyDeclarationIdSet::default();
1023
1024 for (property, animation_value) in animation_value_map.iter() {
1025 property_ids.insert(property.as_borrowed());
1026 declarations.push(animation_value.uncompute());
1027 }
1028
1029 PropertyDeclarationBlock {
1030 declarations,
1031 property_ids,
1032 declarations_importance: SmallBitVec::from_elem(len, false),
1033 }
1034 }
1035
1036 pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
1039 if let Err(longhand_or_custom) = property.as_shorthand() {
1040 if !self.property_ids.contains(longhand_or_custom) {
1041 return false;
1042 }
1043 }
1044 self.declarations.iter().any(|decl| {
1045 decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
1046 })
1047 }
1048
1049 pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
1055 let mut is_first_serialization = true; let mut already_serialized = NonCustomPropertyIdSet::new();
1067
1068 'declaration_loop: for (declaration, importance) in self.declaration_importance_iter() {
1070 let property = declaration.id();
1072 let longhand_id = match property {
1073 PropertyDeclarationId::Longhand(id) => id,
1074 PropertyDeclarationId::Custom(..) => {
1075 append_serialization(
1080 dest,
1081 &property,
1082 AppendableValue::Declaration(declaration),
1083 importance,
1084 &mut is_first_serialization,
1085 )?;
1086 continue;
1087 },
1088 };
1089
1090 if already_serialized.contains(longhand_id.into()) {
1092 continue;
1093 }
1094
1095 for shorthand in longhand_id.shorthands() {
1097 if already_serialized.contains(shorthand.into()) {
1099 continue;
1100 }
1101 already_serialized.insert(shorthand.into());
1102
1103 if shorthand.is_legacy_shorthand() {
1104 continue;
1105 }
1106
1107 let longhands = {
1114 let mut ids = LonghandIdSet::new();
1117 for longhand in shorthand.longhands() {
1118 ids.insert(longhand);
1119 }
1120 ids
1121 };
1122
1123 if !self.property_ids.contains_all_longhands(&longhands) {
1128 continue;
1129 }
1130
1131 let mut current_longhands = SmallVec::<[&_; 10]>::new();
1134 let mut logical_groups = LogicalGroupSet::new();
1135 let mut saw_one = false;
1136 let mut logical_mismatch = false;
1137 let mut seen = LonghandIdSet::new();
1138 let mut important_count = 0;
1139
1140 for (declaration, importance) in self.declaration_importance_iter() {
1144 let longhand = match declaration.id() {
1145 PropertyDeclarationId::Longhand(id) => id,
1146 PropertyDeclarationId::Custom(..) => continue,
1147 };
1148
1149 if longhands.contains(longhand) {
1150 saw_one = true;
1151 if importance.important() {
1152 important_count += 1;
1153 }
1154 current_longhands.push(declaration);
1155 if shorthand != ShorthandId::All {
1156 if let Some(g) = longhand.logical_group() {
1159 logical_groups.insert(g);
1160 }
1161 seen.insert(longhand);
1162 if seen == longhands {
1163 break;
1164 }
1165 }
1166 } else if saw_one {
1167 if let Some(g) = longhand.logical_group() {
1168 if logical_groups.contains(g) {
1169 logical_mismatch = true;
1170 break;
1171 }
1172 }
1173 }
1174 }
1175
1176 let is_important = important_count > 0;
1182 if is_important && important_count != current_longhands.len() {
1183 continue;
1184 }
1185
1186 if logical_mismatch {
1194 continue;
1195 }
1196
1197 let importance = if is_important {
1198 Importance::Important
1199 } else {
1200 Importance::Normal
1201 };
1202
1203 let appendable_value =
1207 match shorthand.get_shorthand_appendable_value(¤t_longhands) {
1208 None => continue,
1209 Some(appendable_value) => appendable_value,
1210 };
1211
1212 let mut v = CssString::new();
1215 let value = match appendable_value {
1216 AppendableValue::Css(css) => {
1217 debug_assert!(!css.is_empty());
1218 appendable_value
1219 },
1220 other => {
1221 append_declaration_value(&mut v, other)?;
1222
1223 if v.is_empty() {
1227 continue;
1228 }
1229
1230 AppendableValue::Css({
1231 #[cfg(feature = "gecko")]
1233 unsafe {
1234 v.as_str_unchecked()
1235 }
1236 #[cfg(feature = "servo")]
1237 &v
1238 })
1239 },
1240 };
1241
1242 append_serialization(
1252 dest,
1253 &shorthand,
1254 value,
1255 importance,
1256 &mut is_first_serialization,
1257 )?;
1258
1259 for current_longhand in ¤t_longhands {
1263 let longhand_id = match current_longhand.id() {
1264 PropertyDeclarationId::Longhand(id) => id,
1265 PropertyDeclarationId::Custom(..) => unreachable!(),
1266 };
1267
1268 already_serialized.insert(longhand_id.into());
1270 }
1271
1272 continue 'declaration_loop;
1275 }
1276
1277 append_serialization(
1288 dest,
1289 &property,
1290 AppendableValue::Declaration(declaration),
1291 importance,
1292 &mut is_first_serialization,
1293 )?;
1294
1295 already_serialized.insert(longhand_id.into());
1298 }
1299
1300 Ok(())
1302 }
1303}
1304
1305pub enum AppendableValue<'a, 'b: 'a> {
1308 Declaration(&'a PropertyDeclaration),
1310 DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]),
1315 Css(&'a str),
1318}
1319
1320fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
1322where
1323 W: Write,
1324{
1325 if !*is_first_serialization {
1326 dest.write_char(' ')
1327 } else {
1328 *is_first_serialization = false;
1329 Ok(())
1330 }
1331}
1332
1333pub fn append_declaration_value<'a, 'b: 'a>(
1335 dest: &mut CssStringWriter,
1336 appendable_value: AppendableValue<'a, 'b>,
1337) -> fmt::Result {
1338 match appendable_value {
1339 AppendableValue::Css(css) => dest.write_str(css),
1340 AppendableValue::Declaration(decl) => decl.to_css(dest),
1341 AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
1342 shorthand.longhands_to_css(decls, dest)
1343 },
1344 }
1345}
1346
1347pub fn append_serialization<'a, 'b: 'a, N>(
1349 dest: &mut CssStringWriter,
1350 property_name: &N,
1351 appendable_value: AppendableValue<'a, 'b>,
1352 importance: Importance,
1353 is_first_serialization: &mut bool,
1354) -> fmt::Result
1355where
1356 N: ToCss,
1357{
1358 handle_first_serialization(dest, is_first_serialization)?;
1359
1360 property_name.to_css(&mut CssWriter::new(dest))?;
1361 dest.write_str(": ")?;
1362
1363 append_declaration_value(dest, appendable_value)?;
1364
1365 if importance.important() {
1366 dest.write_str(" !important")?;
1367 }
1368
1369 dest.write_char(';')
1370}
1371
1372#[inline]
1377pub fn parse_style_attribute(
1378 input: &str,
1379 url_data: &UrlExtraData,
1380 error_reporter: Option<&dyn ParseErrorReporter>,
1381 quirks_mode: QuirksMode,
1382 rule_type: CssRuleType,
1383) -> PropertyDeclarationBlock {
1384 let context = ParserContext::new(
1385 Origin::Author,
1386 url_data,
1387 Some(rule_type),
1388 ParsingMode::DEFAULT,
1389 quirks_mode,
1390 Default::default(),
1391 error_reporter,
1392 None,
1393 );
1394
1395 let mut input = ParserInput::new(input);
1396 parse_property_declaration_list(&context, &mut Parser::new(&mut input), &[])
1397}
1398
1399#[inline]
1404pub fn parse_one_declaration_into(
1405 declarations: &mut SourcePropertyDeclaration,
1406 id: PropertyId,
1407 input: &str,
1408 origin: Origin,
1409 url_data: &UrlExtraData,
1410 error_reporter: Option<&dyn ParseErrorReporter>,
1411 parsing_mode: ParsingMode,
1412 quirks_mode: QuirksMode,
1413 rule_type: CssRuleType,
1414) -> Result<(), ()> {
1415 let context = ParserContext::new(
1416 origin,
1417 url_data,
1418 Some(rule_type),
1419 parsing_mode,
1420 quirks_mode,
1421 Default::default(),
1422 error_reporter,
1423 None,
1424 );
1425
1426 let property_id_for_error_reporting = if context.error_reporting_enabled() {
1427 Some(id.clone())
1428 } else {
1429 None
1430 };
1431
1432 let mut input = ParserInput::new(input);
1433 let mut parser = Parser::new(&mut input);
1434 let start_position = parser.position();
1435 parser
1436 .parse_entirely(|parser| {
1437 PropertyDeclaration::parse_into(declarations, id, &context, parser)
1438 })
1439 .map_err(|err| {
1440 if context.error_reporting_enabled() {
1441 report_one_css_error(
1442 &context,
1443 None,
1444 &[],
1445 err,
1446 parser.slice_from(start_position),
1447 property_id_for_error_reporting,
1448 )
1449 }
1450 })
1451}
1452
1453struct PropertyDeclarationParser<'a, 'b: 'a, 'i> {
1455 context: &'a ParserContext<'b>,
1456 state: &'a mut DeclarationParserState<'i>,
1457}
1458
1459#[derive(Default)]
1463pub struct DeclarationParserState<'i> {
1464 output_block: PropertyDeclarationBlock,
1466 declarations: SourcePropertyDeclaration,
1469 importance: Importance,
1471 errors: SmallParseErrorVec<'i>,
1473 first_declaration_start: SourceLocation,
1475 last_parsed_property_id: Option<PropertyId>,
1477}
1478
1479impl<'i> DeclarationParserState<'i> {
1480 pub fn first_declaration_start(&self) -> SourceLocation {
1482 self.first_declaration_start
1483 }
1484
1485 pub fn has_parsed_declarations(&self) -> bool {
1487 !self.output_block.is_empty()
1488 }
1489
1490 pub fn take_declarations(&mut self) -> PropertyDeclarationBlock {
1492 std::mem::take(&mut self.output_block)
1493 }
1494
1495 pub fn parse_value<'t>(
1497 &mut self,
1498 context: &ParserContext,
1499 name: CowRcStr<'i>,
1500 input: &mut Parser<'i, 't>,
1501 declaration_start: &ParserState,
1502 ) -> Result<(), ParseError<'i>> {
1503 let id = match PropertyId::parse(&name, context) {
1504 Ok(id) => id,
1505 Err(..) => {
1506 return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
1507 },
1508 };
1509 if context.error_reporting_enabled() {
1510 self.last_parsed_property_id = Some(id.clone());
1511 }
1512 input.parse_until_before(Delimiter::Bang, |input| {
1513 PropertyDeclaration::parse_into(&mut self.declarations, id, context, input)
1514 })?;
1515 self.importance = match input.try_parse(parse_important) {
1516 Ok(()) => {
1517 if !context.allows_important_declarations() {
1518 return Err(
1519 input.new_custom_error(StyleParseErrorKind::UnexpectedImportantDeclaration)
1520 );
1521 }
1522 Importance::Important
1523 },
1524 Err(_) => Importance::Normal,
1525 };
1526 input.expect_exhausted()?;
1528 let has_parsed_declarations = self.has_parsed_declarations();
1529 self.output_block
1530 .extend(self.declarations.drain(), self.importance);
1531 self.last_parsed_property_id = None;
1535
1536 if !has_parsed_declarations {
1537 self.first_declaration_start = declaration_start.source_location();
1538 }
1539
1540 Ok(())
1541 }
1542
1543 #[inline]
1545 pub fn report_errors_if_needed(
1546 &mut self,
1547 context: &ParserContext,
1548 selectors: &[SelectorList<SelectorImpl>],
1549 ) {
1550 if self.errors.is_empty() {
1551 return;
1552 }
1553 self.do_report_css_errors(context, selectors);
1554 }
1555
1556 #[cold]
1557 fn do_report_css_errors(
1558 &mut self,
1559 context: &ParserContext,
1560 selectors: &[SelectorList<SelectorImpl>],
1561 ) {
1562 for (error, slice, property) in self.errors.drain(..) {
1563 report_one_css_error(
1564 context,
1565 Some(&self.output_block),
1566 selectors,
1567 error,
1568 slice,
1569 property,
1570 )
1571 }
1572 }
1573
1574 #[inline]
1576 pub fn did_error(&mut self, context: &ParserContext, error: ParseError<'i>, slice: &'i str) {
1577 self.declarations.clear();
1578 if !context.error_reporting_enabled() {
1579 return;
1580 }
1581 let property = self.last_parsed_property_id.take();
1582 self.errors.push((error, slice, property));
1583 }
1584}
1585
1586impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1588 type Prelude = ();
1589 type AtRule = ();
1590 type Error = StyleParseErrorKind<'i>;
1591}
1592
1593impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1595 type Prelude = ();
1596 type QualifiedRule = ();
1597 type Error = StyleParseErrorKind<'i>;
1598}
1599
1600fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
1602 (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
1603}
1604
1605impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1606 type Declaration = ();
1607 type Error = StyleParseErrorKind<'i>;
1608
1609 fn parse_value<'t>(
1610 &mut self,
1611 name: CowRcStr<'i>,
1612 input: &mut Parser<'i, 't>,
1613 declaration_start: &ParserState,
1614 ) -> Result<(), ParseError<'i>> {
1615 self.state
1616 .parse_value(self.context, name, input, declaration_start)
1617 }
1618}
1619
1620impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>>
1621 for PropertyDeclarationParser<'a, 'b, 'i>
1622{
1623 fn parse_declarations(&self) -> bool {
1624 true
1625 }
1626 fn parse_qualified(&self) -> bool {
1628 false
1629 }
1630}
1631
1632type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
1633
1634fn alias_of_known_property(name: &str) -> Option<PropertyId> {
1635 let mut prefixed = String::with_capacity(name.len() + 5);
1636 prefixed.push_str("-moz-");
1637 prefixed.push_str(name);
1638 PropertyId::parse_enabled_for_all_content(&prefixed).ok()
1639}
1640
1641#[cold]
1642fn report_one_css_error<'i>(
1643 context: &ParserContext,
1644 block: Option<&PropertyDeclarationBlock>,
1645 selectors: &[SelectorList<SelectorImpl>],
1646 mut error: ParseError<'i>,
1647 slice: &str,
1648 property: Option<PropertyId>,
1649) {
1650 debug_assert!(context.error_reporting_enabled());
1651
1652 fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
1653 match property.as_shorthand() {
1654 Ok(id) => id
1655 .longhands()
1656 .all(|longhand| block.contains(PropertyDeclarationId::Longhand(longhand))),
1657 Err(longhand_or_custom) => block.contains(longhand_or_custom),
1658 }
1659 }
1660
1661 if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(ref name)) = error.kind {
1662 if is_non_mozilla_vendor_identifier(name) {
1663 return;
1666 }
1667 if let Some(alias) = alias_of_known_property(name) {
1668 if let Some(block) = block {
1672 if all_properties_in_block(block, &alias) {
1673 return;
1674 }
1675 }
1676 }
1677 }
1678
1679 if let Some(ref property) = property {
1680 if let Some(block) = block {
1681 if all_properties_in_block(block, property) {
1682 return;
1683 }
1684 }
1685 if !matches!(
1689 error.kind,
1690 ParseErrorKind::Custom(StyleParseErrorKind::UnexpectedImportantDeclaration)
1691 ) {
1692 error = match *property {
1693 PropertyId::Custom(ref c) => {
1694 StyleParseErrorKind::new_invalid(format!("--{}", c), error)
1695 },
1696 _ => StyleParseErrorKind::new_invalid(
1697 property.non_custom_id().unwrap().name(),
1698 error,
1699 ),
1700 };
1701 }
1702 }
1703
1704 let location = error.location;
1705 let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
1706 context.log_css_error(location, error);
1707}
1708
1709pub fn parse_property_declaration_list(
1712 context: &ParserContext,
1713 input: &mut Parser,
1714 selectors: &[SelectorList<SelectorImpl>],
1715) -> PropertyDeclarationBlock {
1716 let mut state = DeclarationParserState::default();
1717 let mut parser = PropertyDeclarationParser {
1718 context,
1719 state: &mut state,
1720 };
1721 let mut iter = RuleBodyParser::new(input, &mut parser);
1722 while let Some(declaration) = iter.next() {
1723 match declaration {
1724 Ok(()) => {},
1725 Err((error, slice)) => iter.parser.state.did_error(context, error, slice),
1726 }
1727 }
1728 parser.state.report_errors_if_needed(context, selectors);
1729 state.output_block
1730}