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::error_reporting::{ContextualParseError, ParseErrorReporter};
18use crate::parser::ParserContext;
19use crate::properties::{
20 animated_properties::{AnimationValue, AnimationValueMap},
21 StyleBuilder,
22};
23use crate::rule_cache::RuleCacheConditions;
24use crate::selector_map::PrecomputedHashSet;
25use crate::selector_parser::SelectorImpl;
26use crate::shared_lock::Locked;
27use crate::str::{CssString, CssStringWriter};
28use crate::stylesheets::container_rule::ContainerSizeQuery;
29use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
30use crate::stylist::Stylist;
31use crate::values::computed::Context;
32use cssparser::{
33 parse_important, AtRuleParser, CowRcStr, DeclarationParser, Delimiter, ParseErrorKind, Parser,
34 ParserInput, ParserState, QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser,
35 SourceLocation,
36};
37use itertools::Itertools;
38use selectors::SelectorList;
39use servo_arc::Arc;
40use smallbitvec::SmallBitVec;
41use smallvec::SmallVec;
42use std::fmt::{self, Write};
43use std::iter::Zip;
44use std::slice::Iter;
45use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
46use thin_vec::ThinVec;
47
48#[derive(Default)]
50pub struct AnimationDeclarations {
51 pub animations: Option<Arc<Locked<PropertyDeclarationBlock>>>,
53 pub transitions: Option<Arc<Locked<PropertyDeclarationBlock>>>,
55}
56
57impl AnimationDeclarations {
58 pub fn is_empty(&self) -> bool {
60 self.animations.is_none() && self.transitions.is_none()
61 }
62}
63
64#[derive(Clone, Copy, Debug, Eq, PartialEq)]
67enum DeclarationUpdate {
68 None,
70 Append,
72 UpdateInPlace { pos: usize },
74 AppendAndRemove { pos: usize },
77}
78
79#[derive(Default)]
82pub struct SourcePropertyDeclarationUpdate {
83 updates: SubpropertiesVec<DeclarationUpdate>,
84 new_count: usize,
85 any_removal: bool,
86}
87
88#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
92pub enum Importance {
93 Normal,
95
96 Important,
98}
99
100impl Default for Importance {
101 fn default() -> Self {
102 Self::Normal
103 }
104}
105
106impl Importance {
107 pub fn important(self) -> bool {
109 match self {
110 Self::Normal => false,
111 Self::Important => true,
112 }
113 }
114}
115
116#[derive(Clone, Debug, ToShmem, Default, MallocSizeOf)]
118pub struct PropertyDeclarationIdSet {
119 longhands: LonghandIdSet,
120 custom: PrecomputedHashSet<custom_properties::Name>,
121}
122
123impl PropertyDeclarationIdSet {
124 pub fn insert(&mut self, id: PropertyDeclarationId) -> bool {
126 match id {
127 PropertyDeclarationId::Longhand(id) => {
128 if self.longhands.contains(id) {
129 return false;
130 }
131 self.longhands.insert(id);
132 return true;
133 },
134 PropertyDeclarationId::Custom(name) => self.custom.insert((*name).clone()),
135 }
136 }
137
138 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
140 match id {
141 PropertyDeclarationId::Longhand(id) => self.longhands.contains(id),
142 PropertyDeclarationId::Custom(name) => self.custom.contains(name),
143 }
144 }
145
146 pub fn remove(&mut self, id: PropertyDeclarationId) {
148 match id {
149 PropertyDeclarationId::Longhand(id) => self.longhands.remove(id),
150 PropertyDeclarationId::Custom(name) => {
151 self.custom.remove(name);
152 },
153 }
154 }
155
156 pub fn clear(&mut self) {
158 self.longhands.clear();
159 self.custom.clear();
160 }
161
162 #[inline]
164 pub fn is_empty(&self) -> bool {
165 self.longhands.is_empty() && self.custom.is_empty()
166 }
167 #[inline]
169 pub fn contains_any_reset(&self) -> bool {
170 self.longhands.contains_any_reset()
171 }
172
173 #[inline]
175 pub fn contains_all_longhands(&self, longhands: &LonghandIdSet) -> bool {
176 self.longhands.contains_all(longhands)
177 }
178
179 #[inline]
181 pub fn contains_all(&self, properties: &PropertyDeclarationIdSet) -> bool {
182 if !self.longhands.contains_all(&properties.longhands) {
183 return false;
184 }
185 if properties.custom.len() > self.custom.len() {
186 return false;
187 }
188 properties
189 .custom
190 .iter()
191 .all(|item| self.custom.contains(item))
192 }
193
194 pub fn iter(&self) -> PropertyDeclarationIdSetIterator {
196 PropertyDeclarationIdSetIterator {
197 longhands: self.longhands.iter(),
198 custom: self.custom.iter(),
199 }
200 }
201}
202
203pub struct PropertyDeclarationIdSetIterator<'a> {
205 longhands: LonghandIdSetIterator<'a>,
206 custom: std::collections::hash_set::Iter<'a, custom_properties::Name>,
207}
208
209impl<'a> Iterator for PropertyDeclarationIdSetIterator<'a> {
210 type Item = PropertyDeclarationId<'a>;
211
212 fn next(&mut self) -> Option<Self::Item> {
213 match self.longhands.next() {
217 Some(id) => Some(PropertyDeclarationId::Longhand(id)),
218 None => match self.custom.next() {
219 Some(a) => Some(PropertyDeclarationId::Custom(a)),
220 None => None,
221 },
222 }
223 }
224}
225
226#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
228#[derive(Clone, ToShmem, Default)]
229pub struct PropertyDeclarationBlock {
230 declarations: ThinVec<PropertyDeclaration>,
234
235 declarations_importance: SmallBitVec,
237
238 property_ids: PropertyDeclarationIdSet,
240}
241
242pub struct DeclarationImportanceIterator<'a> {
244 iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
245}
246
247impl<'a> Default for DeclarationImportanceIterator<'a> {
248 fn default() -> Self {
249 Self {
250 iter: [].iter().zip(smallbitvec::Iter::default()),
251 }
252 }
253}
254
255impl<'a> DeclarationImportanceIterator<'a> {
256 fn new(declarations: &'a [PropertyDeclaration], important: &'a SmallBitVec) -> Self {
258 DeclarationImportanceIterator {
259 iter: declarations.iter().zip(important.iter()),
260 }
261 }
262}
263
264impl<'a> Iterator for DeclarationImportanceIterator<'a> {
265 type Item = (&'a PropertyDeclaration, Importance);
266
267 #[inline]
268 fn next(&mut self) -> Option<Self::Item> {
269 self.iter.next().map(|(decl, important)| {
270 (
271 decl,
272 if important {
273 Importance::Important
274 } else {
275 Importance::Normal
276 },
277 )
278 })
279 }
280
281 #[inline]
282 fn size_hint(&self) -> (usize, Option<usize>) {
283 self.iter.size_hint()
284 }
285}
286
287impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
288 #[inline(always)]
289 fn next_back(&mut self) -> Option<Self::Item> {
290 self.iter.next_back().map(|(decl, important)| {
291 (
292 decl,
293 if important {
294 Importance::Important
295 } else {
296 Importance::Normal
297 },
298 )
299 })
300 }
301}
302
303pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> {
305 iter: DeclarationImportanceIterator<'a>,
306 context: &'cx mut Context<'cx_a>,
307 style: &'a ComputedValues,
308 default_values: &'a ComputedValues,
309}
310
311impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
312 fn new(
313 declarations: &'a PropertyDeclarationBlock,
314 context: &'cx mut Context<'cx_a>,
315 style: &'a ComputedValues,
316 default_values: &'a ComputedValues,
317 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
318 AnimationValueIterator {
319 iter: declarations.declaration_importance_iter(),
320 context,
321 style,
322 default_values,
323 }
324 }
325}
326
327impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
328 type Item = AnimationValue;
329 #[inline]
330 fn next(&mut self) -> Option<Self::Item> {
331 loop {
332 let (decl, importance) = self.iter.next()?;
333
334 if importance.important() {
335 continue;
336 }
337
338 let animation = AnimationValue::from_declaration(
339 decl,
340 &mut self.context,
341 self.style,
342 self.default_values,
343 );
344
345 if let Some(anim) = animation {
346 return Some(anim);
347 }
348 }
349 }
350}
351
352impl fmt::Debug for PropertyDeclarationBlock {
353 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
354 self.declarations.fmt(f)
355 }
356}
357
358impl PropertyDeclarationBlock {
359 #[inline]
361 pub fn len(&self) -> usize {
362 self.declarations.len()
363 }
364
365 #[inline]
367 pub fn is_empty(&self) -> bool {
368 self.declarations.is_empty()
369 }
370
371 #[inline]
373 pub fn new() -> Self {
374 PropertyDeclarationBlock {
375 declarations: ThinVec::new(),
376 declarations_importance: SmallBitVec::new(),
377 property_ids: PropertyDeclarationIdSet::default(),
378 }
379 }
380
381 pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
383 let mut property_ids = PropertyDeclarationIdSet::default();
384 property_ids.insert(declaration.id());
385 let mut declarations = ThinVec::with_capacity(1);
386 declarations.push(declaration);
387 PropertyDeclarationBlock {
388 declarations,
389 declarations_importance: SmallBitVec::from_elem(1, importance.important()),
390 property_ids,
391 }
392 }
393
394 #[inline]
396 pub fn declarations(&self) -> &[PropertyDeclaration] {
397 &self.declarations
398 }
399
400 #[inline]
402 pub fn declarations_importance(&self) -> &SmallBitVec {
403 &self.declarations_importance
404 }
405
406 #[inline]
408 pub fn declaration_importance_iter(&self) -> DeclarationImportanceIterator {
409 DeclarationImportanceIterator::new(&self.declarations, &self.declarations_importance)
410 }
411
412 #[inline]
414 pub fn normal_declaration_iter<'a>(
415 &'a self,
416 ) -> impl DoubleEndedIterator<Item = &'a PropertyDeclaration> {
417 self.declaration_importance_iter()
418 .filter(|(_, importance)| !importance.important())
419 .map(|(declaration, _)| declaration)
420 }
421
422 #[inline]
424 pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>(
425 &'a self,
426 context: &'cx mut Context<'cx_a>,
427 style: &'a ComputedValues,
428 default_values: &'a ComputedValues,
429 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
430 AnimationValueIterator::new(self, context, style, default_values)
431 }
432
433 #[inline]
438 pub fn any_important(&self) -> bool {
439 !self.declarations_importance.all_false()
440 }
441
442 #[inline]
447 pub fn any_normal(&self) -> bool {
448 !self.declarations_importance.all_true()
449 }
450
451 #[inline]
454 pub fn property_ids(&self) -> &PropertyDeclarationIdSet {
455 &self.property_ids
456 }
457
458 #[inline]
460 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
461 self.property_ids.contains(id)
462 }
463
464 #[inline]
466 pub fn contains_any_reset(&self) -> bool {
467 self.property_ids.contains_any_reset()
468 }
469
470 #[inline]
475 pub fn get(
476 &self,
477 property: PropertyDeclarationId,
478 ) -> Option<(&PropertyDeclaration, Importance)> {
479 if !self.contains(property) {
480 return None;
481 }
482 self.declaration_importance_iter()
483 .find(|(declaration, _)| declaration.id() == property)
484 }
485
486 pub fn shorthand_to_css(
489 &self,
490 shorthand: ShorthandId,
491 dest: &mut CssStringWriter,
492 ) -> fmt::Result {
493 let mut list = SmallVec::<[&_; 10]>::new();
496 let mut important_count = 0;
497
498 for longhand in shorthand.longhands() {
500 let declaration = self.get(PropertyDeclarationId::Longhand(longhand));
502
503 match declaration {
505 Some((declaration, importance)) => {
506 list.push(declaration);
507 if importance.important() {
508 important_count += 1;
509 }
510 },
511 None => return Ok(()),
512 }
513 }
514
515 if important_count > 0 && important_count != list.len() {
518 return Ok(());
519 }
520
521 match shorthand.get_shorthand_appendable_value(&list) {
525 Some(appendable_value) => append_declaration_value(dest, appendable_value),
526 None => return Ok(()),
527 }
528 }
529
530 pub fn property_value_to_css(
534 &self,
535 property: &PropertyId,
536 dest: &mut CssStringWriter,
537 ) -> fmt::Result {
538 let longhand_or_custom = match property.as_shorthand() {
542 Ok(shorthand) => return self.shorthand_to_css(shorthand, dest),
543 Err(longhand_or_custom) => longhand_or_custom,
544 };
545
546 if let Some((value, _importance)) = self.get(longhand_or_custom) {
547 value.to_css(dest)
549 } else {
550 Ok(())
552 }
553 }
554
555 pub fn property_priority(&self, property: &PropertyId) -> Importance {
557 match property.as_shorthand() {
561 Ok(shorthand) => {
562 if shorthand.longhands().all(|l| {
564 self.get(PropertyDeclarationId::Longhand(l))
565 .map_or(false, |(_, importance)| importance.important())
566 }) {
567 Importance::Important
568 } else {
569 Importance::Normal
570 }
571 },
572 Err(longhand_or_custom) => {
573 self.get(longhand_or_custom)
575 .map_or(Importance::Normal, |(_, importance)| importance)
576 },
577 }
578 }
579
580 pub fn extend(
585 &mut self,
586 mut drain: SourcePropertyDeclarationDrain,
587 importance: Importance,
588 ) -> bool {
589 let all_shorthand_len = match drain.all_shorthand {
590 AllShorthand::NotSet => 0,
591 AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
592 property_counts::ALL_SHORTHAND_EXPANDED
593 },
594 };
595 let push_calls_count = drain.declarations.len() + all_shorthand_len;
596
597 self.declarations.reserve(push_calls_count);
599
600 let mut changed = false;
601 for decl in &mut drain.declarations {
602 changed |= self.push(decl, importance);
603 }
604 drain
605 .all_shorthand
606 .declarations()
607 .fold(changed, |changed, decl| {
608 changed | self.push(decl, importance)
609 })
610 }
611
612 pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
618 let id = declaration.id();
619 if !self.property_ids.insert(id) {
620 let mut index_to_remove = None;
621 for (i, slot) in self.declarations.iter_mut().enumerate() {
622 if slot.id() != id {
623 continue;
624 }
625
626 let important = self.declarations_importance[i];
627
628 if important && !importance.important() {
631 return false;
632 }
633
634 index_to_remove = Some(i);
635 break;
636 }
637
638 if let Some(index) = index_to_remove {
639 self.declarations.remove(index);
640 self.declarations_importance.remove(index);
641 self.declarations.push(declaration);
642 self.declarations_importance.push(importance.important());
643 return true;
644 }
645 }
646
647 self.declarations.push(declaration);
648 self.declarations_importance.push(importance.important());
649 true
650 }
651
652 pub fn prepare_for_update(
656 &self,
657 source_declarations: &SourcePropertyDeclaration,
658 importance: Importance,
659 updates: &mut SourcePropertyDeclarationUpdate,
660 ) -> bool {
661 debug_assert!(updates.updates.is_empty());
662 if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
664 debug_assert!(source_declarations.declarations.is_empty());
665 return source_declarations
666 .all_shorthand
667 .declarations()
668 .any(|decl| {
669 !self.contains(decl.id())
670 || self
671 .declarations
672 .iter()
673 .enumerate()
674 .find(|&(_, ref d)| d.id() == decl.id())
675 .map_or(true, |(i, d)| {
676 let important = self.declarations_importance[i];
677 *d != decl || important != importance.important()
678 })
679 });
680 }
681 let mut any_update = false;
683 let new_count = &mut updates.new_count;
684 let any_removal = &mut updates.any_removal;
685 let updates = &mut updates.updates;
686 updates.extend(
687 source_declarations
688 .declarations
689 .iter()
690 .map(|declaration| {
691 if !self.contains(declaration.id()) {
692 return DeclarationUpdate::Append;
693 }
694 let longhand_id = declaration.id().as_longhand();
695 if let Some(longhand_id) = longhand_id {
696 if let Some(logical_group) = longhand_id.logical_group() {
697 let mut needs_append = false;
698 for (pos, decl) in self.declarations.iter().enumerate().rev() {
699 let id = match decl.id().as_longhand() {
700 Some(id) => id,
701 None => continue,
702 };
703 if id == longhand_id {
704 if needs_append {
705 return DeclarationUpdate::AppendAndRemove { pos };
706 }
707 let important = self.declarations_importance[pos];
708 if decl == declaration && important == importance.important() {
709 return DeclarationUpdate::None;
710 }
711 return DeclarationUpdate::UpdateInPlace { pos };
712 }
713 if !needs_append
714 && id.logical_group() == Some(logical_group)
715 && id.is_logical() != longhand_id.is_logical()
716 {
717 needs_append = true;
718 }
719 }
720 unreachable!("Longhand should be found in loop above");
721 }
722 }
723 self.declarations
724 .iter()
725 .enumerate()
726 .find(|&(_, ref decl)| decl.id() == declaration.id())
727 .map_or(DeclarationUpdate::Append, |(pos, decl)| {
728 let important = self.declarations_importance[pos];
729 if decl == declaration && important == importance.important() {
730 DeclarationUpdate::None
731 } else {
732 DeclarationUpdate::UpdateInPlace { pos }
733 }
734 })
735 })
736 .inspect(|update| {
737 if matches!(update, DeclarationUpdate::None) {
738 return;
739 }
740 any_update = true;
741 match update {
742 DeclarationUpdate::Append => {
743 *new_count += 1;
744 },
745 DeclarationUpdate::AppendAndRemove { .. } => {
746 *any_removal = true;
747 },
748 _ => {},
749 }
750 }),
751 );
752 any_update
753 }
754
755 pub fn update(
757 &mut self,
758 drain: SourcePropertyDeclarationDrain,
759 importance: Importance,
760 updates: &mut SourcePropertyDeclarationUpdate,
761 ) {
762 let important = importance.important();
763 if !matches!(drain.all_shorthand, AllShorthand::NotSet) {
764 debug_assert!(updates.updates.is_empty());
765 for decl in drain.all_shorthand.declarations() {
766 let id = decl.id();
767 if self.property_ids.insert(id) {
768 self.declarations.push(decl);
769 self.declarations_importance.push(important);
770 } else {
771 let (idx, slot) = self
772 .declarations
773 .iter_mut()
774 .enumerate()
775 .find(|&(_, ref d)| d.id() == decl.id())
776 .unwrap();
777 *slot = decl;
778 self.declarations_importance.set(idx, important);
779 }
780 }
781 return;
782 }
783
784 self.declarations.reserve(updates.new_count);
785 if updates.any_removal {
786 struct UpdateOrRemoval<'a> {
788 item: &'a mut DeclarationUpdate,
789 pos: usize,
790 remove: bool,
791 }
792 let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
793 .updates
794 .iter_mut()
795 .filter_map(|item| {
796 let (pos, remove) = match *item {
797 DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
798 DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
799 _ => return None,
800 };
801 Some(UpdateOrRemoval { item, pos, remove })
802 })
803 .collect();
804 updates_and_removals.sort_unstable_by_key(|update| update.pos);
807 updates_and_removals
808 .iter()
809 .rev()
810 .filter(|update| update.remove)
811 .for_each(|update| {
812 self.declarations.remove(update.pos);
813 self.declarations_importance.remove(update.pos);
814 });
815 let mut removed_count = 0;
817 for update in updates_and_removals.iter_mut() {
818 if update.remove {
819 removed_count += 1;
820 continue;
821 }
822 debug_assert_eq!(
823 *update.item,
824 DeclarationUpdate::UpdateInPlace { pos: update.pos }
825 );
826 *update.item = DeclarationUpdate::UpdateInPlace {
827 pos: update.pos - removed_count,
828 };
829 }
830 }
831 for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
833 match *update {
834 DeclarationUpdate::None => {},
835 DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
836 self.property_ids.insert(decl.id());
837 self.declarations.push(decl);
838 self.declarations_importance.push(important);
839 },
840 DeclarationUpdate::UpdateInPlace { pos } => {
841 self.declarations[pos] = decl;
842 self.declarations_importance.set(pos, important);
843 },
844 }
845 }
846 updates.updates.clear();
847 }
848
849 #[inline]
852 pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
853 if let Err(longhand_or_custom) = property.as_shorthand() {
854 if !self.contains(longhand_or_custom) {
855 return None;
856 }
857 }
858
859 self.declarations
860 .iter()
861 .position(|declaration| declaration.id().is_or_is_longhand_of(property))
862 }
863
864 #[inline]
866 fn remove_declaration_at(&mut self, i: usize) {
867 self.property_ids.remove(self.declarations[i].id());
868 self.declarations_importance.remove(i);
869 self.declarations.remove(i);
870 }
871
872 #[inline]
874 pub fn clear(&mut self) {
875 self.declarations_importance.clear();
876 self.declarations.clear();
877 self.property_ids.clear();
878 }
879
880 #[inline]
885 pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
886 debug_assert_eq!(
887 Some(first_declaration),
888 self.first_declaration_to_remove(property)
889 );
890 debug_assert!(self.declarations[first_declaration]
891 .id()
892 .is_or_is_longhand_of(property));
893
894 self.remove_declaration_at(first_declaration);
895
896 let shorthand = match property.as_shorthand() {
897 Ok(s) => s,
898 Err(_longhand_or_custom) => return,
899 };
900
901 let mut i = first_declaration;
902 let mut len = self.len();
903 while i < len {
904 if !self.declarations[i].id().is_longhand_of(shorthand) {
905 i += 1;
906 continue;
907 }
908
909 self.remove_declaration_at(i);
910 len -= 1;
911 }
912 }
913
914 pub fn single_value_to_css(
916 &self,
917 property: &PropertyId,
918 dest: &mut CssStringWriter,
919 computed_values: Option<&ComputedValues>,
920 stylist: &Stylist,
921 ) -> fmt::Result {
922 if let Ok(shorthand) = property.as_shorthand() {
923 return self.shorthand_to_css(shorthand, dest);
924 }
925
926 let declaration = match self.declarations.get(0) {
929 Some(d) => d,
930 None => return Err(fmt::Error),
931 };
932
933 let mut rule_cache_conditions = RuleCacheConditions::default();
934 let mut context = Context::new(
935 StyleBuilder::new(
936 stylist.device(),
937 Some(stylist),
938 computed_values,
939 None,
940 None,
941 false,
942 ),
943 stylist.quirks_mode(),
944 &mut rule_cache_conditions,
945 ContainerSizeQuery::none(),
946 );
947
948 if let Some(cv) = computed_values {
949 context.builder.custom_properties = cv.custom_properties().clone();
950 };
951
952 match (declaration, computed_values) {
953 (&PropertyDeclaration::WithVariables(ref declaration), Some(_)) => declaration
961 .value
962 .substitute_variables(
963 declaration.id,
964 &context.builder.custom_properties,
965 stylist,
966 &context,
967 &mut Default::default(),
968 )
969 .to_css(dest),
970 (ref d, _) => d.to_css(dest),
971 }
972 }
973
974 pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
976 let len = animation_value_map.len();
977 let mut declarations = ThinVec::with_capacity(len);
978 let mut property_ids = PropertyDeclarationIdSet::default();
979
980 for (property, animation_value) in animation_value_map.iter() {
981 property_ids.insert(property.as_borrowed());
982 declarations.push(animation_value.uncompute());
983 }
984
985 PropertyDeclarationBlock {
986 declarations,
987 property_ids,
988 declarations_importance: SmallBitVec::from_elem(len, false),
989 }
990 }
991
992 pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
995 if let Err(longhand_or_custom) = property.as_shorthand() {
996 if !self.property_ids.contains(longhand_or_custom) {
997 return false;
998 }
999 }
1000 self.declarations.iter().any(|decl| {
1001 decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
1002 })
1003 }
1004
1005 pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
1011 let mut is_first_serialization = true; let mut already_serialized = NonCustomPropertyIdSet::new();
1023
1024 'declaration_loop: for (declaration, importance) in self.declaration_importance_iter() {
1026 let property = declaration.id();
1028 let longhand_id = match property {
1029 PropertyDeclarationId::Longhand(id) => id,
1030 PropertyDeclarationId::Custom(..) => {
1031 append_serialization(
1036 dest,
1037 &property,
1038 AppendableValue::Declaration(declaration),
1039 importance,
1040 &mut is_first_serialization,
1041 )?;
1042 continue;
1043 },
1044 };
1045
1046 if already_serialized.contains(longhand_id.into()) {
1048 continue;
1049 }
1050
1051 for shorthand in longhand_id.shorthands() {
1053 if already_serialized.contains(shorthand.into()) {
1055 continue;
1056 }
1057 already_serialized.insert(shorthand.into());
1058
1059 if shorthand.is_legacy_shorthand() {
1060 continue;
1061 }
1062
1063 let longhands = {
1070 let mut ids = LonghandIdSet::new();
1073 for longhand in shorthand.longhands() {
1074 ids.insert(longhand);
1075 }
1076 ids
1077 };
1078
1079 if !self.property_ids.contains_all_longhands(&longhands) {
1084 continue;
1085 }
1086
1087 let mut current_longhands = SmallVec::<[&_; 10]>::new();
1090 let mut logical_groups = LogicalGroupSet::new();
1091 let mut saw_one = false;
1092 let mut logical_mismatch = false;
1093 let mut seen = LonghandIdSet::new();
1094 let mut important_count = 0;
1095
1096 for (declaration, importance) in self.declaration_importance_iter() {
1100 let longhand = match declaration.id() {
1101 PropertyDeclarationId::Longhand(id) => id,
1102 PropertyDeclarationId::Custom(..) => continue,
1103 };
1104
1105 if longhands.contains(longhand) {
1106 saw_one = true;
1107 if importance.important() {
1108 important_count += 1;
1109 }
1110 current_longhands.push(declaration);
1111 if shorthand != ShorthandId::All {
1112 if let Some(g) = longhand.logical_group() {
1115 logical_groups.insert(g);
1116 }
1117 seen.insert(longhand);
1118 if seen == longhands {
1119 break;
1120 }
1121 }
1122 } else if saw_one {
1123 if let Some(g) = longhand.logical_group() {
1124 if logical_groups.contains(g) {
1125 logical_mismatch = true;
1126 break;
1127 }
1128 }
1129 }
1130 }
1131
1132 let is_important = important_count > 0;
1138 if is_important && important_count != current_longhands.len() {
1139 continue;
1140 }
1141
1142 if logical_mismatch {
1150 continue;
1151 }
1152
1153 let importance = if is_important {
1154 Importance::Important
1155 } else {
1156 Importance::Normal
1157 };
1158
1159 let appendable_value =
1163 match shorthand.get_shorthand_appendable_value(¤t_longhands) {
1164 None => continue,
1165 Some(appendable_value) => appendable_value,
1166 };
1167
1168 let mut v = CssString::new();
1171 let value = match appendable_value {
1172 AppendableValue::Css(css) => {
1173 debug_assert!(!css.is_empty());
1174 appendable_value
1175 },
1176 other => {
1177 append_declaration_value(&mut v, other)?;
1178
1179 if v.is_empty() {
1183 continue;
1184 }
1185
1186 AppendableValue::Css({
1187 #[cfg(feature = "gecko")]
1189 unsafe {
1190 v.as_str_unchecked()
1191 }
1192 #[cfg(feature = "servo")]
1193 &v
1194 })
1195 },
1196 };
1197
1198 append_serialization(
1208 dest,
1209 &shorthand,
1210 value,
1211 importance,
1212 &mut is_first_serialization,
1213 )?;
1214
1215 for current_longhand in ¤t_longhands {
1219 let longhand_id = match current_longhand.id() {
1220 PropertyDeclarationId::Longhand(id) => id,
1221 PropertyDeclarationId::Custom(..) => unreachable!(),
1222 };
1223
1224 already_serialized.insert(longhand_id.into());
1226 }
1227
1228 continue 'declaration_loop;
1231 }
1232
1233 append_serialization(
1244 dest,
1245 &property,
1246 AppendableValue::Declaration(declaration),
1247 importance,
1248 &mut is_first_serialization,
1249 )?;
1250
1251 already_serialized.insert(longhand_id.into());
1254 }
1255
1256 Ok(())
1258 }
1259}
1260
1261pub enum AppendableValue<'a, 'b: 'a> {
1264 Declaration(&'a PropertyDeclaration),
1266 DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]),
1271 Css(&'a str),
1274}
1275
1276fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
1278where
1279 W: Write,
1280{
1281 if !*is_first_serialization {
1282 dest.write_char(' ')
1283 } else {
1284 *is_first_serialization = false;
1285 Ok(())
1286 }
1287}
1288
1289pub fn append_declaration_value<'a, 'b: 'a>(
1291 dest: &mut CssStringWriter,
1292 appendable_value: AppendableValue<'a, 'b>,
1293) -> fmt::Result {
1294 match appendable_value {
1295 AppendableValue::Css(css) => dest.write_str(css),
1296 AppendableValue::Declaration(decl) => decl.to_css(dest),
1297 AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
1298 shorthand.longhands_to_css(decls, dest)
1299 },
1300 }
1301}
1302
1303pub fn append_serialization<'a, 'b: 'a, N>(
1305 dest: &mut CssStringWriter,
1306 property_name: &N,
1307 appendable_value: AppendableValue<'a, 'b>,
1308 importance: Importance,
1309 is_first_serialization: &mut bool,
1310) -> fmt::Result
1311where
1312 N: ToCss,
1313{
1314 handle_first_serialization(dest, is_first_serialization)?;
1315
1316 property_name.to_css(&mut CssWriter::new(dest))?;
1317 dest.write_str(": ")?;
1318
1319 append_declaration_value(dest, appendable_value)?;
1320
1321 if importance.important() {
1322 dest.write_str(" !important")?;
1323 }
1324
1325 dest.write_char(';')
1326}
1327
1328#[inline]
1333pub fn parse_style_attribute(
1334 input: &str,
1335 url_data: &UrlExtraData,
1336 error_reporter: Option<&dyn ParseErrorReporter>,
1337 quirks_mode: QuirksMode,
1338 rule_type: CssRuleType,
1339) -> PropertyDeclarationBlock {
1340 let context = ParserContext::new(
1341 Origin::Author,
1342 url_data,
1343 Some(rule_type),
1344 ParsingMode::DEFAULT,
1345 quirks_mode,
1346 Default::default(),
1347 error_reporter,
1348 None,
1349 );
1350
1351 let mut input = ParserInput::new(input);
1352 parse_property_declaration_list(&context, &mut Parser::new(&mut input), &[])
1353}
1354
1355#[inline]
1360pub fn parse_one_declaration_into(
1361 declarations: &mut SourcePropertyDeclaration,
1362 id: PropertyId,
1363 input: &str,
1364 origin: Origin,
1365 url_data: &UrlExtraData,
1366 error_reporter: Option<&dyn ParseErrorReporter>,
1367 parsing_mode: ParsingMode,
1368 quirks_mode: QuirksMode,
1369 rule_type: CssRuleType,
1370) -> Result<(), ()> {
1371 let context = ParserContext::new(
1372 origin,
1373 url_data,
1374 Some(rule_type),
1375 parsing_mode,
1376 quirks_mode,
1377 Default::default(),
1378 error_reporter,
1379 None,
1380 );
1381
1382 let property_id_for_error_reporting = if context.error_reporting_enabled() {
1383 Some(id.clone())
1384 } else {
1385 None
1386 };
1387
1388 let mut input = ParserInput::new(input);
1389 let mut parser = Parser::new(&mut input);
1390 let start_position = parser.position();
1391 parser
1392 .parse_entirely(|parser| {
1393 PropertyDeclaration::parse_into(declarations, id, &context, parser)
1394 })
1395 .map_err(|err| {
1396 if context.error_reporting_enabled() {
1397 report_one_css_error(
1398 &context,
1399 None,
1400 &[],
1401 err,
1402 parser.slice_from(start_position),
1403 property_id_for_error_reporting,
1404 )
1405 }
1406 })
1407}
1408
1409struct PropertyDeclarationParser<'a, 'b: 'a, 'i> {
1411 context: &'a ParserContext<'b>,
1412 state: &'a mut DeclarationParserState<'i>,
1413}
1414
1415#[derive(Default)]
1419pub struct DeclarationParserState<'i> {
1420 output_block: PropertyDeclarationBlock,
1422 declarations: SourcePropertyDeclaration,
1425 importance: Importance,
1427 errors: SmallParseErrorVec<'i>,
1429 first_declaration_start: SourceLocation,
1431 last_parsed_property_id: Option<PropertyId>,
1433}
1434
1435impl<'i> DeclarationParserState<'i> {
1436 pub fn first_declaration_start(&self) -> SourceLocation {
1438 self.first_declaration_start
1439 }
1440
1441 pub fn has_parsed_declarations(&self) -> bool {
1443 !self.output_block.is_empty()
1444 }
1445
1446 pub fn take_declarations(&mut self) -> PropertyDeclarationBlock {
1448 std::mem::take(&mut self.output_block)
1449 }
1450
1451 pub fn parse_value<'t>(
1453 &mut self,
1454 context: &ParserContext,
1455 name: CowRcStr<'i>,
1456 input: &mut Parser<'i, 't>,
1457 declaration_start: &ParserState,
1458 ) -> Result<(), ParseError<'i>> {
1459 let id = match PropertyId::parse(&name, context) {
1460 Ok(id) => id,
1461 Err(..) => {
1462 return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
1463 },
1464 };
1465 if context.error_reporting_enabled() {
1466 self.last_parsed_property_id = Some(id.clone());
1467 }
1468 input.parse_until_before(Delimiter::Bang, |input| {
1469 PropertyDeclaration::parse_into(&mut self.declarations, id, context, input)
1470 })?;
1471 self.importance = match input.try_parse(parse_important) {
1472 Ok(()) => {
1473 if !context.allows_important_declarations() {
1474 return Err(
1475 input.new_custom_error(StyleParseErrorKind::UnexpectedImportantDeclaration)
1476 );
1477 }
1478 Importance::Important
1479 },
1480 Err(_) => Importance::Normal,
1481 };
1482 input.expect_exhausted()?;
1484 let has_parsed_declarations = self.has_parsed_declarations();
1485 self.output_block
1486 .extend(self.declarations.drain(), self.importance);
1487 self.last_parsed_property_id = None;
1491
1492 if !has_parsed_declarations {
1493 self.first_declaration_start = declaration_start.source_location();
1494 }
1495
1496 Ok(())
1497 }
1498
1499 #[inline]
1501 pub fn report_errors_if_needed(
1502 &mut self,
1503 context: &ParserContext,
1504 selectors: &[SelectorList<SelectorImpl>],
1505 ) {
1506 if self.errors.is_empty() {
1507 return;
1508 }
1509 self.do_report_css_errors(context, selectors);
1510 }
1511
1512 #[cold]
1513 fn do_report_css_errors(
1514 &mut self,
1515 context: &ParserContext,
1516 selectors: &[SelectorList<SelectorImpl>],
1517 ) {
1518 for (error, slice, property) in self.errors.drain(..) {
1519 report_one_css_error(
1520 context,
1521 Some(&self.output_block),
1522 selectors,
1523 error,
1524 slice,
1525 property,
1526 )
1527 }
1528 }
1529
1530 #[inline]
1532 pub fn did_error(&mut self, context: &ParserContext, error: ParseError<'i>, slice: &'i str) {
1533 self.declarations.clear();
1534 if !context.error_reporting_enabled() {
1535 return;
1536 }
1537 let property = self.last_parsed_property_id.take();
1538 self.errors.push((error, slice, property));
1539 }
1540}
1541
1542impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1544 type Prelude = ();
1545 type AtRule = ();
1546 type Error = StyleParseErrorKind<'i>;
1547}
1548
1549impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1551 type Prelude = ();
1552 type QualifiedRule = ();
1553 type Error = StyleParseErrorKind<'i>;
1554}
1555
1556fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
1558 (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
1559}
1560
1561impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1562 type Declaration = ();
1563 type Error = StyleParseErrorKind<'i>;
1564
1565 fn parse_value<'t>(
1566 &mut self,
1567 name: CowRcStr<'i>,
1568 input: &mut Parser<'i, 't>,
1569 declaration_start: &ParserState,
1570 ) -> Result<(), ParseError<'i>> {
1571 self.state
1572 .parse_value(self.context, name, input, declaration_start)
1573 }
1574}
1575
1576impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>>
1577 for PropertyDeclarationParser<'a, 'b, 'i>
1578{
1579 fn parse_declarations(&self) -> bool {
1580 true
1581 }
1582 fn parse_qualified(&self) -> bool {
1584 false
1585 }
1586}
1587
1588type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
1589
1590fn alias_of_known_property(name: &str) -> Option<PropertyId> {
1591 let mut prefixed = String::with_capacity(name.len() + 5);
1592 prefixed.push_str("-moz-");
1593 prefixed.push_str(name);
1594 PropertyId::parse_enabled_for_all_content(&prefixed).ok()
1595}
1596
1597#[cold]
1598fn report_one_css_error<'i>(
1599 context: &ParserContext,
1600 block: Option<&PropertyDeclarationBlock>,
1601 selectors: &[SelectorList<SelectorImpl>],
1602 mut error: ParseError<'i>,
1603 slice: &str,
1604 property: Option<PropertyId>,
1605) {
1606 debug_assert!(context.error_reporting_enabled());
1607
1608 fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
1609 match property.as_shorthand() {
1610 Ok(id) => id
1611 .longhands()
1612 .all(|longhand| block.contains(PropertyDeclarationId::Longhand(longhand))),
1613 Err(longhand_or_custom) => block.contains(longhand_or_custom),
1614 }
1615 }
1616
1617 if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(ref name)) = error.kind {
1618 if is_non_mozilla_vendor_identifier(name) {
1619 return;
1622 }
1623 if let Some(alias) = alias_of_known_property(name) {
1624 if let Some(block) = block {
1628 if all_properties_in_block(block, &alias) {
1629 return;
1630 }
1631 }
1632 }
1633 }
1634
1635 if let Some(ref property) = property {
1636 if let Some(block) = block {
1637 if all_properties_in_block(block, property) {
1638 return;
1639 }
1640 }
1641 if !matches!(
1645 error.kind,
1646 ParseErrorKind::Custom(StyleParseErrorKind::UnexpectedImportantDeclaration)
1647 ) {
1648 error = match *property {
1649 PropertyId::Custom(ref c) => {
1650 StyleParseErrorKind::new_invalid(format!("--{}", c), error)
1651 },
1652 _ => StyleParseErrorKind::new_invalid(
1653 property.non_custom_id().unwrap().name(),
1654 error,
1655 ),
1656 };
1657 }
1658 }
1659
1660 let location = error.location;
1661 let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
1662 context.log_css_error(location, error);
1663}
1664
1665pub fn parse_property_declaration_list(
1668 context: &ParserContext,
1669 input: &mut Parser,
1670 selectors: &[SelectorList<SelectorImpl>],
1671) -> PropertyDeclarationBlock {
1672 let mut state = DeclarationParserState::default();
1673 let mut parser = PropertyDeclarationParser {
1674 context,
1675 state: &mut state,
1676 };
1677 let mut iter = RuleBodyParser::new(input, &mut parser);
1678 while let Some(declaration) = iter.next() {
1679 match declaration {
1680 Ok(()) => {},
1681 Err((error, slice)) => iter.parser.state.did_error(context, error, slice),
1682 }
1683 }
1684 parser.state.report_errors_if_needed(context, selectors);
1685 state.output_block
1686}