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::dom::DummyAttributeProvider;
20use crate::error_reporting::{ContextualParseError, ParseErrorReporter};
21use crate::parser::ParserContext;
22use crate::properties::{
23 animated_properties::{AnimationValue, AnimationValueMap},
24 StyleBuilder,
25};
26use crate::rule_cache::RuleCacheConditions;
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 TypedValue,
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)]
126pub enum PropertyTypedValue {
127 None,
129
130 Unsupported,
134
135 Typed(TypedValue),
137}
138
139#[derive(Clone, Debug, ToShmem, Default, MallocSizeOf)]
141pub struct PropertyDeclarationIdSet {
142 longhands: LonghandIdSet,
143 custom: PrecomputedHashSet<custom_properties::Name>,
144}
145
146impl PropertyDeclarationIdSet {
147 pub fn insert(&mut self, id: PropertyDeclarationId) -> bool {
149 match id {
150 PropertyDeclarationId::Longhand(id) => {
151 if self.longhands.contains(id) {
152 return false;
153 }
154 self.longhands.insert(id);
155 return true;
156 },
157 PropertyDeclarationId::Custom(name) => self.custom.insert((*name).clone()),
158 }
159 }
160
161 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
163 match id {
164 PropertyDeclarationId::Longhand(id) => self.longhands.contains(id),
165 PropertyDeclarationId::Custom(name) => self.custom.contains(name),
166 }
167 }
168
169 pub fn remove(&mut self, id: PropertyDeclarationId) {
171 match id {
172 PropertyDeclarationId::Longhand(id) => self.longhands.remove(id),
173 PropertyDeclarationId::Custom(name) => {
174 self.custom.remove(name);
175 },
176 }
177 }
178
179 pub fn clear(&mut self) {
181 self.longhands.clear();
182 self.custom.clear();
183 }
184
185 #[inline]
187 pub fn is_empty(&self) -> bool {
188 self.longhands.is_empty() && self.custom.is_empty()
189 }
190 #[inline]
192 pub fn contains_any_reset(&self) -> bool {
193 self.longhands.contains_any_reset()
194 }
195
196 #[inline]
198 pub fn contains_all_longhands(&self, longhands: &LonghandIdSet) -> bool {
199 self.longhands.contains_all(longhands)
200 }
201
202 #[inline]
204 pub fn contains_all(&self, properties: &PropertyDeclarationIdSet) -> bool {
205 if !self.longhands.contains_all(&properties.longhands) {
206 return false;
207 }
208 if properties.custom.len() > self.custom.len() {
209 return false;
210 }
211 properties
212 .custom
213 .iter()
214 .all(|item| self.custom.contains(item))
215 }
216
217 pub fn iter(&self) -> PropertyDeclarationIdSetIterator<'_> {
219 PropertyDeclarationIdSetIterator {
220 longhands: self.longhands.iter(),
221 custom: self.custom.iter(),
222 }
223 }
224}
225
226pub struct PropertyDeclarationIdSetIterator<'a> {
228 longhands: LonghandIdSetIterator<'a>,
229 custom: std::collections::hash_set::Iter<'a, custom_properties::Name>,
230}
231
232impl<'a> Iterator for PropertyDeclarationIdSetIterator<'a> {
233 type Item = PropertyDeclarationId<'a>;
234
235 fn next(&mut self) -> Option<Self::Item> {
236 match self.longhands.next() {
240 Some(id) => Some(PropertyDeclarationId::Longhand(id)),
241 None => match self.custom.next() {
242 Some(a) => Some(PropertyDeclarationId::Custom(a)),
243 None => None,
244 },
245 }
246 }
247}
248
249#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
251#[derive(Clone, ToShmem, Default)]
252pub struct PropertyDeclarationBlock {
253 declarations: ThinVec<PropertyDeclaration>,
257
258 declarations_importance: SmallBitVec,
260
261 property_ids: PropertyDeclarationIdSet,
263}
264
265impl PartialEq for PropertyDeclarationBlock {
266 fn eq(&self, other: &Self) -> bool {
267 self.declarations == other.declarations
270 && self.declarations_importance == other.declarations_importance
271 }
272}
273
274pub struct DeclarationImportanceIterator<'a> {
276 iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
277}
278
279impl<'a> Default for DeclarationImportanceIterator<'a> {
280 fn default() -> Self {
281 Self {
282 iter: [].iter().zip(smallbitvec::Iter::default()),
283 }
284 }
285}
286
287impl<'a> DeclarationImportanceIterator<'a> {
288 fn new(declarations: &'a [PropertyDeclaration], important: &'a SmallBitVec) -> Self {
290 DeclarationImportanceIterator {
291 iter: declarations.iter().zip(important.iter()),
292 }
293 }
294}
295
296impl<'a> Iterator for DeclarationImportanceIterator<'a> {
297 type Item = (&'a PropertyDeclaration, Importance);
298
299 #[inline]
300 fn next(&mut self) -> Option<Self::Item> {
301 self.iter.next().map(|(decl, important)| {
302 (
303 decl,
304 if important {
305 Importance::Important
306 } else {
307 Importance::Normal
308 },
309 )
310 })
311 }
312
313 #[inline]
314 fn size_hint(&self) -> (usize, Option<usize>) {
315 self.iter.size_hint()
316 }
317}
318
319impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
320 #[inline(always)]
321 fn next_back(&mut self) -> Option<Self::Item> {
322 self.iter.next_back().map(|(decl, important)| {
323 (
324 decl,
325 if important {
326 Importance::Important
327 } else {
328 Importance::Normal
329 },
330 )
331 })
332 }
333}
334
335pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> {
337 iter: DeclarationImportanceIterator<'a>,
338 context: &'cx mut Context<'cx_a>,
339 style: &'a ComputedValues,
340 default_values: &'a ComputedValues,
341}
342
343impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
344 fn new(
345 declarations: &'a PropertyDeclarationBlock,
346 context: &'cx mut Context<'cx_a>,
347 style: &'a ComputedValues,
348 default_values: &'a ComputedValues,
349 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
350 AnimationValueIterator {
351 iter: declarations.declaration_importance_iter(),
352 context,
353 style,
354 default_values,
355 }
356 }
357}
358
359impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
360 type Item = AnimationValue;
361 #[inline]
362 fn next(&mut self) -> Option<Self::Item> {
363 loop {
364 let (decl, importance) = self.iter.next()?;
365
366 if importance.important() {
367 continue;
368 }
369
370 let animation = AnimationValue::from_declaration(
371 decl,
372 &mut self.context,
373 self.style,
374 self.default_values,
375 &mut AttributeTracker::new(&DummyAttributeProvider {}),
377 );
378
379 if let Some(anim) = animation {
380 return Some(anim);
381 }
382 }
383 }
384}
385
386impl fmt::Debug for PropertyDeclarationBlock {
387 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
388 self.declarations.fmt(f)
389 }
390}
391
392impl PropertyDeclarationBlock {
393 #[inline]
395 pub fn len(&self) -> usize {
396 self.declarations.len()
397 }
398
399 #[inline]
401 pub fn is_empty(&self) -> bool {
402 self.declarations.is_empty()
403 }
404
405 #[inline]
407 pub fn new() -> Self {
408 PropertyDeclarationBlock {
409 declarations: ThinVec::new(),
410 declarations_importance: SmallBitVec::new(),
411 property_ids: PropertyDeclarationIdSet::default(),
412 }
413 }
414
415 pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
417 let mut property_ids = PropertyDeclarationIdSet::default();
418 property_ids.insert(declaration.id());
419 let mut declarations = ThinVec::with_capacity(1);
420 declarations.push(declaration);
421 PropertyDeclarationBlock {
422 declarations,
423 declarations_importance: SmallBitVec::from_elem(1, importance.important()),
424 property_ids,
425 }
426 }
427
428 #[inline]
430 pub fn declarations(&self) -> &[PropertyDeclaration] {
431 &self.declarations
432 }
433
434 #[inline]
436 pub fn declarations_importance(&self) -> &SmallBitVec {
437 &self.declarations_importance
438 }
439
440 #[inline]
442 pub fn declaration_importance_iter(&self) -> DeclarationImportanceIterator<'_> {
443 DeclarationImportanceIterator::new(&self.declarations, &self.declarations_importance)
444 }
445
446 #[inline]
448 pub fn normal_declaration_iter<'a>(
449 &'a self,
450 ) -> impl DoubleEndedIterator<Item = &'a PropertyDeclaration> {
451 self.declaration_importance_iter()
452 .filter(|(_, importance)| !importance.important())
453 .map(|(declaration, _)| declaration)
454 }
455
456 #[inline]
458 pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>(
459 &'a self,
460 context: &'cx mut Context<'cx_a>,
461 style: &'a ComputedValues,
462 default_values: &'a ComputedValues,
463 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
464 AnimationValueIterator::new(self, context, style, default_values)
465 }
466
467 #[inline]
472 pub fn any_important(&self) -> bool {
473 !self.declarations_importance.all_false()
474 }
475
476 #[inline]
481 pub fn any_normal(&self) -> bool {
482 !self.declarations_importance.all_true()
483 }
484
485 #[inline]
488 pub fn property_ids(&self) -> &PropertyDeclarationIdSet {
489 &self.property_ids
490 }
491
492 #[inline]
494 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
495 self.property_ids.contains(id)
496 }
497
498 #[inline]
500 pub fn contains_any_reset(&self) -> bool {
501 self.property_ids.contains_any_reset()
502 }
503
504 #[inline]
509 pub fn get(
510 &self,
511 property: PropertyDeclarationId,
512 ) -> Option<(&PropertyDeclaration, Importance)> {
513 if !self.contains(property) {
514 return None;
515 }
516 self.declaration_importance_iter()
517 .find(|(declaration, _)| declaration.id() == property)
518 }
519
520 pub fn shorthand_to_css(
523 &self,
524 shorthand: ShorthandId,
525 dest: &mut CssStringWriter,
526 ) -> fmt::Result {
527 let mut list = SmallVec::<[&_; 10]>::new();
530 let mut important_count = 0;
531
532 for longhand in shorthand.longhands() {
534 let declaration = self.get(PropertyDeclarationId::Longhand(longhand));
536
537 match declaration {
539 Some((declaration, importance)) => {
540 list.push(declaration);
541 if importance.important() {
542 important_count += 1;
543 }
544 },
545 None => return Ok(()),
546 }
547 }
548
549 if important_count > 0 && important_count != list.len() {
552 return Ok(());
553 }
554
555 match shorthand.get_shorthand_appendable_value(&list) {
559 Some(appendable_value) => append_declaration_value(dest, appendable_value),
560 None => return Ok(()),
561 }
562 }
563
564 pub fn property_value_to_css(
568 &self,
569 property: &PropertyId,
570 dest: &mut CssStringWriter,
571 ) -> fmt::Result {
572 let longhand_or_custom = match property.as_shorthand() {
576 Ok(shorthand) => return self.shorthand_to_css(shorthand, dest),
577 Err(longhand_or_custom) => longhand_or_custom,
578 };
579
580 if let Some((value, _importance)) = self.get(longhand_or_custom) {
581 value.to_css(dest)
583 } else {
584 Ok(())
586 }
587 }
588
589 pub fn property_priority(&self, property: &PropertyId) -> Importance {
591 match property.as_shorthand() {
595 Ok(shorthand) => {
596 if shorthand.longhands().all(|l| {
598 self.get(PropertyDeclarationId::Longhand(l))
599 .map_or(false, |(_, importance)| importance.important())
600 }) {
601 Importance::Important
602 } else {
603 Importance::Normal
604 }
605 },
606 Err(longhand_or_custom) => {
607 self.get(longhand_or_custom)
609 .map_or(Importance::Normal, |(_, importance)| importance)
610 },
611 }
612 }
613
614 pub fn property_value_to_typed(&self, property: &PropertyId) -> PropertyTypedValue {
616 match property.as_shorthand() {
617 Ok(shorthand) => {
618 if shorthand
619 .longhands()
620 .all(|longhand| self.contains(PropertyDeclarationId::Longhand(longhand)))
621 {
622 PropertyTypedValue::Unsupported
623 } else {
624 PropertyTypedValue::None
625 }
626 },
627 Err(longhand_or_custom) => match self.get(longhand_or_custom) {
628 Some((value, _importance)) => {
629 if let Some(typed_value) = value.to_typed() {
630 PropertyTypedValue::Typed(typed_value)
631 } else {
632 PropertyTypedValue::Unsupported
633 }
634 },
635 None => PropertyTypedValue::None,
636 },
637 }
638 }
639
640 pub fn extend(
645 &mut self,
646 mut drain: SourcePropertyDeclarationDrain,
647 importance: Importance,
648 ) -> bool {
649 let all_shorthand_len = match drain.all_shorthand {
650 AllShorthand::NotSet => 0,
651 AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
652 property_counts::ALL_SHORTHAND_EXPANDED
653 },
654 };
655 let push_calls_count = drain.declarations.len() + all_shorthand_len;
656
657 self.declarations.reserve(push_calls_count);
659
660 let mut changed = false;
661 for decl in &mut drain.declarations {
662 changed |= self.push(decl, importance);
663 }
664 drain
665 .all_shorthand
666 .declarations()
667 .fold(changed, |changed, decl| {
668 changed | self.push(decl, importance)
669 })
670 }
671
672 pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
678 let id = declaration.id();
679 if !self.property_ids.insert(id) {
680 let mut index_to_remove = None;
681 for (i, slot) in self.declarations.iter_mut().enumerate() {
682 if slot.id() != id {
683 continue;
684 }
685
686 let important = self.declarations_importance[i];
687
688 if important && !importance.important() {
691 return false;
692 }
693
694 index_to_remove = Some(i);
695 break;
696 }
697
698 if let Some(index) = index_to_remove {
699 self.declarations.remove(index);
700 self.declarations_importance.remove(index);
701 self.declarations.push(declaration);
702 self.declarations_importance.push(importance.important());
703 return true;
704 }
705 }
706
707 self.declarations.push(declaration);
708 self.declarations_importance.push(importance.important());
709 true
710 }
711
712 pub fn prepare_for_update(
716 &self,
717 source_declarations: &SourcePropertyDeclaration,
718 importance: Importance,
719 updates: &mut SourcePropertyDeclarationUpdate,
720 ) -> bool {
721 debug_assert!(updates.updates.is_empty());
722 if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
724 debug_assert!(source_declarations.declarations.is_empty());
725 return source_declarations
726 .all_shorthand
727 .declarations()
728 .any(|decl| {
729 !self.contains(decl.id())
730 || self
731 .declarations
732 .iter()
733 .enumerate()
734 .find(|&(_, ref d)| d.id() == decl.id())
735 .map_or(true, |(i, d)| {
736 let important = self.declarations_importance[i];
737 *d != decl || important != importance.important()
738 })
739 });
740 }
741 let mut any_update = false;
743 let new_count = &mut updates.new_count;
744 let any_removal = &mut updates.any_removal;
745 let updates = &mut updates.updates;
746 updates.extend(
747 source_declarations
748 .declarations
749 .iter()
750 .map(|declaration| {
751 if !self.contains(declaration.id()) {
752 return DeclarationUpdate::Append;
753 }
754 let longhand_id = declaration.id().as_longhand();
755 if let Some(longhand_id) = longhand_id {
756 if let Some(logical_group) = longhand_id.logical_group() {
757 let mut needs_append = false;
758 for (pos, decl) in self.declarations.iter().enumerate().rev() {
759 let id = match decl.id().as_longhand() {
760 Some(id) => id,
761 None => continue,
762 };
763 if id == longhand_id {
764 if needs_append {
765 return DeclarationUpdate::AppendAndRemove { pos };
766 }
767 let important = self.declarations_importance[pos];
768 if decl == declaration && important == importance.important() {
769 return DeclarationUpdate::None;
770 }
771 return DeclarationUpdate::UpdateInPlace { pos };
772 }
773 if !needs_append
774 && id.logical_group() == Some(logical_group)
775 && id.is_logical() != longhand_id.is_logical()
776 {
777 needs_append = true;
778 }
779 }
780 unreachable!("Longhand should be found in loop above");
781 }
782 }
783 self.declarations
784 .iter()
785 .enumerate()
786 .find(|&(_, ref decl)| decl.id() == declaration.id())
787 .map_or(DeclarationUpdate::Append, |(pos, decl)| {
788 let important = self.declarations_importance[pos];
789 if decl == declaration && important == importance.important() {
790 DeclarationUpdate::None
791 } else {
792 DeclarationUpdate::UpdateInPlace { pos }
793 }
794 })
795 })
796 .inspect(|update| {
797 if matches!(update, DeclarationUpdate::None) {
798 return;
799 }
800 any_update = true;
801 match update {
802 DeclarationUpdate::Append => {
803 *new_count += 1;
804 },
805 DeclarationUpdate::AppendAndRemove { .. } => {
806 *any_removal = true;
807 },
808 _ => {},
809 }
810 }),
811 );
812 any_update
813 }
814
815 pub fn update(
817 &mut self,
818 drain: SourcePropertyDeclarationDrain,
819 importance: Importance,
820 updates: &mut SourcePropertyDeclarationUpdate,
821 ) {
822 let important = importance.important();
823 if !matches!(drain.all_shorthand, AllShorthand::NotSet) {
824 debug_assert!(updates.updates.is_empty());
825 for decl in drain.all_shorthand.declarations() {
826 let id = decl.id();
827 if self.property_ids.insert(id) {
828 self.declarations.push(decl);
829 self.declarations_importance.push(important);
830 } else {
831 let (idx, slot) = self
832 .declarations
833 .iter_mut()
834 .enumerate()
835 .find(|&(_, ref d)| d.id() == decl.id())
836 .unwrap();
837 *slot = decl;
838 self.declarations_importance.set(idx, important);
839 }
840 }
841 return;
842 }
843
844 self.declarations.reserve(updates.new_count);
845 if updates.any_removal {
846 struct UpdateOrRemoval<'a> {
848 item: &'a mut DeclarationUpdate,
849 pos: usize,
850 remove: bool,
851 }
852 let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
853 .updates
854 .iter_mut()
855 .filter_map(|item| {
856 let (pos, remove) = match *item {
857 DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
858 DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
859 _ => return None,
860 };
861 Some(UpdateOrRemoval { item, pos, remove })
862 })
863 .collect();
864 updates_and_removals.sort_unstable_by_key(|update| update.pos);
867 updates_and_removals
868 .iter()
869 .rev()
870 .filter(|update| update.remove)
871 .for_each(|update| {
872 self.declarations.remove(update.pos);
873 self.declarations_importance.remove(update.pos);
874 });
875 let mut removed_count = 0;
877 for update in updates_and_removals.iter_mut() {
878 if update.remove {
879 removed_count += 1;
880 continue;
881 }
882 debug_assert_eq!(
883 *update.item,
884 DeclarationUpdate::UpdateInPlace { pos: update.pos }
885 );
886 *update.item = DeclarationUpdate::UpdateInPlace {
887 pos: update.pos - removed_count,
888 };
889 }
890 }
891 for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
893 match *update {
894 DeclarationUpdate::None => {},
895 DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
896 self.property_ids.insert(decl.id());
897 self.declarations.push(decl);
898 self.declarations_importance.push(important);
899 },
900 DeclarationUpdate::UpdateInPlace { pos } => {
901 self.declarations[pos] = decl;
902 self.declarations_importance.set(pos, important);
903 },
904 }
905 }
906 updates.updates.clear();
907 }
908
909 #[inline]
912 pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
913 if let Err(longhand_or_custom) = property.as_shorthand() {
914 if !self.contains(longhand_or_custom) {
915 return None;
916 }
917 }
918
919 self.declarations
920 .iter()
921 .position(|declaration| declaration.id().is_or_is_longhand_of(property))
922 }
923
924 #[inline]
926 fn remove_declaration_at(&mut self, i: usize) {
927 self.property_ids.remove(self.declarations[i].id());
928 self.declarations_importance.remove(i);
929 self.declarations.remove(i);
930 }
931
932 #[inline]
934 pub fn clear(&mut self) {
935 self.declarations_importance.clear();
936 self.declarations.clear();
937 self.property_ids.clear();
938 }
939
940 #[inline]
945 pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
946 debug_assert_eq!(
947 Some(first_declaration),
948 self.first_declaration_to_remove(property)
949 );
950 debug_assert!(self.declarations[first_declaration]
951 .id()
952 .is_or_is_longhand_of(property));
953
954 self.remove_declaration_at(first_declaration);
955
956 let shorthand = match property.as_shorthand() {
957 Ok(s) => s,
958 Err(_longhand_or_custom) => return,
959 };
960
961 let mut i = first_declaration;
962 let mut len = self.len();
963 while i < len {
964 if !self.declarations[i].id().is_longhand_of(shorthand) {
965 i += 1;
966 continue;
967 }
968
969 self.remove_declaration_at(i);
970 len -= 1;
971 }
972 }
973
974 pub fn single_value_to_css(
976 &self,
977 property: &PropertyId,
978 dest: &mut CssStringWriter,
979 computed_values: Option<&ComputedValues>,
980 stylist: &Stylist,
981 ) -> fmt::Result {
982 if let Ok(shorthand) = property.as_shorthand() {
983 return self.shorthand_to_css(shorthand, dest);
984 }
985
986 let declaration = match self.declarations.get(0) {
989 Some(d) => d,
990 None => return Err(fmt::Error),
991 };
992
993 let mut rule_cache_conditions = RuleCacheConditions::default();
994 let mut context = Context::new(
995 StyleBuilder::new(
996 stylist.device(),
997 Some(stylist),
998 computed_values,
999 None,
1000 None,
1001 false,
1002 ),
1003 stylist.quirks_mode(),
1004 &mut rule_cache_conditions,
1005 ContainerSizeQuery::none(),
1006 );
1007
1008 if let Some(cv) = computed_values {
1009 context.builder.custom_properties = cv.custom_properties().clone();
1010 };
1011
1012 match (declaration, computed_values) {
1013 (&PropertyDeclaration::WithVariables(ref declaration), Some(_)) => declaration
1021 .value
1022 .substitute_variables(
1023 declaration.id,
1024 &context.builder.custom_properties,
1025 stylist,
1026 &context,
1027 &mut Default::default(),
1028 &mut AttributeTracker::new(&DummyAttributeProvider {}),
1029 )
1030 .to_css(dest),
1031 (ref d, _) => d.to_css(dest),
1032 }
1033 }
1034
1035 pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
1037 let len = animation_value_map.len();
1038 let mut declarations = ThinVec::with_capacity(len);
1039 let mut property_ids = PropertyDeclarationIdSet::default();
1040
1041 for (property, animation_value) in animation_value_map.iter() {
1042 property_ids.insert(property.as_borrowed());
1043 declarations.push(animation_value.uncompute());
1044 }
1045
1046 PropertyDeclarationBlock {
1047 declarations,
1048 property_ids,
1049 declarations_importance: SmallBitVec::from_elem(len, false),
1050 }
1051 }
1052
1053 pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
1056 if let Err(longhand_or_custom) = property.as_shorthand() {
1057 if !self.property_ids.contains(longhand_or_custom) {
1058 return false;
1059 }
1060 }
1061 self.declarations.iter().any(|decl| {
1062 decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
1063 })
1064 }
1065
1066 pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
1072 let mut is_first_serialization = true; let mut already_serialized = NonCustomPropertyIdSet::new();
1084
1085 'declaration_loop: for (declaration, importance) in self.declaration_importance_iter() {
1087 let property = declaration.id();
1089 let longhand_id = match property {
1090 PropertyDeclarationId::Longhand(id) => id,
1091 PropertyDeclarationId::Custom(..) => {
1092 append_serialization(
1097 dest,
1098 &property,
1099 AppendableValue::Declaration(declaration),
1100 importance,
1101 &mut is_first_serialization,
1102 )?;
1103 continue;
1104 },
1105 };
1106
1107 if already_serialized.contains(longhand_id.into()) {
1109 continue;
1110 }
1111
1112 for shorthand in longhand_id.shorthands() {
1114 if already_serialized.contains(shorthand.into()) {
1116 continue;
1117 }
1118 already_serialized.insert(shorthand.into());
1119
1120 if shorthand.is_legacy_shorthand() {
1121 continue;
1122 }
1123
1124 let longhands = {
1131 let mut ids = LonghandIdSet::new();
1134 for longhand in shorthand.longhands() {
1135 ids.insert(longhand);
1136 }
1137 ids
1138 };
1139
1140 if !self.property_ids.contains_all_longhands(&longhands) {
1145 continue;
1146 }
1147
1148 let mut current_longhands = SmallVec::<[&_; 10]>::new();
1151 let mut logical_groups = LogicalGroupSet::new();
1152 let mut saw_one = false;
1153 let mut logical_mismatch = false;
1154 let mut seen = LonghandIdSet::new();
1155 let mut important_count = 0;
1156
1157 for (declaration, importance) in self.declaration_importance_iter() {
1161 let longhand = match declaration.id() {
1162 PropertyDeclarationId::Longhand(id) => id,
1163 PropertyDeclarationId::Custom(..) => continue,
1164 };
1165
1166 if longhands.contains(longhand) {
1167 saw_one = true;
1168 if importance.important() {
1169 important_count += 1;
1170 }
1171 current_longhands.push(declaration);
1172 if shorthand != ShorthandId::All {
1173 if let Some(g) = longhand.logical_group() {
1176 logical_groups.insert(g);
1177 }
1178 seen.insert(longhand);
1179 if seen == longhands {
1180 break;
1181 }
1182 }
1183 } else if saw_one {
1184 if let Some(g) = longhand.logical_group() {
1185 if logical_groups.contains(g) {
1186 logical_mismatch = true;
1187 break;
1188 }
1189 }
1190 }
1191 }
1192
1193 let is_important = important_count > 0;
1199 if is_important && important_count != current_longhands.len() {
1200 continue;
1201 }
1202
1203 if logical_mismatch {
1211 continue;
1212 }
1213
1214 let importance = if is_important {
1215 Importance::Important
1216 } else {
1217 Importance::Normal
1218 };
1219
1220 let appendable_value =
1224 match shorthand.get_shorthand_appendable_value(¤t_longhands) {
1225 None => continue,
1226 Some(appendable_value) => appendable_value,
1227 };
1228
1229 let mut v = CssString::new();
1232 let value = match appendable_value {
1233 AppendableValue::Css(css) => {
1234 debug_assert!(!css.is_empty());
1235 appendable_value
1236 },
1237 other => {
1238 append_declaration_value(&mut v, other)?;
1239
1240 if v.is_empty() {
1244 continue;
1245 }
1246
1247 AppendableValue::Css({
1248 #[cfg(feature = "gecko")]
1250 unsafe {
1251 v.as_str_unchecked()
1252 }
1253 #[cfg(feature = "servo")]
1254 &v
1255 })
1256 },
1257 };
1258
1259 append_serialization(
1269 dest,
1270 &shorthand,
1271 value,
1272 importance,
1273 &mut is_first_serialization,
1274 )?;
1275
1276 for current_longhand in ¤t_longhands {
1280 let longhand_id = match current_longhand.id() {
1281 PropertyDeclarationId::Longhand(id) => id,
1282 PropertyDeclarationId::Custom(..) => unreachable!(),
1283 };
1284
1285 already_serialized.insert(longhand_id.into());
1287 }
1288
1289 continue 'declaration_loop;
1292 }
1293
1294 append_serialization(
1305 dest,
1306 &property,
1307 AppendableValue::Declaration(declaration),
1308 importance,
1309 &mut is_first_serialization,
1310 )?;
1311
1312 already_serialized.insert(longhand_id.into());
1315 }
1316
1317 Ok(())
1319 }
1320}
1321
1322pub enum AppendableValue<'a, 'b: 'a> {
1325 Declaration(&'a PropertyDeclaration),
1327 DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]),
1332 Css(&'a str),
1335}
1336
1337fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
1339where
1340 W: Write,
1341{
1342 if !*is_first_serialization {
1343 dest.write_char(' ')
1344 } else {
1345 *is_first_serialization = false;
1346 Ok(())
1347 }
1348}
1349
1350pub fn append_declaration_value<'a, 'b: 'a>(
1352 dest: &mut CssStringWriter,
1353 appendable_value: AppendableValue<'a, 'b>,
1354) -> fmt::Result {
1355 match appendable_value {
1356 AppendableValue::Css(css) => dest.write_str(css),
1357 AppendableValue::Declaration(decl) => decl.to_css(dest),
1358 AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
1359 shorthand.longhands_to_css(decls, dest)
1360 },
1361 }
1362}
1363
1364pub fn append_serialization<'a, 'b: 'a, N>(
1366 dest: &mut CssStringWriter,
1367 property_name: &N,
1368 appendable_value: AppendableValue<'a, 'b>,
1369 importance: Importance,
1370 is_first_serialization: &mut bool,
1371) -> fmt::Result
1372where
1373 N: ToCss,
1374{
1375 handle_first_serialization(dest, is_first_serialization)?;
1376
1377 property_name.to_css(&mut CssWriter::new(dest))?;
1378 dest.write_str(": ")?;
1379
1380 append_declaration_value(dest, appendable_value)?;
1381
1382 if importance.important() {
1383 dest.write_str(" !important")?;
1384 }
1385
1386 dest.write_char(';')
1387}
1388
1389#[inline]
1394pub fn parse_style_attribute(
1395 input: &str,
1396 url_data: &UrlExtraData,
1397 error_reporter: Option<&dyn ParseErrorReporter>,
1398 quirks_mode: QuirksMode,
1399 rule_type: CssRuleType,
1400) -> PropertyDeclarationBlock {
1401 let context = ParserContext::new(
1402 Origin::Author,
1403 url_data,
1404 Some(rule_type),
1405 ParsingMode::DEFAULT,
1406 quirks_mode,
1407 Default::default(),
1408 error_reporter,
1409 None,
1410 );
1411
1412 let mut input = ParserInput::new(input);
1413 parse_property_declaration_list(&context, &mut Parser::new(&mut input), &[])
1414}
1415
1416#[inline]
1421pub fn parse_one_declaration_into(
1422 declarations: &mut SourcePropertyDeclaration,
1423 id: PropertyId,
1424 input: &str,
1425 origin: Origin,
1426 url_data: &UrlExtraData,
1427 error_reporter: Option<&dyn ParseErrorReporter>,
1428 parsing_mode: ParsingMode,
1429 quirks_mode: QuirksMode,
1430 rule_type: CssRuleType,
1431) -> Result<(), ()> {
1432 let context = ParserContext::new(
1433 origin,
1434 url_data,
1435 Some(rule_type),
1436 parsing_mode,
1437 quirks_mode,
1438 Default::default(),
1439 error_reporter,
1440 None,
1441 );
1442
1443 let property_id_for_error_reporting = if context.error_reporting_enabled() {
1444 Some(id.clone())
1445 } else {
1446 None
1447 };
1448
1449 let mut input = ParserInput::new(input);
1450 let mut parser = Parser::new(&mut input);
1451 let start_position = parser.position();
1452 parser
1453 .parse_entirely(|parser| {
1454 PropertyDeclaration::parse_into(declarations, id, &context, parser)
1455 })
1456 .map_err(|err| {
1457 if context.error_reporting_enabled() {
1458 report_one_css_error(
1459 &context,
1460 None,
1461 &[],
1462 err,
1463 parser.slice_from(start_position),
1464 property_id_for_error_reporting,
1465 )
1466 }
1467 })
1468}
1469
1470struct PropertyDeclarationParser<'a, 'b: 'a, 'i> {
1472 context: &'a ParserContext<'b>,
1473 state: &'a mut DeclarationParserState<'i>,
1474}
1475
1476#[derive(Default)]
1480pub struct DeclarationParserState<'i> {
1481 output_block: PropertyDeclarationBlock,
1483 declarations: SourcePropertyDeclaration,
1486 importance: Importance,
1488 errors: SmallParseErrorVec<'i>,
1490 first_declaration_start: SourceLocation,
1492 last_parsed_property_id: Option<PropertyId>,
1494}
1495
1496impl<'i> DeclarationParserState<'i> {
1497 pub fn first_declaration_start(&self) -> SourceLocation {
1499 self.first_declaration_start
1500 }
1501
1502 pub fn has_parsed_declarations(&self) -> bool {
1504 !self.output_block.is_empty()
1505 }
1506
1507 pub fn take_declarations(&mut self) -> PropertyDeclarationBlock {
1509 std::mem::take(&mut self.output_block)
1510 }
1511
1512 pub fn parse_value<'t>(
1514 &mut self,
1515 context: &ParserContext,
1516 name: CowRcStr<'i>,
1517 input: &mut Parser<'i, 't>,
1518 declaration_start: &ParserState,
1519 ) -> Result<(), ParseError<'i>> {
1520 let id = match PropertyId::parse(&name, context) {
1521 Ok(id) => id,
1522 Err(..) => {
1523 return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
1524 },
1525 };
1526 if context.error_reporting_enabled() {
1527 self.last_parsed_property_id = Some(id.clone());
1528 }
1529 input.parse_until_before(Delimiter::Bang, |input| {
1530 PropertyDeclaration::parse_into(&mut self.declarations, id, context, input)
1531 })?;
1532 self.importance = match input.try_parse(parse_important) {
1533 Ok(()) => {
1534 if !context.allows_important_declarations() {
1535 return Err(
1536 input.new_custom_error(StyleParseErrorKind::UnexpectedImportantDeclaration)
1537 );
1538 }
1539 Importance::Important
1540 },
1541 Err(_) => Importance::Normal,
1542 };
1543 input.expect_exhausted()?;
1545 let has_parsed_declarations = self.has_parsed_declarations();
1546 self.output_block
1547 .extend(self.declarations.drain(), self.importance);
1548 self.last_parsed_property_id = None;
1552
1553 if !has_parsed_declarations {
1554 self.first_declaration_start = declaration_start.source_location();
1555 }
1556
1557 Ok(())
1558 }
1559
1560 #[inline]
1562 pub fn report_errors_if_needed(
1563 &mut self,
1564 context: &ParserContext,
1565 selectors: &[SelectorList<SelectorImpl>],
1566 ) {
1567 if self.errors.is_empty() {
1568 return;
1569 }
1570 self.do_report_css_errors(context, selectors);
1571 }
1572
1573 #[cold]
1574 fn do_report_css_errors(
1575 &mut self,
1576 context: &ParserContext,
1577 selectors: &[SelectorList<SelectorImpl>],
1578 ) {
1579 for (error, slice, property) in self.errors.drain(..) {
1580 report_one_css_error(
1581 context,
1582 Some(&self.output_block),
1583 selectors,
1584 error,
1585 slice,
1586 property,
1587 )
1588 }
1589 }
1590
1591 #[inline]
1593 pub fn did_error(&mut self, context: &ParserContext, error: ParseError<'i>, slice: &'i str) {
1594 self.declarations.clear();
1595 if !context.error_reporting_enabled() {
1596 return;
1597 }
1598 let property = self.last_parsed_property_id.take();
1599 self.errors.push((error, slice, property));
1600 }
1601}
1602
1603impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1605 type Prelude = ();
1606 type AtRule = ();
1607 type Error = StyleParseErrorKind<'i>;
1608}
1609
1610impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1612 type Prelude = ();
1613 type QualifiedRule = ();
1614 type Error = StyleParseErrorKind<'i>;
1615}
1616
1617fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
1619 (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
1620}
1621
1622impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1623 type Declaration = ();
1624 type Error = StyleParseErrorKind<'i>;
1625
1626 fn parse_value<'t>(
1627 &mut self,
1628 name: CowRcStr<'i>,
1629 input: &mut Parser<'i, 't>,
1630 declaration_start: &ParserState,
1631 ) -> Result<(), ParseError<'i>> {
1632 self.state
1633 .parse_value(self.context, name, input, declaration_start)
1634 }
1635}
1636
1637impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>>
1638 for PropertyDeclarationParser<'a, 'b, 'i>
1639{
1640 fn parse_declarations(&self) -> bool {
1641 true
1642 }
1643 fn parse_qualified(&self) -> bool {
1645 false
1646 }
1647}
1648
1649type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
1650
1651fn alias_of_known_property(name: &str) -> Option<PropertyId> {
1652 let mut prefixed = String::with_capacity(name.len() + 5);
1653 prefixed.push_str("-moz-");
1654 prefixed.push_str(name);
1655 PropertyId::parse_enabled_for_all_content(&prefixed).ok()
1656}
1657
1658#[cold]
1659fn report_one_css_error<'i>(
1660 context: &ParserContext,
1661 block: Option<&PropertyDeclarationBlock>,
1662 selectors: &[SelectorList<SelectorImpl>],
1663 mut error: ParseError<'i>,
1664 slice: &str,
1665 property: Option<PropertyId>,
1666) {
1667 debug_assert!(context.error_reporting_enabled());
1668
1669 fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
1670 match property.as_shorthand() {
1671 Ok(id) => id
1672 .longhands()
1673 .all(|longhand| block.contains(PropertyDeclarationId::Longhand(longhand))),
1674 Err(longhand_or_custom) => block.contains(longhand_or_custom),
1675 }
1676 }
1677
1678 if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(ref name)) = error.kind {
1679 if is_non_mozilla_vendor_identifier(name) {
1680 return;
1683 }
1684 if let Some(alias) = alias_of_known_property(name) {
1685 if let Some(block) = block {
1689 if all_properties_in_block(block, &alias) {
1690 return;
1691 }
1692 }
1693 }
1694 }
1695
1696 if let Some(ref property) = property {
1697 if let Some(block) = block {
1698 if all_properties_in_block(block, property) {
1699 return;
1700 }
1701 }
1702 if !matches!(
1706 error.kind,
1707 ParseErrorKind::Custom(StyleParseErrorKind::UnexpectedImportantDeclaration)
1708 ) {
1709 error = match *property {
1710 PropertyId::Custom(ref c) => {
1711 StyleParseErrorKind::new_invalid(format!("--{}", c), error)
1712 },
1713 _ => StyleParseErrorKind::new_invalid(
1714 property.non_custom_id().unwrap().name(),
1715 error,
1716 ),
1717 };
1718 }
1719 }
1720
1721 let location = error.location;
1722 let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
1723 context.log_css_error(location, error);
1724}
1725
1726pub fn parse_property_declaration_list(
1729 context: &ParserContext,
1730 input: &mut Parser,
1731 selectors: &[SelectorList<SelectorImpl>],
1732) -> PropertyDeclarationBlock {
1733 let mut state = DeclarationParserState::default();
1734 let mut parser = PropertyDeclarationParser {
1735 context,
1736 state: &mut state,
1737 };
1738 let mut iter = RuleBodyParser::new(input, &mut parser);
1739 while let Some(declaration) = iter.next() {
1740 match declaration {
1741 Ok(()) => {},
1742 Err((error, slice)) => iter.parser.state.did_error(context, error, slice),
1743 }
1744 }
1745 parser.state.report_errors_if_needed(context, selectors);
1746 state.output_block
1747}