1#![deny(missing_docs)]
8
9use super::{
10 AllShorthand, ComputedValues, LogicalGroupSet, LonghandIdSet, LonghandIdSetIterator,
11 NonCustomPropertyId, NonCustomPropertyIdSet, PropertyDeclaration, PropertyDeclarationId,
12 PropertyId, ShorthandId, SourcePropertyDeclaration, SourcePropertyDeclarationDrain,
13 SubpropertiesVec, property_counts,
14};
15
16use crate::context::{QuirksMode, TreeCountingCaches};
17use crate::custom_properties;
18use crate::derives::*;
19use crate::dom::{AttributeTracker, DummyElementContext};
20use crate::error_reporting::{ContextualParseError, ParseErrorReporter};
21use crate::parser::ParserContext;
22use crate::properties::{
23 StyleBuilder,
24 animated_properties::{AnimationValue, AnimationValueMap},
25};
26use crate::rule_cache::RuleCacheConditions;
27use crate::rule_tree::RuleCascadeFlags;
28use crate::selector_map::PrecomputedHashSet;
29use crate::selector_parser::SelectorImpl;
30use crate::shared_lock::Locked;
31use crate::stylesheets::container_rule::ContainerSizeQuery;
32use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
33use crate::stylist::Stylist;
34use crate::typed_om::TypedValueList;
35use crate::values::computed::Context;
36use cssparser::{
37 AtRuleParser, CowRcStr, DeclarationParser, Delimiter, ParseErrorKind, Parser, ParserState,
38 QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser, SourceLocation, parse_important,
39};
40use itertools::Itertools;
41use selectors::SelectorList;
42use servo_arc::Arc;
43use smallbitvec::SmallBitVec;
44use smallvec::SmallVec;
45use std::borrow::Cow;
46use std::fmt::{self, Write};
47use std::iter::Zip;
48use std::slice::Iter;
49use std::sync::atomic::AtomicBool;
50use style_traits::{
51 CssString, CssStringWriter, CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss,
52};
53use thin_vec::ThinVec;
54
55#[derive(Default)]
57pub struct AnimationDeclarations {
58 pub animations: Option<Arc<Locked<PropertyDeclarationBlock>>>,
60 pub transitions: Option<Arc<Locked<PropertyDeclarationBlock>>>,
62}
63
64impl AnimationDeclarations {
65 pub fn is_empty(&self) -> bool {
67 self.animations.is_none() && self.transitions.is_none()
68 }
69}
70
71#[derive(Clone, Copy, Debug, Eq, PartialEq)]
74enum DeclarationUpdate {
75 None,
77 Append,
79 UpdateInPlace { pos: usize },
81 AppendAndRemove { pos: usize },
84}
85
86#[derive(Default)]
89pub struct SourcePropertyDeclarationUpdate {
90 updates: SubpropertiesVec<DeclarationUpdate>,
91 new_count: usize,
92 any_removal: bool,
93}
94
95#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, Default)]
99pub enum Importance {
100 #[default]
102 Normal,
103
104 Important,
106}
107
108impl Importance {
109 pub fn important(self) -> bool {
111 match self {
112 Self::Normal => false,
113 Self::Important => true,
114 }
115 }
116}
117
118#[derive(Clone, Debug, ToShmem, Default, MallocSizeOf)]
120pub struct PropertyDeclarationIdSet {
121 longhands: LonghandIdSet,
122 custom: PrecomputedHashSet<custom_properties::Name>,
123}
124
125impl PropertyDeclarationIdSet {
126 pub fn insert(&mut self, id: PropertyDeclarationId) -> bool {
128 match id {
129 PropertyDeclarationId::Longhand(id) => {
130 if self.longhands.contains(id) {
131 return false;
132 }
133 self.longhands.insert(id);
134 true
135 },
136 PropertyDeclarationId::Custom(name) => self.custom.insert((*name).clone()),
137 }
138 }
139
140 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
142 match id {
143 PropertyDeclarationId::Longhand(id) => self.longhands.contains(id),
144 PropertyDeclarationId::Custom(name) => self.custom.contains(name),
145 }
146 }
147
148 pub fn remove(&mut self, id: PropertyDeclarationId) {
150 match id {
151 PropertyDeclarationId::Longhand(id) => self.longhands.remove(id),
152 PropertyDeclarationId::Custom(name) => {
153 self.custom.remove(name);
154 },
155 }
156 }
157
158 pub fn clear(&mut self) {
160 self.longhands.clear();
161 self.custom.clear();
162 }
163
164 #[inline]
166 pub fn is_empty(&self) -> bool {
167 self.longhands.is_empty() && self.custom.is_empty()
168 }
169 #[inline]
171 pub fn contains_any_reset(&self) -> bool {
172 self.longhands.contains_any_reset()
173 }
174
175 #[inline]
177 pub fn contains_all_longhands(&self, longhands: &LonghandIdSet) -> bool {
178 self.longhands.contains_all(longhands)
179 }
180
181 #[inline]
183 pub fn contains_all(&self, properties: &PropertyDeclarationIdSet) -> bool {
184 if !self.longhands.contains_all(&properties.longhands) {
185 return false;
186 }
187 if properties.custom.len() > self.custom.len() {
188 return false;
189 }
190 properties
191 .custom
192 .iter()
193 .all(|item| self.custom.contains(item))
194 }
195
196 pub fn iter(&self) -> PropertyDeclarationIdSetIterator<'_> {
198 PropertyDeclarationIdSetIterator {
199 longhands: self.longhands.iter(),
200 custom: self.custom.iter(),
201 }
202 }
203}
204
205pub struct PropertyDeclarationIdSetIterator<'a> {
207 longhands: LonghandIdSetIterator<'a>,
208 custom: hashbrown::hash_set::Iter<'a, custom_properties::Name>,
209}
210
211impl<'a> Iterator for PropertyDeclarationIdSetIterator<'a> {
212 type Item = PropertyDeclarationId<'a>;
213
214 fn next(&mut self) -> Option<Self::Item> {
215 match self.longhands.next() {
219 Some(id) => Some(PropertyDeclarationId::Longhand(id)),
220 None => self.custom.next().map(PropertyDeclarationId::Custom),
221 }
222 }
223}
224
225#[derive(Default, MallocSizeOf)]
227pub struct PropertyDeclarationBlock {
228 declarations: ThinVec<PropertyDeclaration>,
232
233 declarations_importance: SmallBitVec,
235
236 property_ids: PropertyDeclarationIdSet,
238
239 pub immutable: AtomicBool,
243}
244
245impl to_shmem::ToShmem for PropertyDeclarationBlock {
246 fn to_shmem(&self, builder: &mut to_shmem::SharedMemoryBuilder) -> to_shmem::Result<Self> {
247 use std::mem::ManuallyDrop;
248 let declarations = self.declarations.to_shmem(builder)?;
249 let declarations_importance = self.declarations_importance.to_shmem(builder)?;
250 let property_ids = self.property_ids.to_shmem(builder)?;
251 let immutable = AtomicBool::new(true);
252
253 Ok(ManuallyDrop::new(Self {
254 declarations: ManuallyDrop::into_inner(declarations),
255 declarations_importance: ManuallyDrop::into_inner(declarations_importance),
256 property_ids: ManuallyDrop::into_inner(property_ids),
257 immutable,
258 }))
259 }
260}
261
262impl Clone for PropertyDeclarationBlock {
263 fn clone(&self) -> Self {
264 Self {
265 declarations: self.declarations.clone(),
266 declarations_importance: self.declarations_importance.clone(),
267 property_ids: self.property_ids.clone(),
268 immutable: AtomicBool::new(false),
269 }
270 }
271}
272
273impl PartialEq for PropertyDeclarationBlock {
274 fn eq(&self, other: &Self) -> bool {
275 self.declarations == other.declarations
279 && self.declarations_importance == other.declarations_importance
280 }
281}
282
283pub struct DeclarationImportanceIterator<'a> {
285 iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
286}
287
288impl<'a> Default for DeclarationImportanceIterator<'a> {
289 fn default() -> Self {
290 Self {
291 iter: [].iter().zip(smallbitvec::Iter::default()),
292 }
293 }
294}
295
296impl<'a> DeclarationImportanceIterator<'a> {
297 fn new(declarations: &'a [PropertyDeclaration], important: &'a SmallBitVec) -> Self {
299 DeclarationImportanceIterator {
300 iter: declarations.iter().zip(important.iter()),
301 }
302 }
303}
304
305impl<'a> Iterator for DeclarationImportanceIterator<'a> {
306 type Item = (&'a PropertyDeclaration, Importance);
307
308 #[inline]
309 fn next(&mut self) -> Option<Self::Item> {
310 self.iter.next().map(|(decl, important)| {
311 (
312 decl,
313 if important {
314 Importance::Important
315 } else {
316 Importance::Normal
317 },
318 )
319 })
320 }
321
322 #[inline]
323 fn size_hint(&self) -> (usize, Option<usize>) {
324 self.iter.size_hint()
325 }
326}
327
328impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
329 #[inline(always)]
330 fn next_back(&mut self) -> Option<Self::Item> {
331 self.iter.next_back().map(|(decl, important)| {
332 (
333 decl,
334 if important {
335 Importance::Important
336 } else {
337 Importance::Normal
338 },
339 )
340 })
341 }
342}
343
344pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> {
346 iter: DeclarationImportanceIterator<'a>,
347 context: &'cx mut Context<'cx_a>,
348 style: &'a ComputedValues,
349 default_values: &'a ComputedValues,
350}
351
352impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
353 fn new(
354 declarations: &'a PropertyDeclarationBlock,
355 context: &'cx mut Context<'cx_a>,
356 style: &'a ComputedValues,
357 default_values: &'a ComputedValues,
358 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
359 AnimationValueIterator {
360 iter: declarations.declaration_importance_iter(),
361 context,
362 style,
363 default_values,
364 }
365 }
366}
367
368impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
369 type Item = AnimationValue;
370 #[inline]
371 fn next(&mut self) -> Option<Self::Item> {
372 loop {
373 let (decl, importance) = self.iter.next()?;
374
375 if importance.important() {
376 continue;
377 }
378
379 let animation = AnimationValue::from_declaration(
380 decl,
381 self.context,
382 self.style,
383 self.default_values,
384 &mut AttributeTracker::new_dummy(),
386 );
387
388 if let Some(anim) = animation {
389 return Some(anim);
390 }
391 }
392 }
393}
394
395impl fmt::Debug for PropertyDeclarationBlock {
396 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
397 self.declarations.fmt(f)
398 }
399}
400
401impl PropertyDeclarationBlock {
402 #[inline]
404 pub fn len(&self) -> usize {
405 self.declarations.len()
406 }
407
408 #[inline]
410 pub fn is_empty(&self) -> bool {
411 self.declarations.is_empty()
412 }
413
414 #[inline]
416 pub fn new() -> Self {
417 PropertyDeclarationBlock {
418 declarations: ThinVec::new(),
419 declarations_importance: SmallBitVec::new(),
420 property_ids: PropertyDeclarationIdSet::default(),
421 immutable: AtomicBool::new(false),
422 }
423 }
424
425 pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
427 let mut property_ids = PropertyDeclarationIdSet::default();
428 property_ids.insert(declaration.id());
429 let mut declarations = ThinVec::with_capacity(1);
430 declarations.push(declaration);
431 PropertyDeclarationBlock {
432 declarations,
433 declarations_importance: SmallBitVec::from_elem(1, importance.important()),
434 property_ids,
435 immutable: AtomicBool::new(false),
436 }
437 }
438
439 #[inline]
441 pub fn declarations(&self) -> &[PropertyDeclaration] {
442 &self.declarations
443 }
444
445 #[inline]
447 pub fn declarations_importance(&self) -> &SmallBitVec {
448 &self.declarations_importance
449 }
450
451 #[inline]
453 pub fn declaration_importance_iter(&self) -> DeclarationImportanceIterator<'_> {
454 DeclarationImportanceIterator::new(&self.declarations, &self.declarations_importance)
455 }
456
457 #[inline]
459 pub fn normal_declaration_iter(&self) -> impl DoubleEndedIterator<Item = &PropertyDeclaration> {
460 self.declaration_importance_iter()
461 .filter(|(_, importance)| !importance.important())
462 .map(|(declaration, _)| declaration)
463 }
464
465 #[inline]
467 pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>(
468 &'a self,
469 context: &'cx mut Context<'cx_a>,
470 style: &'a ComputedValues,
471 default_values: &'a ComputedValues,
472 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
473 AnimationValueIterator::new(self, context, style, default_values)
474 }
475
476 #[inline]
481 pub fn any_important(&self) -> bool {
482 !self.declarations_importance.all_false()
483 }
484
485 #[inline]
490 pub fn any_normal(&self) -> bool {
491 !self.declarations_importance.all_true()
492 }
493
494 #[inline]
497 pub fn property_ids(&self) -> &PropertyDeclarationIdSet {
498 &self.property_ids
499 }
500
501 #[inline]
503 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
504 self.property_ids.contains(id)
505 }
506
507 #[inline]
509 pub fn contains_any_reset(&self) -> bool {
510 self.property_ids.contains_any_reset()
511 }
512
513 #[inline]
518 pub fn get(
519 &self,
520 property: PropertyDeclarationId,
521 ) -> Option<(&PropertyDeclaration, Importance)> {
522 if !self.contains(property) {
523 return None;
524 }
525 self.declaration_importance_iter()
526 .find(|(declaration, _)| declaration.id() == property)
527 }
528
529 pub fn shorthand_to_css(
532 &self,
533 shorthand: ShorthandId,
534 dest: &mut CssStringWriter,
535 ) -> fmt::Result {
536 let mut list = SmallVec::<[&_; 10]>::new();
539 let mut important_count = 0;
540
541 for longhand in shorthand.longhands() {
543 let declaration = self.get(PropertyDeclarationId::Longhand(longhand));
545
546 match declaration {
548 Some((declaration, importance)) => {
549 list.push(declaration);
550 if importance.important() {
551 important_count += 1;
552 }
553 },
554 None => return Ok(()),
555 }
556 }
557
558 if important_count > 0 && important_count != list.len() {
561 return Ok(());
562 }
563
564 match shorthand.get_shorthand_appendable_value(&list) {
568 Some(appendable_value) => append_declaration_value(dest, appendable_value),
569 None => Ok(()),
570 }
571 }
572
573 pub fn property_value_to_css(
577 &self,
578 property: &PropertyId,
579 dest: &mut CssStringWriter,
580 ) -> fmt::Result {
581 let longhand_or_custom = match property.as_shorthand() {
585 Ok(shorthand) => return self.shorthand_to_css(shorthand, dest),
586 Err(longhand_or_custom) => longhand_or_custom,
587 };
588
589 if let Some((value, _importance)) = self.get(longhand_or_custom) {
590 value.to_css(dest)
592 } else {
593 Ok(())
595 }
596 }
597
598 pub fn property_priority(&self, property: &PropertyId) -> Importance {
600 match property.as_shorthand() {
604 Ok(shorthand) => {
605 if shorthand.longhands().all(|l| {
607 self.get(PropertyDeclarationId::Longhand(l))
608 .is_some_and(|(_, importance)| importance.important())
609 }) {
610 Importance::Important
611 } else {
612 Importance::Normal
613 }
614 },
615 Err(longhand_or_custom) => {
616 self.get(longhand_or_custom)
618 .map_or(Importance::Normal, |(_, importance)| importance)
619 },
620 }
621 }
622
623 pub fn property_value_to_typed_value_list(
627 &self,
628 property: &PropertyId,
629 ) -> Result<Option<TypedValueList>, ()> {
630 match property.as_shorthand() {
631 Ok(shorthand) => {
632 if shorthand
633 .longhands()
634 .all(|longhand| self.contains(PropertyDeclarationId::Longhand(longhand)))
635 {
636 Ok(None)
637 } else {
638 Err(())
639 }
640 },
641 Err(longhand_or_custom) => match self.get(longhand_or_custom) {
642 Some((value, _importance)) => Ok(value.to_typed_value_list()),
643 None => Err(()),
644 },
645 }
646 }
647
648 pub fn extend(
653 &mut self,
654 mut drain: SourcePropertyDeclarationDrain,
655 importance: Importance,
656 ) -> bool {
657 let all_shorthand_len = match drain.all_shorthand {
658 AllShorthand::NotSet => 0,
659 AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
660 property_counts::ALL_SHORTHAND_EXPANDED
661 },
662 };
663 let push_calls_count = drain.declarations.len() + all_shorthand_len;
664
665 self.declarations.reserve(push_calls_count);
667
668 let mut changed = false;
669 for decl in &mut drain.declarations {
670 changed |= self.push(decl, importance);
671 }
672 drain
673 .all_shorthand
674 .declarations()
675 .fold(changed, |changed, decl| {
676 changed | self.push(decl, importance)
677 })
678 }
679
680 pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
686 let id = declaration.id();
687 if !self.property_ids.insert(id) {
688 let mut index_to_remove = None;
689 for (i, slot) in self.declarations.iter_mut().enumerate() {
690 if slot.id() != id {
691 continue;
692 }
693
694 let important = self.declarations_importance[i];
695
696 if important && !importance.important() {
699 return false;
700 }
701
702 index_to_remove = Some(i);
703 break;
704 }
705
706 if let Some(index) = index_to_remove {
707 self.declarations.remove(index);
708 self.declarations_importance.remove(index);
709 self.declarations.push(declaration);
710 self.declarations_importance.push(importance.important());
711 return true;
712 }
713 }
714
715 self.declarations.push(declaration);
716 self.declarations_importance.push(importance.important());
717 true
718 }
719
720 pub fn prepare_for_update(
724 &self,
725 source_declarations: &SourcePropertyDeclaration,
726 importance: Importance,
727 updates: &mut SourcePropertyDeclarationUpdate,
728 ) -> bool {
729 debug_assert!(updates.updates.is_empty());
730 if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
732 debug_assert!(source_declarations.declarations.is_empty());
733 return source_declarations
734 .all_shorthand
735 .declarations()
736 .any(|decl| {
737 !self.contains(decl.id())
738 || self
739 .declarations
740 .iter()
741 .enumerate()
742 .find(|&(_, d)| d.id() == decl.id())
743 .is_none_or(|(i, d)| {
744 let important = self.declarations_importance[i];
745 *d != decl || important != importance.important()
746 })
747 });
748 }
749 let mut any_update = false;
751 let new_count = &mut updates.new_count;
752 let any_removal = &mut updates.any_removal;
753 let updates = &mut updates.updates;
754 updates.extend(
755 source_declarations
756 .declarations
757 .iter()
758 .map(|declaration| {
759 if !self.contains(declaration.id()) {
760 return DeclarationUpdate::Append;
761 }
762 let longhand_id = declaration.id().as_longhand();
763 if let Some(longhand_id) = longhand_id
764 && let Some(logical_group) = longhand_id.logical_group()
765 {
766 let mut needs_append = false;
767 for (pos, decl) in self.declarations.iter().enumerate().rev() {
768 let id = match decl.id().as_longhand() {
769 Some(id) => id,
770 None => continue,
771 };
772 if id == longhand_id {
773 if needs_append {
774 return DeclarationUpdate::AppendAndRemove { pos };
775 }
776 let important = self.declarations_importance[pos];
777 if decl == declaration && important == importance.important() {
778 return DeclarationUpdate::None;
779 }
780 return DeclarationUpdate::UpdateInPlace { pos };
781 }
782 if !needs_append
783 && id.logical_group() == Some(logical_group)
784 && id.is_logical() != longhand_id.is_logical()
785 {
786 needs_append = true;
787 }
788 }
789 unreachable!("Longhand should be found in loop above");
790 }
791 self.declarations
792 .iter()
793 .enumerate()
794 .find(|&(_, decl)| decl.id() == declaration.id())
795 .map_or(DeclarationUpdate::Append, |(pos, decl)| {
796 let important = self.declarations_importance[pos];
797 if decl == declaration && important == importance.important() {
798 DeclarationUpdate::None
799 } else {
800 DeclarationUpdate::UpdateInPlace { pos }
801 }
802 })
803 })
804 .inspect(|update| {
805 if matches!(update, DeclarationUpdate::None) {
806 return;
807 }
808 any_update = true;
809 match update {
810 DeclarationUpdate::Append => {
811 *new_count += 1;
812 },
813 DeclarationUpdate::AppendAndRemove { .. } => {
814 *any_removal = true;
815 },
816 _ => {},
817 }
818 }),
819 );
820 any_update
821 }
822
823 pub fn update(
825 &mut self,
826 drain: SourcePropertyDeclarationDrain,
827 importance: Importance,
828 updates: &mut SourcePropertyDeclarationUpdate,
829 ) {
830 let important = importance.important();
831 if !matches!(drain.all_shorthand, AllShorthand::NotSet) {
832 debug_assert!(updates.updates.is_empty());
833 for decl in drain.all_shorthand.declarations() {
834 let id = decl.id();
835 if self.property_ids.insert(id) {
836 self.declarations.push(decl);
837 self.declarations_importance.push(important);
838 } else {
839 let (idx, slot) = self
840 .declarations
841 .iter_mut()
842 .enumerate()
843 .find(|(_, d)| d.id() == decl.id())
844 .unwrap();
845 *slot = decl;
846 self.declarations_importance.set(idx, important);
847 }
848 }
849 return;
850 }
851
852 self.declarations.reserve(updates.new_count);
853 if updates.any_removal {
854 struct UpdateOrRemoval<'a> {
856 item: &'a mut DeclarationUpdate,
857 pos: usize,
858 remove: bool,
859 }
860 let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
861 .updates
862 .iter_mut()
863 .filter_map(|item| {
864 let (pos, remove) = match *item {
865 DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
866 DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
867 _ => return None,
868 };
869 Some(UpdateOrRemoval { item, pos, remove })
870 })
871 .collect();
872 updates_and_removals.sort_unstable_by_key(|update| update.pos);
875 updates_and_removals
876 .iter()
877 .rev()
878 .filter(|update| update.remove)
879 .for_each(|update| {
880 self.declarations.remove(update.pos);
881 self.declarations_importance.remove(update.pos);
882 });
883 let mut removed_count = 0;
885 for update in updates_and_removals.iter_mut() {
886 if update.remove {
887 removed_count += 1;
888 continue;
889 }
890 debug_assert_eq!(
891 *update.item,
892 DeclarationUpdate::UpdateInPlace { pos: update.pos }
893 );
894 *update.item = DeclarationUpdate::UpdateInPlace {
895 pos: update.pos - removed_count,
896 };
897 }
898 }
899 for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
901 match *update {
902 DeclarationUpdate::None => {},
903 DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
904 self.property_ids.insert(decl.id());
905 self.declarations.push(decl);
906 self.declarations_importance.push(important);
907 },
908 DeclarationUpdate::UpdateInPlace { pos } => {
909 self.declarations[pos] = decl;
910 self.declarations_importance.set(pos, important);
911 },
912 }
913 }
914 updates.updates.clear();
915 }
916
917 #[inline]
920 pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
921 if let Err(longhand_or_custom) = property.as_shorthand()
922 && !self.contains(longhand_or_custom)
923 {
924 return None;
925 }
926
927 self.declarations
928 .iter()
929 .position(|declaration| declaration.id().is_or_is_longhand_of(property))
930 }
931
932 #[inline]
934 fn remove_declaration_at(&mut self, i: usize) {
935 self.property_ids.remove(self.declarations[i].id());
936 self.declarations_importance.remove(i);
937 self.declarations.remove(i);
938 }
939
940 #[inline]
942 pub fn clear(&mut self) {
943 self.declarations_importance.clear();
944 self.declarations.clear();
945 self.property_ids.clear();
946 }
947
948 #[inline]
953 pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
954 debug_assert_eq!(
955 Some(first_declaration),
956 self.first_declaration_to_remove(property)
957 );
958 debug_assert!(
959 self.declarations[first_declaration]
960 .id()
961 .is_or_is_longhand_of(property)
962 );
963
964 self.remove_declaration_at(first_declaration);
965
966 let shorthand = match property.as_shorthand() {
967 Ok(s) => s,
968 Err(_longhand_or_custom) => return,
969 };
970
971 let mut i = first_declaration;
972 let mut len = self.len();
973 while i < len {
974 if !self.declarations[i].id().is_longhand_of(shorthand) {
975 i += 1;
976 continue;
977 }
978
979 self.remove_declaration_at(i);
980 len -= 1;
981 }
982 }
983
984 pub fn single_value_to_css(
986 &self,
987 property: &PropertyId,
988 dest: &mut CssStringWriter,
989 computed_values: Option<&ComputedValues>,
990 stylist: &Stylist,
991 ) -> fmt::Result {
992 if let Ok(shorthand) = property.as_shorthand() {
993 return self.shorthand_to_css(shorthand, dest);
994 }
995
996 let declaration = match self.declarations.first() {
999 Some(d) => d,
1000 None => return Err(fmt::Error),
1001 };
1002
1003 let mut rule_cache_conditions = RuleCacheConditions::default();
1004 let mut tree_counting_caches = TreeCountingCaches::default();
1005 let mut context = Context::new(
1006 StyleBuilder::new(
1007 stylist.device(),
1008 Some(stylist),
1009 computed_values,
1010 None,
1011 None,
1012 false,
1013 ),
1014 stylist.quirks_mode(),
1015 &mut rule_cache_conditions,
1016 ContainerSizeQuery::none(),
1017 RuleCascadeFlags::empty(),
1018 &DummyElementContext {},
1019 &mut tree_counting_caches,
1020 );
1021
1022 if let Some(cv) = computed_values {
1023 context.builder.substitution_functions.custom_properties =
1024 cv.custom_properties().clone();
1025 };
1026
1027 match (declaration, computed_values) {
1028 (PropertyDeclaration::WithVariables(declaration), Some(_)) => declaration
1036 .value
1037 .substitute_variables(
1038 declaration.id,
1039 &context.builder.substitution_functions,
1040 stylist,
1041 &context,
1042 &mut Default::default(),
1043 &mut AttributeTracker::new_dummy(),
1044 )
1045 .to_css(dest),
1046 (d, _) => d.to_css(dest),
1047 }
1048 }
1049
1050 pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
1052 let len = animation_value_map.len();
1053 let mut declarations = ThinVec::with_capacity(len);
1054 let mut property_ids = PropertyDeclarationIdSet::default();
1055
1056 for (property, animation_value) in animation_value_map.iter() {
1057 property_ids.insert(property.as_borrowed());
1058 declarations.push(animation_value.uncompute());
1059 }
1060
1061 PropertyDeclarationBlock {
1062 declarations,
1063 property_ids,
1064 declarations_importance: SmallBitVec::from_elem(len, false),
1065 immutable: AtomicBool::new(false),
1066 }
1067 }
1068
1069 fn has_declaration_matching(
1070 &self,
1071 property: &PropertyId,
1072 matches: impl Fn(&PropertyDeclaration) -> bool,
1073 ) -> bool {
1074 if let Err(longhand_or_custom) = property.as_shorthand()
1075 && !self.property_ids.contains(longhand_or_custom)
1076 {
1077 return false;
1078 }
1079 self.declarations
1080 .iter()
1081 .any(|decl| decl.id().is_or_is_longhand_of(property) && matches(decl))
1082 }
1083
1084 pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
1087 self.has_declaration_matching(property, |decl| decl.get_css_wide_keyword().is_some())
1088 }
1089
1090 pub fn has_unparsed_value(&self, property: &PropertyId) -> bool {
1093 self.has_declaration_matching(property, PropertyDeclaration::is_unparsed)
1094 }
1095
1096 pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
1102 let mut is_first_serialization = true; let mut already_serialized = NonCustomPropertyIdSet::new();
1114
1115 'declaration_loop: for (declaration, importance) in self.declaration_importance_iter() {
1117 let property = declaration.id();
1119 let longhand_id = match property {
1120 PropertyDeclarationId::Longhand(id) => id,
1121 PropertyDeclarationId::Custom(..) => {
1122 append_serialization(
1127 dest,
1128 &property,
1129 AppendableValue::Declaration(declaration),
1130 importance,
1131 &mut is_first_serialization,
1132 )?;
1133 continue;
1134 },
1135 };
1136
1137 if already_serialized.contains(longhand_id.into()) {
1139 continue;
1140 }
1141
1142 for shorthand in longhand_id.shorthands() {
1144 if already_serialized.contains(shorthand.into()) {
1146 continue;
1147 }
1148 already_serialized.insert(shorthand.into());
1149
1150 if shorthand.is_legacy_shorthand()
1151 && !(shorthand.allows_disabled_subproperties()
1152 && !NonCustomPropertyId::from(longhand_id).enabled_for_all_content())
1153 {
1154 continue;
1156 }
1157
1158 let longhands = {
1165 let mut ids = LonghandIdSet::new();
1168 for longhand in shorthand.longhands() {
1169 ids.insert(longhand);
1170 }
1171 ids
1172 };
1173
1174 if !self.property_ids.contains_all_longhands(&longhands) {
1179 continue;
1180 }
1181
1182 let mut current_longhands = SmallVec::<[&_; 10]>::new();
1185 let mut logical_groups = LogicalGroupSet::new();
1186 let mut saw_one = false;
1187 let mut logical_mismatch = false;
1188 let mut seen = LonghandIdSet::new();
1189 let mut important_count = 0;
1190
1191 for (declaration, importance) in self.declaration_importance_iter() {
1195 let longhand = match declaration.id() {
1196 PropertyDeclarationId::Longhand(id) => id,
1197 PropertyDeclarationId::Custom(..) => continue,
1198 };
1199
1200 if longhands.contains(longhand) {
1201 saw_one = true;
1202 if importance.important() {
1203 important_count += 1;
1204 }
1205 current_longhands.push(declaration);
1206 if shorthand != ShorthandId::All {
1207 if let Some(g) = longhand.logical_group() {
1210 logical_groups.insert(g);
1211 }
1212 seen.insert(longhand);
1213 if seen == longhands {
1214 break;
1215 }
1216 }
1217 } else if saw_one
1218 && let Some(g) = longhand.logical_group()
1219 && logical_groups.contains(g)
1220 {
1221 logical_mismatch = true;
1222 break;
1223 }
1224 }
1225
1226 let is_important = important_count > 0;
1232 if is_important && important_count != current_longhands.len() {
1233 continue;
1234 }
1235
1236 if logical_mismatch {
1244 continue;
1245 }
1246
1247 let importance = if is_important {
1248 Importance::Important
1249 } else {
1250 Importance::Normal
1251 };
1252
1253 let appendable_value =
1257 match shorthand.get_shorthand_appendable_value(¤t_longhands) {
1258 None => continue,
1259 Some(appendable_value) => appendable_value,
1260 };
1261
1262 let mut v = CssString::new();
1265 let value = match appendable_value {
1266 AppendableValue::Css(css) => {
1267 debug_assert!(!css.is_empty());
1268 appendable_value
1269 },
1270 other => {
1271 append_declaration_value(&mut v, other)?;
1272
1273 if v.is_empty() {
1277 continue;
1278 }
1279
1280 AppendableValue::Css({
1281 #[cfg(feature = "gecko")]
1283 unsafe {
1284 v.as_str_unchecked()
1285 }
1286 #[cfg(feature = "servo")]
1287 &v
1288 })
1289 },
1290 };
1291
1292 append_serialization(
1302 dest,
1303 &shorthand,
1304 value,
1305 importance,
1306 &mut is_first_serialization,
1307 )?;
1308
1309 for current_longhand in ¤t_longhands {
1313 let longhand_id = match current_longhand.id() {
1314 PropertyDeclarationId::Longhand(id) => id,
1315 PropertyDeclarationId::Custom(..) => unreachable!(),
1316 };
1317
1318 already_serialized.insert(longhand_id.into());
1320 }
1321
1322 continue 'declaration_loop;
1325 }
1326
1327 append_serialization(
1338 dest,
1339 &property,
1340 AppendableValue::Declaration(declaration),
1341 importance,
1342 &mut is_first_serialization,
1343 )?;
1344
1345 already_serialized.insert(longhand_id.into());
1348 }
1349
1350 Ok(())
1352 }
1353}
1354
1355pub enum AppendableValue<'a, 'b: 'a> {
1358 Declaration(&'a PropertyDeclaration),
1360 DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]),
1365 Css(&'a str),
1368}
1369
1370fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
1372where
1373 W: Write,
1374{
1375 if !*is_first_serialization {
1376 dest.write_char(' ')
1377 } else {
1378 *is_first_serialization = false;
1379 Ok(())
1380 }
1381}
1382
1383pub fn append_declaration_value<'a, 'b: 'a>(
1385 dest: &mut CssStringWriter,
1386 appendable_value: AppendableValue<'a, 'b>,
1387) -> fmt::Result {
1388 match appendable_value {
1389 AppendableValue::Css(css) => dest.write_str(css),
1390 AppendableValue::Declaration(decl) => decl.to_css(dest),
1391 AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
1392 shorthand.longhands_to_css(decls, dest)
1393 },
1394 }
1395}
1396
1397pub fn append_serialization<'a, 'b: 'a, N>(
1399 dest: &mut CssStringWriter,
1400 property_name: &N,
1401 appendable_value: AppendableValue<'a, 'b>,
1402 importance: Importance,
1403 is_first_serialization: &mut bool,
1404) -> fmt::Result
1405where
1406 N: ToCss,
1407{
1408 handle_first_serialization(dest, is_first_serialization)?;
1409
1410 property_name.to_css(&mut CssWriter::new(dest))?;
1411 dest.write_str(": ")?;
1412
1413 append_declaration_value(dest, appendable_value)?;
1414
1415 if importance.important() {
1416 dest.write_str(" !important")?;
1417 }
1418
1419 dest.write_char(';')
1420}
1421
1422#[inline]
1427pub fn parse_style_attribute(
1428 input: &str,
1429 url_data: &UrlExtraData,
1430 error_reporter: Option<&dyn ParseErrorReporter>,
1431 quirks_mode: QuirksMode,
1432 rule_type: CssRuleType,
1433) -> PropertyDeclarationBlock {
1434 let mut context = ParserContext::new(
1435 Origin::Author,
1436 url_data,
1437 Some(rule_type),
1438 ParsingMode::DEFAULT,
1439 quirks_mode,
1440 Default::default(),
1441 error_reporter,
1442 None,
1443 Default::default(),
1444 );
1445
1446 parse_property_declaration_list(&mut context, &mut Parser::new(input), &[])
1447}
1448
1449#[inline]
1454pub fn parse_one_declaration_into(
1455 declarations: &mut SourcePropertyDeclaration,
1456 id: PropertyId,
1457 input: &str,
1458 origin: Origin,
1459 url_data: &UrlExtraData,
1460 error_reporter: Option<&dyn ParseErrorReporter>,
1461 parsing_mode: ParsingMode,
1462 quirks_mode: QuirksMode,
1463 rule_type: CssRuleType,
1464) -> Result<(), ()> {
1465 let mut context = ParserContext::new(
1466 origin,
1467 url_data,
1468 Some(rule_type),
1469 parsing_mode,
1470 quirks_mode,
1471 Default::default(),
1472 error_reporter,
1473 None,
1474 Default::default(),
1475 );
1476
1477 let property_id_for_error_reporting = if context.error_reporting_enabled() {
1478 Some(id.clone())
1479 } else {
1480 None
1481 };
1482
1483 let mut parser = Parser::new(input);
1484 let start_position = parser.position();
1485 let start_location = parser.current_source_location();
1486 parser
1487 .parse_entirely(|parser| {
1488 PropertyDeclaration::parse_into(declarations, id, &mut context, parser)
1489 })
1490 .map_err(|err| {
1491 if context.error_reporting_enabled() {
1492 report_one_css_error(
1493 &context,
1494 None,
1495 &[],
1496 err,
1497 parser.slice_from(start_position),
1498 start_location,
1499 property_id_for_error_reporting,
1500 )
1501 }
1502 })
1503}
1504
1505struct PropertyDeclarationParser<'a, 'b: 'a, 'i> {
1507 context: &'a mut ParserContext<'b>,
1508 state: &'a mut DeclarationParserState<'i>,
1509}
1510
1511#[derive(Default)]
1515pub struct DeclarationParserState<'i> {
1516 output_block: PropertyDeclarationBlock,
1518 declarations: SourcePropertyDeclaration,
1521 importance: Importance,
1523 errors: SmallParseErrorVec<'i>,
1525 first_declaration_start: SourceLocation,
1527 last_parsed_property_id: Option<PropertyId>,
1529}
1530
1531impl<'i> DeclarationParserState<'i> {
1532 pub fn first_declaration_start(&self) -> SourceLocation {
1534 self.first_declaration_start
1535 }
1536
1537 pub fn has_parsed_declarations(&self) -> bool {
1539 !self.output_block.is_empty()
1540 }
1541
1542 pub fn take_declarations(&mut self) -> PropertyDeclarationBlock {
1544 std::mem::take(&mut self.output_block)
1545 }
1546
1547 pub fn parse_value(
1549 &mut self,
1550 context: &mut ParserContext,
1551 name: CowRcStr<'i>,
1552 input: &mut Parser<'i>,
1553 declaration_start: &ParserState,
1554 ) -> Result<(), ParseError> {
1555 let id = match PropertyId::parse(&name, context) {
1556 Ok(id) => id,
1557 Err(..) => {
1558 return Err(ParseError::custom(StyleParseErrorKind::UnknownProperty));
1559 },
1560 };
1561 if context.error_reporting_enabled() {
1562 self.last_parsed_property_id = Some(id.clone());
1563 }
1564 input.parse_until_before(Delimiter::Bang, |input| {
1565 PropertyDeclaration::parse_into(&mut self.declarations, id, context, input)
1566 })?;
1567 self.importance = match input.try_parse(parse_important) {
1568 Ok(()) => {
1569 if !context.allows_important_declarations() {
1570 return Err(ParseError::custom(
1571 StyleParseErrorKind::UnexpectedImportantDeclaration,
1572 ));
1573 }
1574 Importance::Important
1575 },
1576 Err(_) => Importance::Normal,
1577 };
1578 input.expect_exhausted()?;
1580 let has_parsed_declarations = self.has_parsed_declarations();
1581 self.output_block
1582 .extend(self.declarations.drain(), self.importance);
1583 self.last_parsed_property_id = None;
1587
1588 if !has_parsed_declarations {
1589 self.first_declaration_start = declaration_start.source_location();
1590 }
1591
1592 Ok(())
1593 }
1594
1595 #[inline]
1597 pub fn report_errors_if_needed(
1598 &mut self,
1599 context: &ParserContext,
1600 selectors: &[SelectorList<SelectorImpl>],
1601 ) {
1602 if self.errors.is_empty() {
1603 return;
1604 }
1605 self.do_report_css_errors(context, selectors);
1606 }
1607
1608 #[cold]
1609 fn do_report_css_errors(
1610 &mut self,
1611 context: &ParserContext,
1612 selectors: &[SelectorList<SelectorImpl>],
1613 ) {
1614 for (error, slice, location, property) in self.errors.drain(..) {
1615 report_one_css_error(
1616 context,
1617 Some(&self.output_block),
1618 selectors,
1619 error,
1620 slice,
1621 location,
1622 property,
1623 )
1624 }
1625 }
1626
1627 #[inline]
1629 pub fn did_error(
1630 &mut self,
1631 context: &ParserContext,
1632 error: ParseError,
1633 slice: &'i str,
1634 location: SourceLocation,
1635 ) {
1636 self.declarations.clear();
1637 if !context.error_reporting_enabled() {
1638 return;
1639 }
1640 let property = self.last_parsed_property_id.take();
1641 self.errors.push((error, slice, location, property));
1642 }
1643}
1644
1645impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1647 type Prelude = ();
1648 type AtRule = ();
1649 type Error = StyleParseErrorKind;
1650}
1651
1652impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1654 type Prelude = ();
1655 type QualifiedRule = ();
1656 type Error = StyleParseErrorKind;
1657}
1658
1659fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
1661 (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
1662}
1663
1664impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1665 type Declaration = ();
1666 type Error = StyleParseErrorKind;
1667
1668 fn parse_value(
1669 &mut self,
1670 name: CowRcStr<'i>,
1671 input: &mut Parser<'i>,
1672 declaration_start: &ParserState,
1673 ) -> Result<(), ParseError> {
1674 self.state
1675 .parse_value(self.context, name, input, declaration_start)
1676 }
1677}
1678
1679impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind>
1680 for PropertyDeclarationParser<'a, 'b, 'i>
1681{
1682 fn parse_declarations(&self) -> bool {
1683 true
1684 }
1685 fn parse_qualified(&self) -> bool {
1687 false
1688 }
1689}
1690
1691type SmallParseErrorVec<'i> =
1692 SmallVec<[(ParseError, &'i str, SourceLocation, Option<PropertyId>); 2]>;
1693
1694fn alias_of_known_property(name: &str) -> Option<PropertyId> {
1695 let mut prefixed = String::with_capacity(name.len() + 5);
1696 prefixed.push_str("-moz-");
1697 prefixed.push_str(name);
1698 PropertyId::parse_enabled_for_all_content(&prefixed).ok()
1699}
1700
1701#[cold]
1702fn report_one_css_error(
1703 context: &ParserContext,
1704 block: Option<&PropertyDeclarationBlock>,
1705 selectors: &[SelectorList<SelectorImpl>],
1706 mut error: ParseError,
1707 slice: &str,
1708 location: SourceLocation,
1709 property: Option<PropertyId>,
1710) {
1711 debug_assert!(context.error_reporting_enabled());
1712
1713 fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
1714 match property.as_shorthand() {
1715 Ok(id) => id
1716 .longhands()
1717 .all(|longhand| block.contains(PropertyDeclarationId::Longhand(longhand))),
1718 Err(longhand_or_custom) => block.contains(longhand_or_custom),
1719 }
1720 }
1721
1722 let mut error_string = Cow::Borrowed(slice);
1723 if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty) = error.kind {
1724 let name = slice.split(':').next().unwrap_or("").trim();
1727 if is_non_mozilla_vendor_identifier(name) {
1728 return;
1731 }
1732 if let Some(alias) = alias_of_known_property(name) {
1733 if let Some(block) = block
1737 && all_properties_in_block(block, &alias)
1738 {
1739 return;
1740 }
1741 }
1742 if !name.is_empty() {
1743 error_string = Cow::Borrowed(name);
1745 }
1746 }
1747
1748 if let Some(ref property) = property {
1749 if let Some(block) = block
1750 && all_properties_in_block(block, property)
1751 {
1752 return;
1753 }
1754 if !matches!(
1758 error.kind,
1759 ParseErrorKind::Custom(StyleParseErrorKind::UnexpectedImportantDeclaration)
1760 ) {
1761 error = ParseError::custom(StyleParseErrorKind::OtherInvalidValue);
1762 }
1763 if !slice.contains(':') {
1764 error_string = Cow::Owned(format!("{}: {slice}", property.to_css_string()));
1766 }
1767 }
1768
1769 let error =
1770 ContextualParseError::UnsupportedPropertyDeclaration(&error_string, error, selectors);
1771 context.log_css_error(location, error);
1772}
1773
1774pub fn parse_property_declaration_list(
1777 context: &mut ParserContext,
1778 input: &mut Parser,
1779 selectors: &[SelectorList<SelectorImpl>],
1780) -> PropertyDeclarationBlock {
1781 let mut state = DeclarationParserState::default();
1782 let mut parser = PropertyDeclarationParser {
1783 context,
1784 state: &mut state,
1785 };
1786 let mut iter = RuleBodyParser::new(input, &mut parser);
1787 while let Some(declaration) = iter.next() {
1788 match declaration {
1789 Ok(()) => {},
1790 Err((error, slice, location)) => {
1791 let parser = &mut *iter.parser;
1792 parser
1793 .state
1794 .did_error(parser.context, error, slice, location)
1795 },
1796 }
1797 }
1798 parser
1799 .state
1800 .report_errors_if_needed(parser.context, selectors);
1801 state.output_block
1802}