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, SourceLocation,
35};
36use itertools::Itertools;
37use selectors::SelectorList;
38use servo_arc::Arc;
39use smallbitvec::SmallBitVec;
40use smallvec::SmallVec;
41use std::fmt::{self, Write};
42use std::iter::Zip;
43use std::slice::Iter;
44use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
45use thin_vec::ThinVec;
46
47#[derive(Default)]
49pub struct AnimationDeclarations {
50 pub animations: Option<Arc<Locked<PropertyDeclarationBlock>>>,
52 pub transitions: Option<Arc<Locked<PropertyDeclarationBlock>>>,
54}
55
56impl AnimationDeclarations {
57 pub fn is_empty(&self) -> bool {
59 self.animations.is_none() && self.transitions.is_none()
60 }
61}
62
63#[derive(Clone, Copy, Debug, Eq, PartialEq)]
66enum DeclarationUpdate {
67 None,
69 Append,
71 UpdateInPlace { pos: usize },
73 AppendAndRemove { pos: usize },
76}
77
78#[derive(Default)]
81pub struct SourcePropertyDeclarationUpdate {
82 updates: SubpropertiesVec<DeclarationUpdate>,
83 new_count: usize,
84 any_removal: bool,
85}
86
87#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
91pub enum Importance {
92 Normal,
94
95 Important,
97}
98
99impl Default for Importance {
100 fn default() -> Self {
101 Self::Normal
102 }
103}
104
105impl Importance {
106 pub fn important(self) -> bool {
108 match self {
109 Self::Normal => false,
110 Self::Important => true,
111 }
112 }
113}
114
115#[derive(Clone, Debug, ToShmem, Default, MallocSizeOf)]
117pub struct PropertyDeclarationIdSet {
118 longhands: LonghandIdSet,
119 custom: PrecomputedHashSet<custom_properties::Name>,
120}
121
122impl PropertyDeclarationIdSet {
123 pub fn insert(&mut self, id: PropertyDeclarationId) -> bool {
125 match id {
126 PropertyDeclarationId::Longhand(id) => {
127 if self.longhands.contains(id) {
128 return false;
129 }
130 self.longhands.insert(id);
131 return true;
132 },
133 PropertyDeclarationId::Custom(name) => self.custom.insert((*name).clone()),
134 }
135 }
136
137 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
139 match id {
140 PropertyDeclarationId::Longhand(id) => self.longhands.contains(id),
141 PropertyDeclarationId::Custom(name) => self.custom.contains(name),
142 }
143 }
144
145 pub fn remove(&mut self, id: PropertyDeclarationId) {
147 match id {
148 PropertyDeclarationId::Longhand(id) => self.longhands.remove(id),
149 PropertyDeclarationId::Custom(name) => {
150 self.custom.remove(name);
151 },
152 }
153 }
154
155 pub fn clear(&mut self) {
157 self.longhands.clear();
158 self.custom.clear();
159 }
160
161 #[inline]
163 pub fn is_empty(&self) -> bool {
164 self.longhands.is_empty() && self.custom.is_empty()
165 }
166 #[inline]
168 pub fn contains_any_reset(&self) -> bool {
169 self.longhands.contains_any_reset()
170 }
171
172 #[inline]
174 pub fn contains_all_longhands(&self, longhands: &LonghandIdSet) -> bool {
175 self.longhands.contains_all(longhands)
176 }
177
178 #[inline]
180 pub fn contains_all(&self, properties: &PropertyDeclarationIdSet) -> bool {
181 if !self.longhands.contains_all(&properties.longhands) {
182 return false;
183 }
184 if properties.custom.len() > self.custom.len() {
185 return false;
186 }
187 properties
188 .custom
189 .iter()
190 .all(|item| self.custom.contains(item))
191 }
192
193 pub fn iter(&self) -> PropertyDeclarationIdSetIterator {
195 PropertyDeclarationIdSetIterator {
196 longhands: self.longhands.iter(),
197 custom: self.custom.iter(),
198 }
199 }
200}
201
202pub struct PropertyDeclarationIdSetIterator<'a> {
204 longhands: LonghandIdSetIterator<'a>,
205 custom: std::collections::hash_set::Iter<'a, custom_properties::Name>,
206}
207
208impl<'a> Iterator for PropertyDeclarationIdSetIterator<'a> {
209 type Item = PropertyDeclarationId<'a>;
210
211 fn next(&mut self) -> Option<Self::Item> {
212 match self.longhands.next() {
216 Some(id) => Some(PropertyDeclarationId::Longhand(id)),
217 None => match self.custom.next() {
218 Some(a) => Some(PropertyDeclarationId::Custom(a)),
219 None => None,
220 },
221 }
222 }
223}
224
225#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
227#[derive(Clone, ToShmem, Default)]
228pub struct PropertyDeclarationBlock {
229 declarations: ThinVec<PropertyDeclaration>,
233
234 declarations_importance: SmallBitVec,
236
237 property_ids: PropertyDeclarationIdSet,
239}
240
241pub struct DeclarationImportanceIterator<'a> {
243 iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
244}
245
246impl<'a> Default for DeclarationImportanceIterator<'a> {
247 fn default() -> Self {
248 Self {
249 iter: [].iter().zip(smallbitvec::Iter::default()),
250 }
251 }
252}
253
254impl<'a> DeclarationImportanceIterator<'a> {
255 fn new(declarations: &'a [PropertyDeclaration], important: &'a SmallBitVec) -> Self {
257 DeclarationImportanceIterator {
258 iter: declarations.iter().zip(important.iter()),
259 }
260 }
261}
262
263impl<'a> Iterator for DeclarationImportanceIterator<'a> {
264 type Item = (&'a PropertyDeclaration, Importance);
265
266 #[inline]
267 fn next(&mut self) -> Option<Self::Item> {
268 self.iter.next().map(|(decl, important)| {
269 (
270 decl,
271 if important {
272 Importance::Important
273 } else {
274 Importance::Normal
275 },
276 )
277 })
278 }
279
280 #[inline]
281 fn size_hint(&self) -> (usize, Option<usize>) {
282 self.iter.size_hint()
283 }
284}
285
286impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
287 #[inline(always)]
288 fn next_back(&mut self) -> Option<Self::Item> {
289 self.iter.next_back().map(|(decl, important)| {
290 (
291 decl,
292 if important {
293 Importance::Important
294 } else {
295 Importance::Normal
296 },
297 )
298 })
299 }
300}
301
302pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> {
304 iter: DeclarationImportanceIterator<'a>,
305 context: &'cx mut Context<'cx_a>,
306 style: &'a ComputedValues,
307 default_values: &'a ComputedValues,
308}
309
310impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
311 fn new(
312 declarations: &'a PropertyDeclarationBlock,
313 context: &'cx mut Context<'cx_a>,
314 style: &'a ComputedValues,
315 default_values: &'a ComputedValues,
316 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
317 AnimationValueIterator {
318 iter: declarations.declaration_importance_iter(),
319 context,
320 style,
321 default_values,
322 }
323 }
324}
325
326impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
327 type Item = AnimationValue;
328 #[inline]
329 fn next(&mut self) -> Option<Self::Item> {
330 loop {
331 let (decl, importance) = self.iter.next()?;
332
333 if importance.important() {
334 continue;
335 }
336
337 let animation =
338 AnimationValue::from_declaration(decl, &mut self.context, self.style, self.default_values);
339
340 if let Some(anim) = animation {
341 return Some(anim);
342 }
343 }
344 }
345}
346
347impl fmt::Debug for PropertyDeclarationBlock {
348 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
349 self.declarations.fmt(f)
350 }
351}
352
353impl PropertyDeclarationBlock {
354 #[inline]
356 pub fn len(&self) -> usize {
357 self.declarations.len()
358 }
359
360 #[inline]
362 pub fn is_empty(&self) -> bool {
363 self.declarations.is_empty()
364 }
365
366 #[inline]
368 pub fn new() -> Self {
369 PropertyDeclarationBlock {
370 declarations: ThinVec::new(),
371 declarations_importance: SmallBitVec::new(),
372 property_ids: PropertyDeclarationIdSet::default(),
373 }
374 }
375
376 pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
378 let mut property_ids = PropertyDeclarationIdSet::default();
379 property_ids.insert(declaration.id());
380 let mut declarations = ThinVec::with_capacity(1);
381 declarations.push(declaration);
382 PropertyDeclarationBlock {
383 declarations,
384 declarations_importance: SmallBitVec::from_elem(1, importance.important()),
385 property_ids,
386 }
387 }
388
389 #[inline]
391 pub fn declarations(&self) -> &[PropertyDeclaration] {
392 &self.declarations
393 }
394
395 #[inline]
397 pub fn declarations_importance(&self) -> &SmallBitVec {
398 &self.declarations_importance
399 }
400
401 #[inline]
403 pub fn declaration_importance_iter(&self) -> DeclarationImportanceIterator {
404 DeclarationImportanceIterator::new(&self.declarations, &self.declarations_importance)
405 }
406
407 #[inline]
409 pub fn normal_declaration_iter<'a>(
410 &'a self,
411 ) -> impl DoubleEndedIterator<Item = &'a PropertyDeclaration> {
412 self.declaration_importance_iter()
413 .filter(|(_, importance)| !importance.important())
414 .map(|(declaration, _)| declaration)
415 }
416
417 #[inline]
419 pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>(
420 &'a self,
421 context: &'cx mut Context<'cx_a>,
422 style: &'a ComputedValues,
423 default_values: &'a ComputedValues,
424 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
425 AnimationValueIterator::new(self, context, style, default_values)
426 }
427
428 #[inline]
433 pub fn any_important(&self) -> bool {
434 !self.declarations_importance.all_false()
435 }
436
437 #[inline]
442 pub fn any_normal(&self) -> bool {
443 !self.declarations_importance.all_true()
444 }
445
446 #[inline]
449 pub fn property_ids(&self) -> &PropertyDeclarationIdSet {
450 &self.property_ids
451 }
452
453 #[inline]
455 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
456 self.property_ids.contains(id)
457 }
458
459 #[inline]
461 pub fn contains_any_reset(&self) -> bool {
462 self.property_ids.contains_any_reset()
463 }
464
465 #[inline]
470 pub fn get(
471 &self,
472 property: PropertyDeclarationId,
473 ) -> Option<(&PropertyDeclaration, Importance)> {
474 if !self.contains(property) {
475 return None;
476 }
477 self.declaration_importance_iter()
478 .find(|(declaration, _)| declaration.id() == property)
479 }
480
481 pub fn shorthand_to_css(
484 &self,
485 shorthand: ShorthandId,
486 dest: &mut CssStringWriter,
487 ) -> fmt::Result {
488 let mut list = SmallVec::<[&_; 10]>::new();
491 let mut important_count = 0;
492
493 for longhand in shorthand.longhands() {
495 let declaration = self.get(PropertyDeclarationId::Longhand(longhand));
497
498 match declaration {
500 Some((declaration, importance)) => {
501 list.push(declaration);
502 if importance.important() {
503 important_count += 1;
504 }
505 },
506 None => return Ok(()),
507 }
508 }
509
510 if important_count > 0 && important_count != list.len() {
513 return Ok(());
514 }
515
516 match shorthand.get_shorthand_appendable_value(&list) {
520 Some(appendable_value) => append_declaration_value(dest, appendable_value),
521 None => return Ok(()),
522 }
523 }
524
525 pub fn property_value_to_css(
529 &self,
530 property: &PropertyId,
531 dest: &mut CssStringWriter,
532 ) -> fmt::Result {
533 let longhand_or_custom = match property.as_shorthand() {
537 Ok(shorthand) => return self.shorthand_to_css(shorthand, dest),
538 Err(longhand_or_custom) => longhand_or_custom,
539 };
540
541 if let Some((value, _importance)) = self.get(longhand_or_custom) {
542 value.to_css(dest)
544 } else {
545 Ok(())
547 }
548 }
549
550 pub fn property_priority(&self, property: &PropertyId) -> Importance {
552 match property.as_shorthand() {
556 Ok(shorthand) => {
557 if shorthand.longhands().all(|l| {
559 self.get(PropertyDeclarationId::Longhand(l))
560 .map_or(false, |(_, importance)| importance.important())
561 }) {
562 Importance::Important
563 } else {
564 Importance::Normal
565 }
566 },
567 Err(longhand_or_custom) => {
568 self.get(longhand_or_custom)
570 .map_or(Importance::Normal, |(_, importance)| importance)
571 },
572 }
573 }
574
575 pub fn extend(
580 &mut self,
581 mut drain: SourcePropertyDeclarationDrain,
582 importance: Importance,
583 ) -> bool {
584 let all_shorthand_len = match drain.all_shorthand {
585 AllShorthand::NotSet => 0,
586 AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
587 property_counts::ALL_SHORTHAND_EXPANDED
588 },
589 };
590 let push_calls_count = drain.declarations.len() + all_shorthand_len;
591
592 self.declarations.reserve(push_calls_count);
594
595 let mut changed = false;
596 for decl in &mut drain.declarations {
597 changed |= self.push(decl, importance);
598 }
599 drain
600 .all_shorthand
601 .declarations()
602 .fold(changed, |changed, decl| {
603 changed | self.push(decl, importance)
604 })
605 }
606
607 pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
613 let id = declaration.id();
614 if !self.property_ids.insert(id) {
615 let mut index_to_remove = None;
616 for (i, slot) in self.declarations.iter_mut().enumerate() {
617 if slot.id() != id {
618 continue;
619 }
620
621 let important = self.declarations_importance[i];
622
623 if important && !importance.important() {
626 return false;
627 }
628
629 index_to_remove = Some(i);
630 break;
631 }
632
633 if let Some(index) = index_to_remove {
634 self.declarations.remove(index);
635 self.declarations_importance.remove(index);
636 self.declarations.push(declaration);
637 self.declarations_importance.push(importance.important());
638 return true;
639 }
640 }
641
642 self.declarations.push(declaration);
643 self.declarations_importance.push(importance.important());
644 true
645 }
646
647 pub fn prepare_for_update(
651 &self,
652 source_declarations: &SourcePropertyDeclaration,
653 importance: Importance,
654 updates: &mut SourcePropertyDeclarationUpdate,
655 ) -> bool {
656 debug_assert!(updates.updates.is_empty());
657 if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
659 debug_assert!(source_declarations.declarations.is_empty());
660 return source_declarations
661 .all_shorthand
662 .declarations()
663 .any(|decl| {
664 !self.contains(decl.id()) ||
665 self.declarations
666 .iter()
667 .enumerate()
668 .find(|&(_, ref d)| d.id() == decl.id())
669 .map_or(true, |(i, d)| {
670 let important = self.declarations_importance[i];
671 *d != decl || important != importance.important()
672 })
673 });
674 }
675 let mut any_update = false;
677 let new_count = &mut updates.new_count;
678 let any_removal = &mut updates.any_removal;
679 let updates = &mut updates.updates;
680 updates.extend(
681 source_declarations
682 .declarations
683 .iter()
684 .map(|declaration| {
685 if !self.contains(declaration.id()) {
686 return DeclarationUpdate::Append;
687 }
688 let longhand_id = declaration.id().as_longhand();
689 if let Some(longhand_id) = longhand_id {
690 if let Some(logical_group) = longhand_id.logical_group() {
691 let mut needs_append = false;
692 for (pos, decl) in self.declarations.iter().enumerate().rev() {
693 let id = match decl.id().as_longhand() {
694 Some(id) => id,
695 None => continue,
696 };
697 if id == longhand_id {
698 if needs_append {
699 return DeclarationUpdate::AppendAndRemove { pos };
700 }
701 let important = self.declarations_importance[pos];
702 if decl == declaration && important == importance.important() {
703 return DeclarationUpdate::None;
704 }
705 return DeclarationUpdate::UpdateInPlace { pos };
706 }
707 if !needs_append &&
708 id.logical_group() == Some(logical_group) &&
709 id.is_logical() != longhand_id.is_logical()
710 {
711 needs_append = true;
712 }
713 }
714 unreachable!("Longhand should be found in loop above");
715 }
716 }
717 self.declarations
718 .iter()
719 .enumerate()
720 .find(|&(_, ref decl)| decl.id() == declaration.id())
721 .map_or(DeclarationUpdate::Append, |(pos, decl)| {
722 let important = self.declarations_importance[pos];
723 if decl == declaration && important == importance.important() {
724 DeclarationUpdate::None
725 } else {
726 DeclarationUpdate::UpdateInPlace { pos }
727 }
728 })
729 })
730 .inspect(|update| {
731 if matches!(update, DeclarationUpdate::None) {
732 return;
733 }
734 any_update = true;
735 match update {
736 DeclarationUpdate::Append => {
737 *new_count += 1;
738 },
739 DeclarationUpdate::AppendAndRemove { .. } => {
740 *any_removal = true;
741 },
742 _ => {},
743 }
744 }),
745 );
746 any_update
747 }
748
749 pub fn update(
751 &mut self,
752 drain: SourcePropertyDeclarationDrain,
753 importance: Importance,
754 updates: &mut SourcePropertyDeclarationUpdate,
755 ) {
756 let important = importance.important();
757 if !matches!(drain.all_shorthand, AllShorthand::NotSet) {
758 debug_assert!(updates.updates.is_empty());
759 for decl in drain.all_shorthand.declarations() {
760 let id = decl.id();
761 if self.property_ids.insert(id) {
762 self.declarations.push(decl);
763 self.declarations_importance.push(important);
764 } else {
765 let (idx, slot) = self
766 .declarations
767 .iter_mut()
768 .enumerate()
769 .find(|&(_, ref d)| d.id() == decl.id())
770 .unwrap();
771 *slot = decl;
772 self.declarations_importance.set(idx, important);
773 }
774 }
775 return;
776 }
777
778 self.declarations.reserve(updates.new_count);
779 if updates.any_removal {
780 struct UpdateOrRemoval<'a> {
782 item: &'a mut DeclarationUpdate,
783 pos: usize,
784 remove: bool,
785 }
786 let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
787 .updates
788 .iter_mut()
789 .filter_map(|item| {
790 let (pos, remove) = match *item {
791 DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
792 DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
793 _ => return None,
794 };
795 Some(UpdateOrRemoval { item, pos, remove })
796 })
797 .collect();
798 updates_and_removals.sort_unstable_by_key(|update| update.pos);
801 updates_and_removals
802 .iter()
803 .rev()
804 .filter(|update| update.remove)
805 .for_each(|update| {
806 self.declarations.remove(update.pos);
807 self.declarations_importance.remove(update.pos);
808 });
809 let mut removed_count = 0;
811 for update in updates_and_removals.iter_mut() {
812 if update.remove {
813 removed_count += 1;
814 continue;
815 }
816 debug_assert_eq!(
817 *update.item,
818 DeclarationUpdate::UpdateInPlace { pos: update.pos }
819 );
820 *update.item = DeclarationUpdate::UpdateInPlace {
821 pos: update.pos - removed_count,
822 };
823 }
824 }
825 for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
827 match *update {
828 DeclarationUpdate::None => {},
829 DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
830 self.property_ids.insert(decl.id());
831 self.declarations.push(decl);
832 self.declarations_importance.push(important);
833 },
834 DeclarationUpdate::UpdateInPlace { pos } => {
835 self.declarations[pos] = decl;
836 self.declarations_importance.set(pos, important);
837 },
838 }
839 }
840 updates.updates.clear();
841 }
842
843 #[inline]
846 pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
847 if let Err(longhand_or_custom) = property.as_shorthand() {
848 if !self.contains(longhand_or_custom) {
849 return None;
850 }
851 }
852
853 self.declarations
854 .iter()
855 .position(|declaration| declaration.id().is_or_is_longhand_of(property))
856 }
857
858 #[inline]
860 fn remove_declaration_at(&mut self, i: usize) {
861 self.property_ids.remove(self.declarations[i].id());
862 self.declarations_importance.remove(i);
863 self.declarations.remove(i);
864 }
865
866 #[inline]
868 pub fn clear(&mut self) {
869 self.declarations_importance.clear();
870 self.declarations.clear();
871 self.property_ids.clear();
872 }
873
874 #[inline]
879 pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
880 debug_assert_eq!(
881 Some(first_declaration),
882 self.first_declaration_to_remove(property)
883 );
884 debug_assert!(self.declarations[first_declaration]
885 .id()
886 .is_or_is_longhand_of(property));
887
888 self.remove_declaration_at(first_declaration);
889
890 let shorthand = match property.as_shorthand() {
891 Ok(s) => s,
892 Err(_longhand_or_custom) => return,
893 };
894
895 let mut i = first_declaration;
896 let mut len = self.len();
897 while i < len {
898 if !self.declarations[i].id().is_longhand_of(shorthand) {
899 i += 1;
900 continue;
901 }
902
903 self.remove_declaration_at(i);
904 len -= 1;
905 }
906 }
907
908 pub fn single_value_to_css(
910 &self,
911 property: &PropertyId,
912 dest: &mut CssStringWriter,
913 computed_values: Option<&ComputedValues>,
914 stylist: &Stylist,
915 ) -> fmt::Result {
916 if let Ok(shorthand) = property.as_shorthand() {
917 return self.shorthand_to_css(shorthand, dest);
918 }
919
920 let declaration = match self.declarations.get(0) {
923 Some(d) => d,
924 None => return Err(fmt::Error),
925 };
926
927 let mut rule_cache_conditions = RuleCacheConditions::default();
928 let mut context = Context::new(
929 StyleBuilder::new(
930 stylist.device(),
931 Some(stylist),
932 computed_values,
933 None,
934 None,
935 false,
936 ),
937 stylist.quirks_mode(),
938 &mut rule_cache_conditions,
939 ContainerSizeQuery::none(),
940 );
941
942 if let Some(cv) = computed_values {
943 context.builder.custom_properties = cv.custom_properties().clone();
944 };
945
946 match (declaration, computed_values) {
947 (&PropertyDeclaration::WithVariables(ref declaration), Some(_)) => declaration
955 .value
956 .substitute_variables(
957 declaration.id,
958 &context.builder.custom_properties,
959 stylist,
960 &context,
961 &mut Default::default(),
962 )
963 .to_css(dest),
964 (ref d, _) => d.to_css(dest),
965 }
966 }
967
968 pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
970 let len = animation_value_map.len();
971 let mut declarations = ThinVec::with_capacity(len);
972 let mut property_ids = PropertyDeclarationIdSet::default();
973
974 for (property, animation_value) in animation_value_map.iter() {
975 property_ids.insert(property.as_borrowed());
976 declarations.push(animation_value.uncompute());
977 }
978
979 PropertyDeclarationBlock {
980 declarations,
981 property_ids,
982 declarations_importance: SmallBitVec::from_elem(len, false),
983 }
984 }
985
986 pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
989 if let Err(longhand_or_custom) = property.as_shorthand() {
990 if !self.property_ids.contains(longhand_or_custom) {
991 return false;
992 }
993 }
994 self.declarations.iter().any(|decl| {
995 decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
996 })
997 }
998
999 pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
1005 let mut is_first_serialization = true; let mut already_serialized = NonCustomPropertyIdSet::new();
1017
1018 'declaration_loop: for (declaration, importance) in self.declaration_importance_iter() {
1020 let property = declaration.id();
1022 let longhand_id = match property {
1023 PropertyDeclarationId::Longhand(id) => id,
1024 PropertyDeclarationId::Custom(..) => {
1025 append_serialization(
1030 dest,
1031 &property,
1032 AppendableValue::Declaration(declaration),
1033 importance,
1034 &mut is_first_serialization,
1035 )?;
1036 continue;
1037 },
1038 };
1039
1040 if already_serialized.contains(longhand_id.into()) {
1042 continue;
1043 }
1044
1045 for shorthand in longhand_id.shorthands() {
1047 if already_serialized.contains(shorthand.into()) {
1049 continue;
1050 }
1051 already_serialized.insert(shorthand.into());
1052
1053 if shorthand.is_legacy_shorthand() {
1054 continue;
1055 }
1056
1057 let longhands = {
1064 let mut ids = LonghandIdSet::new();
1067 for longhand in shorthand.longhands() {
1068 ids.insert(longhand);
1069 }
1070 ids
1071 };
1072
1073 if !self.property_ids.contains_all_longhands(&longhands) {
1078 continue;
1079 }
1080
1081 let mut current_longhands = SmallVec::<[&_; 10]>::new();
1084 let mut logical_groups = LogicalGroupSet::new();
1085 let mut saw_one = false;
1086 let mut logical_mismatch = false;
1087 let mut seen = LonghandIdSet::new();
1088 let mut important_count = 0;
1089
1090 for (declaration, importance) in self.declaration_importance_iter() {
1094 let longhand = match declaration.id() {
1095 PropertyDeclarationId::Longhand(id) => id,
1096 PropertyDeclarationId::Custom(..) => continue,
1097 };
1098
1099 if longhands.contains(longhand) {
1100 saw_one = true;
1101 if importance.important() {
1102 important_count += 1;
1103 }
1104 current_longhands.push(declaration);
1105 if shorthand != ShorthandId::All {
1106 if let Some(g) = longhand.logical_group() {
1109 logical_groups.insert(g);
1110 }
1111 seen.insert(longhand);
1112 if seen == longhands {
1113 break;
1114 }
1115 }
1116 } else if saw_one {
1117 if let Some(g) = longhand.logical_group() {
1118 if logical_groups.contains(g) {
1119 logical_mismatch = true;
1120 break;
1121 }
1122 }
1123 }
1124 }
1125
1126 let is_important = important_count > 0;
1132 if is_important && important_count != current_longhands.len() {
1133 continue;
1134 }
1135
1136 if logical_mismatch {
1144 continue;
1145 }
1146
1147 let importance = if is_important {
1148 Importance::Important
1149 } else {
1150 Importance::Normal
1151 };
1152
1153 let appendable_value =
1157 match shorthand.get_shorthand_appendable_value(¤t_longhands) {
1158 None => continue,
1159 Some(appendable_value) => appendable_value,
1160 };
1161
1162 let mut v = CssString::new();
1165 let value = match appendable_value {
1166 AppendableValue::Css(css) => {
1167 debug_assert!(!css.is_empty());
1168 appendable_value
1169 },
1170 other => {
1171 append_declaration_value(&mut v, other)?;
1172
1173 if v.is_empty() {
1177 continue;
1178 }
1179
1180 AppendableValue::Css({
1181 #[cfg(feature = "gecko")]
1183 unsafe {
1184 v.as_str_unchecked()
1185 }
1186 #[cfg(feature = "servo")]
1187 &v
1188 })
1189 },
1190 };
1191
1192 append_serialization(
1202 dest,
1203 &shorthand,
1204 value,
1205 importance,
1206 &mut is_first_serialization,
1207 )?;
1208
1209 for current_longhand in ¤t_longhands {
1213 let longhand_id = match current_longhand.id() {
1214 PropertyDeclarationId::Longhand(id) => id,
1215 PropertyDeclarationId::Custom(..) => unreachable!(),
1216 };
1217
1218 already_serialized.insert(longhand_id.into());
1220 }
1221
1222 continue 'declaration_loop;
1225 }
1226
1227 append_serialization(
1238 dest,
1239 &property,
1240 AppendableValue::Declaration(declaration),
1241 importance,
1242 &mut is_first_serialization,
1243 )?;
1244
1245 already_serialized.insert(longhand_id.into());
1248 }
1249
1250 Ok(())
1252 }
1253}
1254
1255pub enum AppendableValue<'a, 'b: 'a> {
1258 Declaration(&'a PropertyDeclaration),
1260 DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]),
1265 Css(&'a str),
1268}
1269
1270fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
1272where
1273 W: Write,
1274{
1275 if !*is_first_serialization {
1276 dest.write_char(' ')
1277 } else {
1278 *is_first_serialization = false;
1279 Ok(())
1280 }
1281}
1282
1283pub fn append_declaration_value<'a, 'b: 'a>(
1285 dest: &mut CssStringWriter,
1286 appendable_value: AppendableValue<'a, 'b>,
1287) -> fmt::Result {
1288 match appendable_value {
1289 AppendableValue::Css(css) => dest.write_str(css),
1290 AppendableValue::Declaration(decl) => decl.to_css(dest),
1291 AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
1292 shorthand.longhands_to_css(decls, dest)
1293 },
1294 }
1295}
1296
1297pub fn append_serialization<'a, 'b: 'a, N>(
1299 dest: &mut CssStringWriter,
1300 property_name: &N,
1301 appendable_value: AppendableValue<'a, 'b>,
1302 importance: Importance,
1303 is_first_serialization: &mut bool,
1304) -> fmt::Result
1305where
1306 N: ToCss,
1307{
1308 handle_first_serialization(dest, is_first_serialization)?;
1309
1310 property_name.to_css(&mut CssWriter::new(dest))?;
1311 dest.write_str(": ")?;
1312
1313 append_declaration_value(dest, appendable_value)?;
1314
1315 if importance.important() {
1316 dest.write_str(" !important")?;
1317 }
1318
1319 dest.write_char(';')
1320}
1321
1322#[inline]
1327pub fn parse_style_attribute(
1328 input: &str,
1329 url_data: &UrlExtraData,
1330 error_reporter: Option<&dyn ParseErrorReporter>,
1331 quirks_mode: QuirksMode,
1332 rule_type: CssRuleType,
1333) -> PropertyDeclarationBlock {
1334 let context = ParserContext::new(
1335 Origin::Author,
1336 url_data,
1337 Some(rule_type),
1338 ParsingMode::DEFAULT,
1339 quirks_mode,
1340 Default::default(),
1341 error_reporter,
1342 None,
1343 );
1344
1345 let mut input = ParserInput::new(input);
1346 parse_property_declaration_list(&context, &mut Parser::new(&mut input), &[])
1347}
1348
1349#[inline]
1354pub fn parse_one_declaration_into(
1355 declarations: &mut SourcePropertyDeclaration,
1356 id: PropertyId,
1357 input: &str,
1358 origin: Origin,
1359 url_data: &UrlExtraData,
1360 error_reporter: Option<&dyn ParseErrorReporter>,
1361 parsing_mode: ParsingMode,
1362 quirks_mode: QuirksMode,
1363 rule_type: CssRuleType,
1364) -> Result<(), ()> {
1365 let context = ParserContext::new(
1366 origin,
1367 url_data,
1368 Some(rule_type),
1369 parsing_mode,
1370 quirks_mode,
1371 Default::default(),
1372 error_reporter,
1373 None,
1374 );
1375
1376 let property_id_for_error_reporting = if context.error_reporting_enabled() {
1377 Some(id.clone())
1378 } else {
1379 None
1380 };
1381
1382 let mut input = ParserInput::new(input);
1383 let mut parser = Parser::new(&mut input);
1384 let start_position = parser.position();
1385 parser
1386 .parse_entirely(|parser| {
1387 PropertyDeclaration::parse_into(declarations, id, &context, parser)
1388 })
1389 .map_err(|err| {
1390 if context.error_reporting_enabled() {
1391 report_one_css_error(
1392 &context,
1393 None,
1394 &[],
1395 err,
1396 parser.slice_from(start_position),
1397 property_id_for_error_reporting,
1398 )
1399 }
1400 })
1401}
1402
1403struct PropertyDeclarationParser<'a, 'b: 'a, 'i> {
1405 context: &'a ParserContext<'b>,
1406 state: &'a mut DeclarationParserState<'i>,
1407}
1408
1409#[derive(Default)]
1413pub struct DeclarationParserState<'i> {
1414 output_block: PropertyDeclarationBlock,
1416 declarations: SourcePropertyDeclaration,
1419 importance: Importance,
1421 errors: SmallParseErrorVec<'i>,
1423 first_declaration_start: SourceLocation,
1425 last_parsed_property_id: Option<PropertyId>,
1427}
1428
1429impl<'i> DeclarationParserState<'i> {
1430 pub fn first_declaration_start(&self) -> SourceLocation {
1432 self.first_declaration_start
1433 }
1434
1435 pub fn has_parsed_declarations(&self) -> bool {
1437 !self.output_block.is_empty()
1438 }
1439
1440 pub fn take_declarations(&mut self) -> PropertyDeclarationBlock {
1442 std::mem::take(&mut self.output_block)
1443 }
1444
1445 pub fn parse_value<'t>(
1447 &mut self,
1448 context: &ParserContext,
1449 name: CowRcStr<'i>,
1450 input: &mut Parser<'i, 't>,
1451 declaration_start: &ParserState,
1452 ) -> Result<(), ParseError<'i>> {
1453 let id = match PropertyId::parse(&name, context) {
1454 Ok(id) => id,
1455 Err(..) => {
1456 return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
1457 },
1458 };
1459 if context.error_reporting_enabled() {
1460 self.last_parsed_property_id = Some(id.clone());
1461 }
1462 input.parse_until_before(Delimiter::Bang, |input| {
1463 PropertyDeclaration::parse_into(&mut self.declarations, id, context, input)
1464 })?;
1465 self.importance = match input.try_parse(parse_important) {
1466 Ok(()) => {
1467 if !context.allows_important_declarations() {
1468 return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedImportantDeclaration));
1469 }
1470 Importance::Important
1471 },
1472 Err(_) => Importance::Normal,
1473 };
1474 input.expect_exhausted()?;
1476 let has_parsed_declarations = self.has_parsed_declarations();
1477 self.output_block
1478 .extend(self.declarations.drain(), self.importance);
1479 self.last_parsed_property_id = None;
1483
1484 if !has_parsed_declarations {
1485 self.first_declaration_start = declaration_start.source_location();
1486 }
1487
1488 Ok(())
1489 }
1490
1491 #[inline]
1493 pub fn report_errors_if_needed(
1494 &mut self,
1495 context: &ParserContext,
1496 selectors: &[SelectorList<SelectorImpl>],
1497 ) {
1498 if self.errors.is_empty() {
1499 return;
1500 }
1501 self.do_report_css_errors(context, selectors);
1502 }
1503
1504 #[cold]
1505 fn do_report_css_errors(
1506 &mut self,
1507 context: &ParserContext,
1508 selectors: &[SelectorList<SelectorImpl>],
1509 ) {
1510 for (error, slice, property) in self.errors.drain(..) {
1511 report_one_css_error(
1512 context,
1513 Some(&self.output_block),
1514 selectors,
1515 error,
1516 slice,
1517 property,
1518 )
1519 }
1520 }
1521
1522 #[inline]
1524 pub fn did_error(&mut self, context: &ParserContext, error: ParseError<'i>, slice: &'i str) {
1525 self.declarations.clear();
1526 if !context.error_reporting_enabled() {
1527 return;
1528 }
1529 let property = self.last_parsed_property_id.take();
1530 self.errors.push((error, slice, property));
1531 }
1532}
1533
1534impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1536 type Prelude = ();
1537 type AtRule = ();
1538 type Error = StyleParseErrorKind<'i>;
1539}
1540
1541impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1543 type Prelude = ();
1544 type QualifiedRule = ();
1545 type Error = StyleParseErrorKind<'i>;
1546}
1547
1548fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
1550 (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
1551}
1552
1553impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1554 type Declaration = ();
1555 type Error = StyleParseErrorKind<'i>;
1556
1557 fn parse_value<'t>(
1558 &mut self,
1559 name: CowRcStr<'i>,
1560 input: &mut Parser<'i, 't>,
1561 declaration_start: &ParserState,
1562 ) -> Result<(), ParseError<'i>> {
1563 self.state.parse_value(self.context, name, input, declaration_start)
1564 }
1565}
1566
1567impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>>
1568 for PropertyDeclarationParser<'a, 'b, 'i>
1569{
1570 fn parse_declarations(&self) -> bool {
1571 true
1572 }
1573 fn parse_qualified(&self) -> bool {
1575 false
1576 }
1577}
1578
1579type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
1580
1581fn alias_of_known_property(name: &str) -> Option<PropertyId> {
1582 let mut prefixed = String::with_capacity(name.len() + 5);
1583 prefixed.push_str("-moz-");
1584 prefixed.push_str(name);
1585 PropertyId::parse_enabled_for_all_content(&prefixed).ok()
1586}
1587
1588#[cold]
1589fn report_one_css_error<'i>(
1590 context: &ParserContext,
1591 block: Option<&PropertyDeclarationBlock>,
1592 selectors: &[SelectorList<SelectorImpl>],
1593 mut error: ParseError<'i>,
1594 slice: &str,
1595 property: Option<PropertyId>,
1596) {
1597 debug_assert!(context.error_reporting_enabled());
1598
1599 fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
1600 match property.as_shorthand() {
1601 Ok(id) => id
1602 .longhands()
1603 .all(|longhand| block.contains(PropertyDeclarationId::Longhand(longhand))),
1604 Err(longhand_or_custom) => block.contains(longhand_or_custom),
1605 }
1606 }
1607
1608 if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(ref name)) = error.kind {
1609 if is_non_mozilla_vendor_identifier(name) {
1610 return;
1613 }
1614 if let Some(alias) = alias_of_known_property(name) {
1615 if let Some(block) = block {
1619 if all_properties_in_block(block, &alias) {
1620 return;
1621 }
1622 }
1623 }
1624 }
1625
1626 if let Some(ref property) = property {
1627 if let Some(block) = block {
1628 if all_properties_in_block(block, property) {
1629 return;
1630 }
1631 }
1632 if !matches!(
1636 error.kind,
1637 ParseErrorKind::Custom(StyleParseErrorKind::UnexpectedImportantDeclaration)
1638 ) {
1639 error = match *property {
1640 PropertyId::Custom(ref c) => {
1641 StyleParseErrorKind::new_invalid(format!("--{}", c), error)
1642 },
1643 _ => StyleParseErrorKind::new_invalid(property.non_custom_id().unwrap().name(), error),
1644 };
1645 }
1646 }
1647
1648 let location = error.location;
1649 let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
1650 context.log_css_error(location, error);
1651}
1652
1653pub fn parse_property_declaration_list(
1656 context: &ParserContext,
1657 input: &mut Parser,
1658 selectors: &[SelectorList<SelectorImpl>],
1659) -> PropertyDeclarationBlock {
1660 let mut state = DeclarationParserState::default();
1661 let mut parser = PropertyDeclarationParser {
1662 context,
1663 state: &mut state,
1664 };
1665 let mut iter = RuleBodyParser::new(input, &mut parser);
1666 while let Some(declaration) = iter.next() {
1667 match declaration {
1668 Ok(()) => {},
1669 Err((error, slice)) => iter.parser.state.did_error(context, error, slice),
1670 }
1671 }
1672 parser.state.report_errors_if_needed(context, selectors);
1673 state.output_block
1674}