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