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::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::rule_tree::RuleCascadeFlags;
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::typed_om::TypedValueList;
34use crate::values::computed::Context;
35use cssparser::{
36 parse_important, AtRuleParser, CowRcStr, DeclarationParser, Delimiter, ParseErrorKind, Parser,
37 ParserInput, ParserState, QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser,
38 SourceLocation,
39};
40use itertools::Itertools;
41use selectors::SelectorList;
42use servo_arc::Arc;
43use smallbitvec::SmallBitVec;
44use smallvec::SmallVec;
45use std::fmt::{self, Write};
46use std::iter::Zip;
47use std::slice::Iter;
48use std::sync::atomic::AtomicBool;
49use style_traits::{
50 CssString, CssStringWriter, CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss,
51};
52use thin_vec::ThinVec;
53
54#[derive(Default)]
56pub struct AnimationDeclarations {
57 pub animations: Option<Arc<Locked<PropertyDeclarationBlock>>>,
59 pub transitions: Option<Arc<Locked<PropertyDeclarationBlock>>>,
61}
62
63impl AnimationDeclarations {
64 pub fn is_empty(&self) -> bool {
66 self.animations.is_none() && self.transitions.is_none()
67 }
68}
69
70#[derive(Clone, Copy, Debug, Eq, PartialEq)]
73enum DeclarationUpdate {
74 None,
76 Append,
78 UpdateInPlace { pos: usize },
80 AppendAndRemove { pos: usize },
83}
84
85#[derive(Default)]
88pub struct SourcePropertyDeclarationUpdate {
89 updates: SubpropertiesVec<DeclarationUpdate>,
90 new_count: usize,
91 any_removal: bool,
92}
93
94#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
98pub enum Importance {
99 Normal,
101
102 Important,
104}
105
106impl Default for Importance {
107 fn default() -> Self {
108 Self::Normal
109 }
110}
111
112impl Importance {
113 pub fn important(self) -> bool {
115 match self {
116 Self::Normal => false,
117 Self::Important => true,
118 }
119 }
120}
121
122#[derive(Clone, Debug, ToShmem, Default, MallocSizeOf)]
124pub struct PropertyDeclarationIdSet {
125 longhands: LonghandIdSet,
126 custom: PrecomputedHashSet<custom_properties::Name>,
127}
128
129impl PropertyDeclarationIdSet {
130 pub fn insert(&mut self, id: PropertyDeclarationId) -> bool {
132 match id {
133 PropertyDeclarationId::Longhand(id) => {
134 if self.longhands.contains(id) {
135 return false;
136 }
137 self.longhands.insert(id);
138 return true;
139 },
140 PropertyDeclarationId::Custom(name) => self.custom.insert((*name).clone()),
141 }
142 }
143
144 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
146 match id {
147 PropertyDeclarationId::Longhand(id) => self.longhands.contains(id),
148 PropertyDeclarationId::Custom(name) => self.custom.contains(name),
149 }
150 }
151
152 pub fn remove(&mut self, id: PropertyDeclarationId) {
154 match id {
155 PropertyDeclarationId::Longhand(id) => self.longhands.remove(id),
156 PropertyDeclarationId::Custom(name) => {
157 self.custom.remove(name);
158 },
159 }
160 }
161
162 pub fn clear(&mut self) {
164 self.longhands.clear();
165 self.custom.clear();
166 }
167
168 #[inline]
170 pub fn is_empty(&self) -> bool {
171 self.longhands.is_empty() && self.custom.is_empty()
172 }
173 #[inline]
175 pub fn contains_any_reset(&self) -> bool {
176 self.longhands.contains_any_reset()
177 }
178
179 #[inline]
181 pub fn contains_all_longhands(&self, longhands: &LonghandIdSet) -> bool {
182 self.longhands.contains_all(longhands)
183 }
184
185 #[inline]
187 pub fn contains_all(&self, properties: &PropertyDeclarationIdSet) -> bool {
188 if !self.longhands.contains_all(&properties.longhands) {
189 return false;
190 }
191 if properties.custom.len() > self.custom.len() {
192 return false;
193 }
194 properties
195 .custom
196 .iter()
197 .all(|item| self.custom.contains(item))
198 }
199
200 pub fn iter(&self) -> PropertyDeclarationIdSetIterator<'_> {
202 PropertyDeclarationIdSetIterator {
203 longhands: self.longhands.iter(),
204 custom: self.custom.iter(),
205 }
206 }
207}
208
209pub struct PropertyDeclarationIdSetIterator<'a> {
211 longhands: LonghandIdSetIterator<'a>,
212 custom: std::collections::hash_set::Iter<'a, custom_properties::Name>,
213}
214
215impl<'a> Iterator for PropertyDeclarationIdSetIterator<'a> {
216 type Item = PropertyDeclarationId<'a>;
217
218 fn next(&mut self) -> Option<Self::Item> {
219 match self.longhands.next() {
223 Some(id) => Some(PropertyDeclarationId::Longhand(id)),
224 None => match self.custom.next() {
225 Some(a) => Some(PropertyDeclarationId::Custom(a)),
226 None => None,
227 },
228 }
229 }
230}
231
232#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
234#[derive(Default)]
235pub struct PropertyDeclarationBlock {
236 declarations: ThinVec<PropertyDeclaration>,
240
241 declarations_importance: SmallBitVec,
243
244 property_ids: PropertyDeclarationIdSet,
246
247 pub immutable: AtomicBool,
251}
252
253impl to_shmem::ToShmem for PropertyDeclarationBlock {
254 fn to_shmem(&self, builder: &mut to_shmem::SharedMemoryBuilder) -> to_shmem::Result<Self> {
255 use std::mem::ManuallyDrop;
256 let declarations = self.declarations.to_shmem(builder)?;
257 let declarations_importance = self.declarations_importance.to_shmem(builder)?;
258 let property_ids = self.property_ids.to_shmem(builder)?;
259 let immutable = AtomicBool::new(true);
260
261 Ok(ManuallyDrop::new(Self {
262 declarations: ManuallyDrop::into_inner(declarations),
263 declarations_importance: ManuallyDrop::into_inner(declarations_importance),
264 property_ids: ManuallyDrop::into_inner(property_ids),
265 immutable,
266 }))
267 }
268}
269
270impl Clone for PropertyDeclarationBlock {
271 fn clone(&self) -> Self {
272 Self {
273 declarations: self.declarations.clone(),
274 declarations_importance: self.declarations_importance.clone(),
275 property_ids: self.property_ids.clone(),
276 immutable: AtomicBool::new(false),
277 }
278 }
279}
280
281impl PartialEq for PropertyDeclarationBlock {
282 fn eq(&self, other: &Self) -> bool {
283 self.declarations == other.declarations
287 && self.declarations_importance == other.declarations_importance
288 }
289}
290
291pub struct DeclarationImportanceIterator<'a> {
293 iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
294}
295
296impl<'a> Default for DeclarationImportanceIterator<'a> {
297 fn default() -> Self {
298 Self {
299 iter: [].iter().zip(smallbitvec::Iter::default()),
300 }
301 }
302}
303
304impl<'a> DeclarationImportanceIterator<'a> {
305 fn new(declarations: &'a [PropertyDeclaration], important: &'a SmallBitVec) -> Self {
307 DeclarationImportanceIterator {
308 iter: declarations.iter().zip(important.iter()),
309 }
310 }
311}
312
313impl<'a> Iterator for DeclarationImportanceIterator<'a> {
314 type Item = (&'a PropertyDeclaration, Importance);
315
316 #[inline]
317 fn next(&mut self) -> Option<Self::Item> {
318 self.iter.next().map(|(decl, important)| {
319 (
320 decl,
321 if important {
322 Importance::Important
323 } else {
324 Importance::Normal
325 },
326 )
327 })
328 }
329
330 #[inline]
331 fn size_hint(&self) -> (usize, Option<usize>) {
332 self.iter.size_hint()
333 }
334}
335
336impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
337 #[inline(always)]
338 fn next_back(&mut self) -> Option<Self::Item> {
339 self.iter.next_back().map(|(decl, important)| {
340 (
341 decl,
342 if important {
343 Importance::Important
344 } else {
345 Importance::Normal
346 },
347 )
348 })
349 }
350}
351
352pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> {
354 iter: DeclarationImportanceIterator<'a>,
355 context: &'cx mut Context<'cx_a>,
356 style: &'a ComputedValues,
357 default_values: &'a ComputedValues,
358}
359
360impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
361 fn new(
362 declarations: &'a PropertyDeclarationBlock,
363 context: &'cx mut Context<'cx_a>,
364 style: &'a ComputedValues,
365 default_values: &'a ComputedValues,
366 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
367 AnimationValueIterator {
368 iter: declarations.declaration_importance_iter(),
369 context,
370 style,
371 default_values,
372 }
373 }
374}
375
376impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
377 type Item = AnimationValue;
378 #[inline]
379 fn next(&mut self) -> Option<Self::Item> {
380 loop {
381 let (decl, importance) = self.iter.next()?;
382
383 if importance.important() {
384 continue;
385 }
386
387 let animation = AnimationValue::from_declaration(
388 decl,
389 &mut self.context,
390 self.style,
391 self.default_values,
392 &mut AttributeTracker::new_dummy(),
394 );
395
396 if let Some(anim) = animation {
397 return Some(anim);
398 }
399 }
400 }
401}
402
403impl fmt::Debug for PropertyDeclarationBlock {
404 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
405 self.declarations.fmt(f)
406 }
407}
408
409impl PropertyDeclarationBlock {
410 #[inline]
412 pub fn len(&self) -> usize {
413 self.declarations.len()
414 }
415
416 #[inline]
418 pub fn is_empty(&self) -> bool {
419 self.declarations.is_empty()
420 }
421
422 #[inline]
424 pub fn new() -> Self {
425 PropertyDeclarationBlock {
426 declarations: ThinVec::new(),
427 declarations_importance: SmallBitVec::new(),
428 property_ids: PropertyDeclarationIdSet::default(),
429 immutable: AtomicBool::new(false),
430 }
431 }
432
433 pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
435 let mut property_ids = PropertyDeclarationIdSet::default();
436 property_ids.insert(declaration.id());
437 let mut declarations = ThinVec::with_capacity(1);
438 declarations.push(declaration);
439 PropertyDeclarationBlock {
440 declarations,
441 declarations_importance: SmallBitVec::from_elem(1, importance.important()),
442 property_ids,
443 immutable: AtomicBool::new(false),
444 }
445 }
446
447 #[inline]
449 pub fn declarations(&self) -> &[PropertyDeclaration] {
450 &self.declarations
451 }
452
453 #[inline]
455 pub fn declarations_importance(&self) -> &SmallBitVec {
456 &self.declarations_importance
457 }
458
459 #[inline]
461 pub fn declaration_importance_iter(&self) -> DeclarationImportanceIterator<'_> {
462 DeclarationImportanceIterator::new(&self.declarations, &self.declarations_importance)
463 }
464
465 #[inline]
467 pub fn normal_declaration_iter<'a>(
468 &'a self,
469 ) -> impl DoubleEndedIterator<Item = &'a PropertyDeclaration> {
470 self.declaration_importance_iter()
471 .filter(|(_, importance)| !importance.important())
472 .map(|(declaration, _)| declaration)
473 }
474
475 #[inline]
477 pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>(
478 &'a self,
479 context: &'cx mut Context<'cx_a>,
480 style: &'a ComputedValues,
481 default_values: &'a ComputedValues,
482 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
483 AnimationValueIterator::new(self, context, style, default_values)
484 }
485
486 #[inline]
491 pub fn any_important(&self) -> bool {
492 !self.declarations_importance.all_false()
493 }
494
495 #[inline]
500 pub fn any_normal(&self) -> bool {
501 !self.declarations_importance.all_true()
502 }
503
504 #[inline]
507 pub fn property_ids(&self) -> &PropertyDeclarationIdSet {
508 &self.property_ids
509 }
510
511 #[inline]
513 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
514 self.property_ids.contains(id)
515 }
516
517 #[inline]
519 pub fn contains_any_reset(&self) -> bool {
520 self.property_ids.contains_any_reset()
521 }
522
523 #[inline]
528 pub fn get(
529 &self,
530 property: PropertyDeclarationId,
531 ) -> Option<(&PropertyDeclaration, Importance)> {
532 if !self.contains(property) {
533 return None;
534 }
535 self.declaration_importance_iter()
536 .find(|(declaration, _)| declaration.id() == property)
537 }
538
539 pub fn shorthand_to_css(
542 &self,
543 shorthand: ShorthandId,
544 dest: &mut CssStringWriter,
545 ) -> fmt::Result {
546 let mut list = SmallVec::<[&_; 10]>::new();
549 let mut important_count = 0;
550
551 for longhand in shorthand.longhands() {
553 let declaration = self.get(PropertyDeclarationId::Longhand(longhand));
555
556 match declaration {
558 Some((declaration, importance)) => {
559 list.push(declaration);
560 if importance.important() {
561 important_count += 1;
562 }
563 },
564 None => return Ok(()),
565 }
566 }
567
568 if important_count > 0 && important_count != list.len() {
571 return Ok(());
572 }
573
574 match shorthand.get_shorthand_appendable_value(&list) {
578 Some(appendable_value) => append_declaration_value(dest, appendable_value),
579 None => return Ok(()),
580 }
581 }
582
583 pub fn property_value_to_css(
587 &self,
588 property: &PropertyId,
589 dest: &mut CssStringWriter,
590 ) -> fmt::Result {
591 let longhand_or_custom = match property.as_shorthand() {
595 Ok(shorthand) => return self.shorthand_to_css(shorthand, dest),
596 Err(longhand_or_custom) => longhand_or_custom,
597 };
598
599 if let Some((value, _importance)) = self.get(longhand_or_custom) {
600 value.to_css(dest)
602 } else {
603 Ok(())
605 }
606 }
607
608 pub fn property_priority(&self, property: &PropertyId) -> Importance {
610 match property.as_shorthand() {
614 Ok(shorthand) => {
615 if shorthand.longhands().all(|l| {
617 self.get(PropertyDeclarationId::Longhand(l))
618 .map_or(false, |(_, importance)| importance.important())
619 }) {
620 Importance::Important
621 } else {
622 Importance::Normal
623 }
624 },
625 Err(longhand_or_custom) => {
626 self.get(longhand_or_custom)
628 .map_or(Importance::Normal, |(_, importance)| importance)
629 },
630 }
631 }
632
633 pub fn property_value_to_typed_value_list(
637 &self,
638 property: &PropertyId,
639 ) -> Result<Option<TypedValueList>, ()> {
640 match property.as_shorthand() {
641 Ok(shorthand) => {
642 if shorthand
643 .longhands()
644 .all(|longhand| self.contains(PropertyDeclarationId::Longhand(longhand)))
645 {
646 Ok(None)
647 } else {
648 Err(())
649 }
650 },
651 Err(longhand_or_custom) => match self.get(longhand_or_custom) {
652 Some((value, _importance)) => Ok(value.to_typed_value_list()),
653 None => Err(()),
654 },
655 }
656 }
657
658 pub fn extend(
663 &mut self,
664 mut drain: SourcePropertyDeclarationDrain,
665 importance: Importance,
666 ) -> bool {
667 let all_shorthand_len = match drain.all_shorthand {
668 AllShorthand::NotSet => 0,
669 AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
670 property_counts::ALL_SHORTHAND_EXPANDED
671 },
672 };
673 let push_calls_count = drain.declarations.len() + all_shorthand_len;
674
675 self.declarations.reserve(push_calls_count);
677
678 let mut changed = false;
679 for decl in &mut drain.declarations {
680 changed |= self.push(decl, importance);
681 }
682 drain
683 .all_shorthand
684 .declarations()
685 .fold(changed, |changed, decl| {
686 changed | self.push(decl, importance)
687 })
688 }
689
690 pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
696 let id = declaration.id();
697 if !self.property_ids.insert(id) {
698 let mut index_to_remove = None;
699 for (i, slot) in self.declarations.iter_mut().enumerate() {
700 if slot.id() != id {
701 continue;
702 }
703
704 let important = self.declarations_importance[i];
705
706 if important && !importance.important() {
709 return false;
710 }
711
712 index_to_remove = Some(i);
713 break;
714 }
715
716 if let Some(index) = index_to_remove {
717 self.declarations.remove(index);
718 self.declarations_importance.remove(index);
719 self.declarations.push(declaration);
720 self.declarations_importance.push(importance.important());
721 return true;
722 }
723 }
724
725 self.declarations.push(declaration);
726 self.declarations_importance.push(importance.important());
727 true
728 }
729
730 pub fn prepare_for_update(
734 &self,
735 source_declarations: &SourcePropertyDeclaration,
736 importance: Importance,
737 updates: &mut SourcePropertyDeclarationUpdate,
738 ) -> bool {
739 debug_assert!(updates.updates.is_empty());
740 if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
742 debug_assert!(source_declarations.declarations.is_empty());
743 return source_declarations
744 .all_shorthand
745 .declarations()
746 .any(|decl| {
747 !self.contains(decl.id())
748 || self
749 .declarations
750 .iter()
751 .enumerate()
752 .find(|&(_, ref d)| d.id() == decl.id())
753 .map_or(true, |(i, d)| {
754 let important = self.declarations_importance[i];
755 *d != decl || important != importance.important()
756 })
757 });
758 }
759 let mut any_update = false;
761 let new_count = &mut updates.new_count;
762 let any_removal = &mut updates.any_removal;
763 let updates = &mut updates.updates;
764 updates.extend(
765 source_declarations
766 .declarations
767 .iter()
768 .map(|declaration| {
769 if !self.contains(declaration.id()) {
770 return DeclarationUpdate::Append;
771 }
772 let longhand_id = declaration.id().as_longhand();
773 if let Some(longhand_id) = longhand_id {
774 if let Some(logical_group) = longhand_id.logical_group() {
775 let mut needs_append = false;
776 for (pos, decl) in self.declarations.iter().enumerate().rev() {
777 let id = match decl.id().as_longhand() {
778 Some(id) => id,
779 None => continue,
780 };
781 if id == longhand_id {
782 if needs_append {
783 return DeclarationUpdate::AppendAndRemove { pos };
784 }
785 let important = self.declarations_importance[pos];
786 if decl == declaration && important == importance.important() {
787 return DeclarationUpdate::None;
788 }
789 return DeclarationUpdate::UpdateInPlace { pos };
790 }
791 if !needs_append
792 && id.logical_group() == Some(logical_group)
793 && id.is_logical() != longhand_id.is_logical()
794 {
795 needs_append = true;
796 }
797 }
798 unreachable!("Longhand should be found in loop above");
799 }
800 }
801 self.declarations
802 .iter()
803 .enumerate()
804 .find(|&(_, ref decl)| decl.id() == declaration.id())
805 .map_or(DeclarationUpdate::Append, |(pos, decl)| {
806 let important = self.declarations_importance[pos];
807 if decl == declaration && important == importance.important() {
808 DeclarationUpdate::None
809 } else {
810 DeclarationUpdate::UpdateInPlace { pos }
811 }
812 })
813 })
814 .inspect(|update| {
815 if matches!(update, DeclarationUpdate::None) {
816 return;
817 }
818 any_update = true;
819 match update {
820 DeclarationUpdate::Append => {
821 *new_count += 1;
822 },
823 DeclarationUpdate::AppendAndRemove { .. } => {
824 *any_removal = true;
825 },
826 _ => {},
827 }
828 }),
829 );
830 any_update
831 }
832
833 pub fn update(
835 &mut self,
836 drain: SourcePropertyDeclarationDrain,
837 importance: Importance,
838 updates: &mut SourcePropertyDeclarationUpdate,
839 ) {
840 let important = importance.important();
841 if !matches!(drain.all_shorthand, AllShorthand::NotSet) {
842 debug_assert!(updates.updates.is_empty());
843 for decl in drain.all_shorthand.declarations() {
844 let id = decl.id();
845 if self.property_ids.insert(id) {
846 self.declarations.push(decl);
847 self.declarations_importance.push(important);
848 } else {
849 let (idx, slot) = self
850 .declarations
851 .iter_mut()
852 .enumerate()
853 .find(|&(_, ref d)| d.id() == decl.id())
854 .unwrap();
855 *slot = decl;
856 self.declarations_importance.set(idx, important);
857 }
858 }
859 return;
860 }
861
862 self.declarations.reserve(updates.new_count);
863 if updates.any_removal {
864 struct UpdateOrRemoval<'a> {
866 item: &'a mut DeclarationUpdate,
867 pos: usize,
868 remove: bool,
869 }
870 let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
871 .updates
872 .iter_mut()
873 .filter_map(|item| {
874 let (pos, remove) = match *item {
875 DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
876 DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
877 _ => return None,
878 };
879 Some(UpdateOrRemoval { item, pos, remove })
880 })
881 .collect();
882 updates_and_removals.sort_unstable_by_key(|update| update.pos);
885 updates_and_removals
886 .iter()
887 .rev()
888 .filter(|update| update.remove)
889 .for_each(|update| {
890 self.declarations.remove(update.pos);
891 self.declarations_importance.remove(update.pos);
892 });
893 let mut removed_count = 0;
895 for update in updates_and_removals.iter_mut() {
896 if update.remove {
897 removed_count += 1;
898 continue;
899 }
900 debug_assert_eq!(
901 *update.item,
902 DeclarationUpdate::UpdateInPlace { pos: update.pos }
903 );
904 *update.item = DeclarationUpdate::UpdateInPlace {
905 pos: update.pos - removed_count,
906 };
907 }
908 }
909 for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
911 match *update {
912 DeclarationUpdate::None => {},
913 DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
914 self.property_ids.insert(decl.id());
915 self.declarations.push(decl);
916 self.declarations_importance.push(important);
917 },
918 DeclarationUpdate::UpdateInPlace { pos } => {
919 self.declarations[pos] = decl;
920 self.declarations_importance.set(pos, important);
921 },
922 }
923 }
924 updates.updates.clear();
925 }
926
927 #[inline]
930 pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
931 if let Err(longhand_or_custom) = property.as_shorthand() {
932 if !self.contains(longhand_or_custom) {
933 return None;
934 }
935 }
936
937 self.declarations
938 .iter()
939 .position(|declaration| declaration.id().is_or_is_longhand_of(property))
940 }
941
942 #[inline]
944 fn remove_declaration_at(&mut self, i: usize) {
945 self.property_ids.remove(self.declarations[i].id());
946 self.declarations_importance.remove(i);
947 self.declarations.remove(i);
948 }
949
950 #[inline]
952 pub fn clear(&mut self) {
953 self.declarations_importance.clear();
954 self.declarations.clear();
955 self.property_ids.clear();
956 }
957
958 #[inline]
963 pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
964 debug_assert_eq!(
965 Some(first_declaration),
966 self.first_declaration_to_remove(property)
967 );
968 debug_assert!(self.declarations[first_declaration]
969 .id()
970 .is_or_is_longhand_of(property));
971
972 self.remove_declaration_at(first_declaration);
973
974 let shorthand = match property.as_shorthand() {
975 Ok(s) => s,
976 Err(_longhand_or_custom) => return,
977 };
978
979 let mut i = first_declaration;
980 let mut len = self.len();
981 while i < len {
982 if !self.declarations[i].id().is_longhand_of(shorthand) {
983 i += 1;
984 continue;
985 }
986
987 self.remove_declaration_at(i);
988 len -= 1;
989 }
990 }
991
992 pub fn single_value_to_css(
994 &self,
995 property: &PropertyId,
996 dest: &mut CssStringWriter,
997 computed_values: Option<&ComputedValues>,
998 stylist: &Stylist,
999 ) -> fmt::Result {
1000 if let Ok(shorthand) = property.as_shorthand() {
1001 return self.shorthand_to_css(shorthand, dest);
1002 }
1003
1004 let declaration = match self.declarations.get(0) {
1007 Some(d) => d,
1008 None => return Err(fmt::Error),
1009 };
1010
1011 let mut rule_cache_conditions = RuleCacheConditions::default();
1012 let mut context = Context::new(
1013 StyleBuilder::new(
1014 stylist.device(),
1015 Some(stylist),
1016 computed_values,
1017 None,
1018 None,
1019 false,
1020 ),
1021 stylist.quirks_mode(),
1022 &mut rule_cache_conditions,
1023 ContainerSizeQuery::none(),
1024 RuleCascadeFlags::empty(),
1025 );
1026
1027 if let Some(cv) = computed_values {
1028 context.builder.substitution_functions.custom_properties =
1029 cv.custom_properties().clone();
1030 };
1031
1032 match (declaration, computed_values) {
1033 (&PropertyDeclaration::WithVariables(ref declaration), Some(_)) => declaration
1041 .value
1042 .substitute_variables(
1043 declaration.id,
1044 &context.builder.substitution_functions,
1045 stylist,
1046 &context,
1047 &mut Default::default(),
1048 &mut AttributeTracker::new_dummy(),
1049 )
1050 .to_css(dest),
1051 (ref d, _) => d.to_css(dest),
1052 }
1053 }
1054
1055 pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
1057 let len = animation_value_map.len();
1058 let mut declarations = ThinVec::with_capacity(len);
1059 let mut property_ids = PropertyDeclarationIdSet::default();
1060
1061 for (property, animation_value) in animation_value_map.iter() {
1062 property_ids.insert(property.as_borrowed());
1063 declarations.push(animation_value.uncompute());
1064 }
1065
1066 PropertyDeclarationBlock {
1067 declarations,
1068 property_ids,
1069 declarations_importance: SmallBitVec::from_elem(len, false),
1070 immutable: AtomicBool::new(false),
1071 }
1072 }
1073
1074 pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
1077 if let Err(longhand_or_custom) = property.as_shorthand() {
1078 if !self.property_ids.contains(longhand_or_custom) {
1079 return false;
1080 }
1081 }
1082 self.declarations.iter().any(|decl| {
1083 decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
1084 })
1085 }
1086
1087 pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
1093 let mut is_first_serialization = true; let mut already_serialized = NonCustomPropertyIdSet::new();
1105
1106 'declaration_loop: for (declaration, importance) in self.declaration_importance_iter() {
1108 let property = declaration.id();
1110 let longhand_id = match property {
1111 PropertyDeclarationId::Longhand(id) => id,
1112 PropertyDeclarationId::Custom(..) => {
1113 append_serialization(
1118 dest,
1119 &property,
1120 AppendableValue::Declaration(declaration),
1121 importance,
1122 &mut is_first_serialization,
1123 )?;
1124 continue;
1125 },
1126 };
1127
1128 if already_serialized.contains(longhand_id.into()) {
1130 continue;
1131 }
1132
1133 for shorthand in longhand_id.shorthands() {
1135 if already_serialized.contains(shorthand.into()) {
1137 continue;
1138 }
1139 already_serialized.insert(shorthand.into());
1140
1141 if shorthand.is_legacy_shorthand() {
1142 continue;
1143 }
1144
1145 let longhands = {
1152 let mut ids = LonghandIdSet::new();
1155 for longhand in shorthand.longhands() {
1156 ids.insert(longhand);
1157 }
1158 ids
1159 };
1160
1161 if !self.property_ids.contains_all_longhands(&longhands) {
1166 continue;
1167 }
1168
1169 let mut current_longhands = SmallVec::<[&_; 10]>::new();
1172 let mut logical_groups = LogicalGroupSet::new();
1173 let mut saw_one = false;
1174 let mut logical_mismatch = false;
1175 let mut seen = LonghandIdSet::new();
1176 let mut important_count = 0;
1177
1178 for (declaration, importance) in self.declaration_importance_iter() {
1182 let longhand = match declaration.id() {
1183 PropertyDeclarationId::Longhand(id) => id,
1184 PropertyDeclarationId::Custom(..) => continue,
1185 };
1186
1187 if longhands.contains(longhand) {
1188 saw_one = true;
1189 if importance.important() {
1190 important_count += 1;
1191 }
1192 current_longhands.push(declaration);
1193 if shorthand != ShorthandId::All {
1194 if let Some(g) = longhand.logical_group() {
1197 logical_groups.insert(g);
1198 }
1199 seen.insert(longhand);
1200 if seen == longhands {
1201 break;
1202 }
1203 }
1204 } else if saw_one {
1205 if let Some(g) = longhand.logical_group() {
1206 if logical_groups.contains(g) {
1207 logical_mismatch = true;
1208 break;
1209 }
1210 }
1211 }
1212 }
1213
1214 let is_important = important_count > 0;
1220 if is_important && important_count != current_longhands.len() {
1221 continue;
1222 }
1223
1224 if logical_mismatch {
1232 continue;
1233 }
1234
1235 let importance = if is_important {
1236 Importance::Important
1237 } else {
1238 Importance::Normal
1239 };
1240
1241 let appendable_value =
1245 match shorthand.get_shorthand_appendable_value(¤t_longhands) {
1246 None => continue,
1247 Some(appendable_value) => appendable_value,
1248 };
1249
1250 let mut v = CssString::new();
1253 let value = match appendable_value {
1254 AppendableValue::Css(css) => {
1255 debug_assert!(!css.is_empty());
1256 appendable_value
1257 },
1258 other => {
1259 append_declaration_value(&mut v, other)?;
1260
1261 if v.is_empty() {
1265 continue;
1266 }
1267
1268 AppendableValue::Css({
1269 #[cfg(feature = "gecko")]
1271 unsafe {
1272 v.as_str_unchecked()
1273 }
1274 #[cfg(feature = "servo")]
1275 &v
1276 })
1277 },
1278 };
1279
1280 append_serialization(
1290 dest,
1291 &shorthand,
1292 value,
1293 importance,
1294 &mut is_first_serialization,
1295 )?;
1296
1297 for current_longhand in ¤t_longhands {
1301 let longhand_id = match current_longhand.id() {
1302 PropertyDeclarationId::Longhand(id) => id,
1303 PropertyDeclarationId::Custom(..) => unreachable!(),
1304 };
1305
1306 already_serialized.insert(longhand_id.into());
1308 }
1309
1310 continue 'declaration_loop;
1313 }
1314
1315 append_serialization(
1326 dest,
1327 &property,
1328 AppendableValue::Declaration(declaration),
1329 importance,
1330 &mut is_first_serialization,
1331 )?;
1332
1333 already_serialized.insert(longhand_id.into());
1336 }
1337
1338 Ok(())
1340 }
1341}
1342
1343pub enum AppendableValue<'a, 'b: 'a> {
1346 Declaration(&'a PropertyDeclaration),
1348 DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]),
1353 Css(&'a str),
1356}
1357
1358fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
1360where
1361 W: Write,
1362{
1363 if !*is_first_serialization {
1364 dest.write_char(' ')
1365 } else {
1366 *is_first_serialization = false;
1367 Ok(())
1368 }
1369}
1370
1371pub fn append_declaration_value<'a, 'b: 'a>(
1373 dest: &mut CssStringWriter,
1374 appendable_value: AppendableValue<'a, 'b>,
1375) -> fmt::Result {
1376 match appendable_value {
1377 AppendableValue::Css(css) => dest.write_str(css),
1378 AppendableValue::Declaration(decl) => decl.to_css(dest),
1379 AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
1380 shorthand.longhands_to_css(decls, dest)
1381 },
1382 }
1383}
1384
1385pub fn append_serialization<'a, 'b: 'a, N>(
1387 dest: &mut CssStringWriter,
1388 property_name: &N,
1389 appendable_value: AppendableValue<'a, 'b>,
1390 importance: Importance,
1391 is_first_serialization: &mut bool,
1392) -> fmt::Result
1393where
1394 N: ToCss,
1395{
1396 handle_first_serialization(dest, is_first_serialization)?;
1397
1398 property_name.to_css(&mut CssWriter::new(dest))?;
1399 dest.write_str(": ")?;
1400
1401 append_declaration_value(dest, appendable_value)?;
1402
1403 if importance.important() {
1404 dest.write_str(" !important")?;
1405 }
1406
1407 dest.write_char(';')
1408}
1409
1410#[inline]
1415pub fn parse_style_attribute(
1416 input: &str,
1417 url_data: &UrlExtraData,
1418 error_reporter: Option<&dyn ParseErrorReporter>,
1419 quirks_mode: QuirksMode,
1420 rule_type: CssRuleType,
1421) -> PropertyDeclarationBlock {
1422 let context = ParserContext::new(
1423 Origin::Author,
1424 url_data,
1425 Some(rule_type),
1426 ParsingMode::DEFAULT,
1427 quirks_mode,
1428 Default::default(),
1429 error_reporter,
1430 None,
1431 Default::default(),
1432 );
1433
1434 let mut input = ParserInput::new(input);
1435 parse_property_declaration_list(&context, &mut Parser::new(&mut input), &[])
1436}
1437
1438#[inline]
1443pub fn parse_one_declaration_into(
1444 declarations: &mut SourcePropertyDeclaration,
1445 id: PropertyId,
1446 input: &str,
1447 origin: Origin,
1448 url_data: &UrlExtraData,
1449 error_reporter: Option<&dyn ParseErrorReporter>,
1450 parsing_mode: ParsingMode,
1451 quirks_mode: QuirksMode,
1452 rule_type: CssRuleType,
1453) -> Result<(), ()> {
1454 let context = ParserContext::new(
1455 origin,
1456 url_data,
1457 Some(rule_type),
1458 parsing_mode,
1459 quirks_mode,
1460 Default::default(),
1461 error_reporter,
1462 None,
1463 Default::default(),
1464 );
1465
1466 let property_id_for_error_reporting = if context.error_reporting_enabled() {
1467 Some(id.clone())
1468 } else {
1469 None
1470 };
1471
1472 let mut input = ParserInput::new(input);
1473 let mut parser = Parser::new(&mut input);
1474 let start_position = parser.position();
1475 parser
1476 .parse_entirely(|parser| {
1477 PropertyDeclaration::parse_into(declarations, id, &context, parser)
1478 })
1479 .map_err(|err| {
1480 if context.error_reporting_enabled() {
1481 report_one_css_error(
1482 &context,
1483 None,
1484 &[],
1485 err,
1486 parser.slice_from(start_position),
1487 property_id_for_error_reporting,
1488 )
1489 }
1490 })
1491}
1492
1493struct PropertyDeclarationParser<'a, 'b: 'a, 'i> {
1495 context: &'a ParserContext<'b>,
1496 state: &'a mut DeclarationParserState<'i>,
1497}
1498
1499#[derive(Default)]
1503pub struct DeclarationParserState<'i> {
1504 output_block: PropertyDeclarationBlock,
1506 declarations: SourcePropertyDeclaration,
1509 importance: Importance,
1511 errors: SmallParseErrorVec<'i>,
1513 first_declaration_start: SourceLocation,
1515 last_parsed_property_id: Option<PropertyId>,
1517}
1518
1519impl<'i> DeclarationParserState<'i> {
1520 pub fn first_declaration_start(&self) -> SourceLocation {
1522 self.first_declaration_start
1523 }
1524
1525 pub fn has_parsed_declarations(&self) -> bool {
1527 !self.output_block.is_empty()
1528 }
1529
1530 pub fn take_declarations(&mut self) -> PropertyDeclarationBlock {
1532 std::mem::take(&mut self.output_block)
1533 }
1534
1535 pub fn parse_value<'t>(
1537 &mut self,
1538 context: &ParserContext,
1539 name: CowRcStr<'i>,
1540 input: &mut Parser<'i, 't>,
1541 declaration_start: &ParserState,
1542 ) -> Result<(), ParseError<'i>> {
1543 let id = match PropertyId::parse(&name, context) {
1544 Ok(id) => id,
1545 Err(..) => {
1546 return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
1547 },
1548 };
1549 if context.error_reporting_enabled() {
1550 self.last_parsed_property_id = Some(id.clone());
1551 }
1552 input.parse_until_before(Delimiter::Bang, |input| {
1553 PropertyDeclaration::parse_into(&mut self.declarations, id, context, input)
1554 })?;
1555 self.importance = match input.try_parse(parse_important) {
1556 Ok(()) => {
1557 if !context.allows_important_declarations() {
1558 return Err(
1559 input.new_custom_error(StyleParseErrorKind::UnexpectedImportantDeclaration)
1560 );
1561 }
1562 Importance::Important
1563 },
1564 Err(_) => Importance::Normal,
1565 };
1566 input.expect_exhausted()?;
1568 let has_parsed_declarations = self.has_parsed_declarations();
1569 self.output_block
1570 .extend(self.declarations.drain(), self.importance);
1571 self.last_parsed_property_id = None;
1575
1576 if !has_parsed_declarations {
1577 self.first_declaration_start = declaration_start.source_location();
1578 }
1579
1580 Ok(())
1581 }
1582
1583 #[inline]
1585 pub fn report_errors_if_needed(
1586 &mut self,
1587 context: &ParserContext,
1588 selectors: &[SelectorList<SelectorImpl>],
1589 ) {
1590 if self.errors.is_empty() {
1591 return;
1592 }
1593 self.do_report_css_errors(context, selectors);
1594 }
1595
1596 #[cold]
1597 fn do_report_css_errors(
1598 &mut self,
1599 context: &ParserContext,
1600 selectors: &[SelectorList<SelectorImpl>],
1601 ) {
1602 for (error, slice, property) in self.errors.drain(..) {
1603 report_one_css_error(
1604 context,
1605 Some(&self.output_block),
1606 selectors,
1607 error,
1608 slice,
1609 property,
1610 )
1611 }
1612 }
1613
1614 #[inline]
1616 pub fn did_error(&mut self, context: &ParserContext, error: ParseError<'i>, slice: &'i str) {
1617 self.declarations.clear();
1618 if !context.error_reporting_enabled() {
1619 return;
1620 }
1621 let property = self.last_parsed_property_id.take();
1622 self.errors.push((error, slice, property));
1623 }
1624}
1625
1626impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1628 type Prelude = ();
1629 type AtRule = ();
1630 type Error = StyleParseErrorKind<'i>;
1631}
1632
1633impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1635 type Prelude = ();
1636 type QualifiedRule = ();
1637 type Error = StyleParseErrorKind<'i>;
1638}
1639
1640fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
1642 (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
1643}
1644
1645impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1646 type Declaration = ();
1647 type Error = StyleParseErrorKind<'i>;
1648
1649 fn parse_value<'t>(
1650 &mut self,
1651 name: CowRcStr<'i>,
1652 input: &mut Parser<'i, 't>,
1653 declaration_start: &ParserState,
1654 ) -> Result<(), ParseError<'i>> {
1655 self.state
1656 .parse_value(self.context, name, input, declaration_start)
1657 }
1658}
1659
1660impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>>
1661 for PropertyDeclarationParser<'a, 'b, 'i>
1662{
1663 fn parse_declarations(&self) -> bool {
1664 true
1665 }
1666 fn parse_qualified(&self) -> bool {
1668 false
1669 }
1670}
1671
1672type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
1673
1674fn alias_of_known_property(name: &str) -> Option<PropertyId> {
1675 let mut prefixed = String::with_capacity(name.len() + 5);
1676 prefixed.push_str("-moz-");
1677 prefixed.push_str(name);
1678 PropertyId::parse_enabled_for_all_content(&prefixed).ok()
1679}
1680
1681#[cold]
1682fn report_one_css_error<'i>(
1683 context: &ParserContext,
1684 block: Option<&PropertyDeclarationBlock>,
1685 selectors: &[SelectorList<SelectorImpl>],
1686 mut error: ParseError<'i>,
1687 slice: &str,
1688 property: Option<PropertyId>,
1689) {
1690 debug_assert!(context.error_reporting_enabled());
1691
1692 fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
1693 match property.as_shorthand() {
1694 Ok(id) => id
1695 .longhands()
1696 .all(|longhand| block.contains(PropertyDeclarationId::Longhand(longhand))),
1697 Err(longhand_or_custom) => block.contains(longhand_or_custom),
1698 }
1699 }
1700
1701 if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(ref name)) = error.kind {
1702 if is_non_mozilla_vendor_identifier(name) {
1703 return;
1706 }
1707 if let Some(alias) = alias_of_known_property(name) {
1708 if let Some(block) = block {
1712 if all_properties_in_block(block, &alias) {
1713 return;
1714 }
1715 }
1716 }
1717 }
1718
1719 if let Some(ref property) = property {
1720 if let Some(block) = block {
1721 if all_properties_in_block(block, property) {
1722 return;
1723 }
1724 }
1725 if !matches!(
1729 error.kind,
1730 ParseErrorKind::Custom(StyleParseErrorKind::UnexpectedImportantDeclaration)
1731 ) {
1732 error = match *property {
1733 PropertyId::Custom(ref c) => {
1734 StyleParseErrorKind::new_invalid(format!("--{}", c), error)
1735 },
1736 _ => StyleParseErrorKind::new_invalid(
1737 property.non_custom_id().unwrap().name(),
1738 error,
1739 ),
1740 };
1741 }
1742 }
1743
1744 let location = error.location;
1745 let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
1746 context.log_css_error(location, error);
1747}
1748
1749pub fn parse_property_declaration_list(
1752 context: &ParserContext,
1753 input: &mut Parser,
1754 selectors: &[SelectorList<SelectorImpl>],
1755) -> PropertyDeclarationBlock {
1756 let mut state = DeclarationParserState::default();
1757 let mut parser = PropertyDeclarationParser {
1758 context,
1759 state: &mut state,
1760 };
1761 let mut iter = RuleBodyParser::new(input, &mut parser);
1762 while let Some(declaration) = iter.next() {
1763 match declaration {
1764 Ok(()) => {},
1765 Err((error, slice)) => iter.parser.state.did_error(context, error, slice),
1766 }
1767 }
1768 parser.state.report_errors_if_needed(context, selectors);
1769 state.output_block
1770}