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, TreeCountingCaches};
16use crate::custom_properties;
17use crate::derives::*;
18use crate::dom::{AttributeTracker, DummyElementContext};
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 tree_counting_caches = TreeCountingCaches::default();
1013 let mut context = Context::new(
1014 StyleBuilder::new(
1015 stylist.device(),
1016 Some(stylist),
1017 computed_values,
1018 None,
1019 None,
1020 false,
1021 ),
1022 stylist.quirks_mode(),
1023 &mut rule_cache_conditions,
1024 ContainerSizeQuery::none(),
1025 RuleCascadeFlags::empty(),
1026 &DummyElementContext {},
1027 &mut tree_counting_caches,
1028 );
1029
1030 if let Some(cv) = computed_values {
1031 context.builder.substitution_functions.custom_properties =
1032 cv.custom_properties().clone();
1033 };
1034
1035 match (declaration, computed_values) {
1036 (&PropertyDeclaration::WithVariables(ref declaration), Some(_)) => declaration
1044 .value
1045 .substitute_variables(
1046 declaration.id,
1047 &context.builder.substitution_functions,
1048 stylist,
1049 &context,
1050 &mut Default::default(),
1051 &mut AttributeTracker::new_dummy(),
1052 )
1053 .to_css(dest),
1054 (ref d, _) => d.to_css(dest),
1055 }
1056 }
1057
1058 pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
1060 let len = animation_value_map.len();
1061 let mut declarations = ThinVec::with_capacity(len);
1062 let mut property_ids = PropertyDeclarationIdSet::default();
1063
1064 for (property, animation_value) in animation_value_map.iter() {
1065 property_ids.insert(property.as_borrowed());
1066 declarations.push(animation_value.uncompute());
1067 }
1068
1069 PropertyDeclarationBlock {
1070 declarations,
1071 property_ids,
1072 declarations_importance: SmallBitVec::from_elem(len, false),
1073 immutable: AtomicBool::new(false),
1074 }
1075 }
1076
1077 pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
1080 if let Err(longhand_or_custom) = property.as_shorthand() {
1081 if !self.property_ids.contains(longhand_or_custom) {
1082 return false;
1083 }
1084 }
1085 self.declarations.iter().any(|decl| {
1086 decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
1087 })
1088 }
1089
1090 pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
1096 let mut is_first_serialization = true; let mut already_serialized = NonCustomPropertyIdSet::new();
1108
1109 'declaration_loop: for (declaration, importance) in self.declaration_importance_iter() {
1111 let property = declaration.id();
1113 let longhand_id = match property {
1114 PropertyDeclarationId::Longhand(id) => id,
1115 PropertyDeclarationId::Custom(..) => {
1116 append_serialization(
1121 dest,
1122 &property,
1123 AppendableValue::Declaration(declaration),
1124 importance,
1125 &mut is_first_serialization,
1126 )?;
1127 continue;
1128 },
1129 };
1130
1131 if already_serialized.contains(longhand_id.into()) {
1133 continue;
1134 }
1135
1136 for shorthand in longhand_id.shorthands() {
1138 if already_serialized.contains(shorthand.into()) {
1140 continue;
1141 }
1142 already_serialized.insert(shorthand.into());
1143
1144 if shorthand.is_legacy_shorthand() {
1145 continue;
1146 }
1147
1148 let longhands = {
1155 let mut ids = LonghandIdSet::new();
1158 for longhand in shorthand.longhands() {
1159 ids.insert(longhand);
1160 }
1161 ids
1162 };
1163
1164 if !self.property_ids.contains_all_longhands(&longhands) {
1169 continue;
1170 }
1171
1172 let mut current_longhands = SmallVec::<[&_; 10]>::new();
1175 let mut logical_groups = LogicalGroupSet::new();
1176 let mut saw_one = false;
1177 let mut logical_mismatch = false;
1178 let mut seen = LonghandIdSet::new();
1179 let mut important_count = 0;
1180
1181 for (declaration, importance) in self.declaration_importance_iter() {
1185 let longhand = match declaration.id() {
1186 PropertyDeclarationId::Longhand(id) => id,
1187 PropertyDeclarationId::Custom(..) => continue,
1188 };
1189
1190 if longhands.contains(longhand) {
1191 saw_one = true;
1192 if importance.important() {
1193 important_count += 1;
1194 }
1195 current_longhands.push(declaration);
1196 if shorthand != ShorthandId::All {
1197 if let Some(g) = longhand.logical_group() {
1200 logical_groups.insert(g);
1201 }
1202 seen.insert(longhand);
1203 if seen == longhands {
1204 break;
1205 }
1206 }
1207 } else if saw_one {
1208 if let Some(g) = longhand.logical_group() {
1209 if logical_groups.contains(g) {
1210 logical_mismatch = true;
1211 break;
1212 }
1213 }
1214 }
1215 }
1216
1217 let is_important = important_count > 0;
1223 if is_important && important_count != current_longhands.len() {
1224 continue;
1225 }
1226
1227 if logical_mismatch {
1235 continue;
1236 }
1237
1238 let importance = if is_important {
1239 Importance::Important
1240 } else {
1241 Importance::Normal
1242 };
1243
1244 let appendable_value =
1248 match shorthand.get_shorthand_appendable_value(¤t_longhands) {
1249 None => continue,
1250 Some(appendable_value) => appendable_value,
1251 };
1252
1253 let mut v = CssString::new();
1256 let value = match appendable_value {
1257 AppendableValue::Css(css) => {
1258 debug_assert!(!css.is_empty());
1259 appendable_value
1260 },
1261 other => {
1262 append_declaration_value(&mut v, other)?;
1263
1264 if v.is_empty() {
1268 continue;
1269 }
1270
1271 AppendableValue::Css({
1272 #[cfg(feature = "gecko")]
1274 unsafe {
1275 v.as_str_unchecked()
1276 }
1277 #[cfg(feature = "servo")]
1278 &v
1279 })
1280 },
1281 };
1282
1283 append_serialization(
1293 dest,
1294 &shorthand,
1295 value,
1296 importance,
1297 &mut is_first_serialization,
1298 )?;
1299
1300 for current_longhand in ¤t_longhands {
1304 let longhand_id = match current_longhand.id() {
1305 PropertyDeclarationId::Longhand(id) => id,
1306 PropertyDeclarationId::Custom(..) => unreachable!(),
1307 };
1308
1309 already_serialized.insert(longhand_id.into());
1311 }
1312
1313 continue 'declaration_loop;
1316 }
1317
1318 append_serialization(
1329 dest,
1330 &property,
1331 AppendableValue::Declaration(declaration),
1332 importance,
1333 &mut is_first_serialization,
1334 )?;
1335
1336 already_serialized.insert(longhand_id.into());
1339 }
1340
1341 Ok(())
1343 }
1344}
1345
1346pub enum AppendableValue<'a, 'b: 'a> {
1349 Declaration(&'a PropertyDeclaration),
1351 DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]),
1356 Css(&'a str),
1359}
1360
1361fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
1363where
1364 W: Write,
1365{
1366 if !*is_first_serialization {
1367 dest.write_char(' ')
1368 } else {
1369 *is_first_serialization = false;
1370 Ok(())
1371 }
1372}
1373
1374pub fn append_declaration_value<'a, 'b: 'a>(
1376 dest: &mut CssStringWriter,
1377 appendable_value: AppendableValue<'a, 'b>,
1378) -> fmt::Result {
1379 match appendable_value {
1380 AppendableValue::Css(css) => dest.write_str(css),
1381 AppendableValue::Declaration(decl) => decl.to_css(dest),
1382 AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
1383 shorthand.longhands_to_css(decls, dest)
1384 },
1385 }
1386}
1387
1388pub fn append_serialization<'a, 'b: 'a, N>(
1390 dest: &mut CssStringWriter,
1391 property_name: &N,
1392 appendable_value: AppendableValue<'a, 'b>,
1393 importance: Importance,
1394 is_first_serialization: &mut bool,
1395) -> fmt::Result
1396where
1397 N: ToCss,
1398{
1399 handle_first_serialization(dest, is_first_serialization)?;
1400
1401 property_name.to_css(&mut CssWriter::new(dest))?;
1402 dest.write_str(": ")?;
1403
1404 append_declaration_value(dest, appendable_value)?;
1405
1406 if importance.important() {
1407 dest.write_str(" !important")?;
1408 }
1409
1410 dest.write_char(';')
1411}
1412
1413#[inline]
1418pub fn parse_style_attribute(
1419 input: &str,
1420 url_data: &UrlExtraData,
1421 error_reporter: Option<&dyn ParseErrorReporter>,
1422 quirks_mode: QuirksMode,
1423 rule_type: CssRuleType,
1424) -> PropertyDeclarationBlock {
1425 let context = ParserContext::new(
1426 Origin::Author,
1427 url_data,
1428 Some(rule_type),
1429 ParsingMode::DEFAULT,
1430 quirks_mode,
1431 Default::default(),
1432 error_reporter,
1433 None,
1434 Default::default(),
1435 );
1436
1437 let mut input = ParserInput::new(input);
1438 parse_property_declaration_list(&context, &mut Parser::new(&mut input), &[])
1439}
1440
1441#[inline]
1446pub fn parse_one_declaration_into(
1447 declarations: &mut SourcePropertyDeclaration,
1448 id: PropertyId,
1449 input: &str,
1450 origin: Origin,
1451 url_data: &UrlExtraData,
1452 error_reporter: Option<&dyn ParseErrorReporter>,
1453 parsing_mode: ParsingMode,
1454 quirks_mode: QuirksMode,
1455 rule_type: CssRuleType,
1456) -> Result<(), ()> {
1457 let context = ParserContext::new(
1458 origin,
1459 url_data,
1460 Some(rule_type),
1461 parsing_mode,
1462 quirks_mode,
1463 Default::default(),
1464 error_reporter,
1465 None,
1466 Default::default(),
1467 );
1468
1469 let property_id_for_error_reporting = if context.error_reporting_enabled() {
1470 Some(id.clone())
1471 } else {
1472 None
1473 };
1474
1475 let mut input = ParserInput::new(input);
1476 let mut parser = Parser::new(&mut input);
1477 let start_position = parser.position();
1478 parser
1479 .parse_entirely(|parser| {
1480 PropertyDeclaration::parse_into(declarations, id, &context, parser)
1481 })
1482 .map_err(|err| {
1483 if context.error_reporting_enabled() {
1484 report_one_css_error(
1485 &context,
1486 None,
1487 &[],
1488 err,
1489 parser.slice_from(start_position),
1490 property_id_for_error_reporting,
1491 )
1492 }
1493 })
1494}
1495
1496struct PropertyDeclarationParser<'a, 'b: 'a, 'i> {
1498 context: &'a ParserContext<'b>,
1499 state: &'a mut DeclarationParserState<'i>,
1500}
1501
1502#[derive(Default)]
1506pub struct DeclarationParserState<'i> {
1507 output_block: PropertyDeclarationBlock,
1509 declarations: SourcePropertyDeclaration,
1512 importance: Importance,
1514 errors: SmallParseErrorVec<'i>,
1516 first_declaration_start: SourceLocation,
1518 last_parsed_property_id: Option<PropertyId>,
1520}
1521
1522impl<'i> DeclarationParserState<'i> {
1523 pub fn first_declaration_start(&self) -> SourceLocation {
1525 self.first_declaration_start
1526 }
1527
1528 pub fn has_parsed_declarations(&self) -> bool {
1530 !self.output_block.is_empty()
1531 }
1532
1533 pub fn take_declarations(&mut self) -> PropertyDeclarationBlock {
1535 std::mem::take(&mut self.output_block)
1536 }
1537
1538 pub fn parse_value<'t>(
1540 &mut self,
1541 context: &ParserContext,
1542 name: CowRcStr<'i>,
1543 input: &mut Parser<'i, 't>,
1544 declaration_start: &ParserState,
1545 ) -> Result<(), ParseError<'i>> {
1546 let id = match PropertyId::parse(&name, context) {
1547 Ok(id) => id,
1548 Err(..) => {
1549 return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
1550 },
1551 };
1552 if context.error_reporting_enabled() {
1553 self.last_parsed_property_id = Some(id.clone());
1554 }
1555 input.parse_until_before(Delimiter::Bang, |input| {
1556 PropertyDeclaration::parse_into(&mut self.declarations, id, context, input)
1557 })?;
1558 self.importance = match input.try_parse(parse_important) {
1559 Ok(()) => {
1560 if !context.allows_important_declarations() {
1561 return Err(
1562 input.new_custom_error(StyleParseErrorKind::UnexpectedImportantDeclaration)
1563 );
1564 }
1565 Importance::Important
1566 },
1567 Err(_) => Importance::Normal,
1568 };
1569 input.expect_exhausted()?;
1571 let has_parsed_declarations = self.has_parsed_declarations();
1572 self.output_block
1573 .extend(self.declarations.drain(), self.importance);
1574 self.last_parsed_property_id = None;
1578
1579 if !has_parsed_declarations {
1580 self.first_declaration_start = declaration_start.source_location();
1581 }
1582
1583 Ok(())
1584 }
1585
1586 #[inline]
1588 pub fn report_errors_if_needed(
1589 &mut self,
1590 context: &ParserContext,
1591 selectors: &[SelectorList<SelectorImpl>],
1592 ) {
1593 if self.errors.is_empty() {
1594 return;
1595 }
1596 self.do_report_css_errors(context, selectors);
1597 }
1598
1599 #[cold]
1600 fn do_report_css_errors(
1601 &mut self,
1602 context: &ParserContext,
1603 selectors: &[SelectorList<SelectorImpl>],
1604 ) {
1605 for (error, slice, property) in self.errors.drain(..) {
1606 report_one_css_error(
1607 context,
1608 Some(&self.output_block),
1609 selectors,
1610 error,
1611 slice,
1612 property,
1613 )
1614 }
1615 }
1616
1617 #[inline]
1619 pub fn did_error(&mut self, context: &ParserContext, error: ParseError<'i>, slice: &'i str) {
1620 self.declarations.clear();
1621 if !context.error_reporting_enabled() {
1622 return;
1623 }
1624 let property = self.last_parsed_property_id.take();
1625 self.errors.push((error, slice, property));
1626 }
1627}
1628
1629impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1631 type Prelude = ();
1632 type AtRule = ();
1633 type Error = StyleParseErrorKind<'i>;
1634}
1635
1636impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1638 type Prelude = ();
1639 type QualifiedRule = ();
1640 type Error = StyleParseErrorKind<'i>;
1641}
1642
1643fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
1645 (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
1646}
1647
1648impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1649 type Declaration = ();
1650 type Error = StyleParseErrorKind<'i>;
1651
1652 fn parse_value<'t>(
1653 &mut self,
1654 name: CowRcStr<'i>,
1655 input: &mut Parser<'i, 't>,
1656 declaration_start: &ParserState,
1657 ) -> Result<(), ParseError<'i>> {
1658 self.state
1659 .parse_value(self.context, name, input, declaration_start)
1660 }
1661}
1662
1663impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>>
1664 for PropertyDeclarationParser<'a, 'b, 'i>
1665{
1666 fn parse_declarations(&self) -> bool {
1667 true
1668 }
1669 fn parse_qualified(&self) -> bool {
1671 false
1672 }
1673}
1674
1675type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
1676
1677fn alias_of_known_property(name: &str) -> Option<PropertyId> {
1678 let mut prefixed = String::with_capacity(name.len() + 5);
1679 prefixed.push_str("-moz-");
1680 prefixed.push_str(name);
1681 PropertyId::parse_enabled_for_all_content(&prefixed).ok()
1682}
1683
1684#[cold]
1685fn report_one_css_error<'i>(
1686 context: &ParserContext,
1687 block: Option<&PropertyDeclarationBlock>,
1688 selectors: &[SelectorList<SelectorImpl>],
1689 mut error: ParseError<'i>,
1690 slice: &str,
1691 property: Option<PropertyId>,
1692) {
1693 debug_assert!(context.error_reporting_enabled());
1694
1695 fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
1696 match property.as_shorthand() {
1697 Ok(id) => id
1698 .longhands()
1699 .all(|longhand| block.contains(PropertyDeclarationId::Longhand(longhand))),
1700 Err(longhand_or_custom) => block.contains(longhand_or_custom),
1701 }
1702 }
1703
1704 if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(ref name)) = error.kind {
1705 if is_non_mozilla_vendor_identifier(name) {
1706 return;
1709 }
1710 if let Some(alias) = alias_of_known_property(name) {
1711 if let Some(block) = block {
1715 if all_properties_in_block(block, &alias) {
1716 return;
1717 }
1718 }
1719 }
1720 }
1721
1722 if let Some(ref property) = property {
1723 if let Some(block) = block {
1724 if all_properties_in_block(block, property) {
1725 return;
1726 }
1727 }
1728 if !matches!(
1732 error.kind,
1733 ParseErrorKind::Custom(StyleParseErrorKind::UnexpectedImportantDeclaration)
1734 ) {
1735 error = match *property {
1736 PropertyId::Custom(ref c) => {
1737 StyleParseErrorKind::new_invalid(format!("--{}", c), error)
1738 },
1739 _ => StyleParseErrorKind::new_invalid(
1740 property.non_custom_id().unwrap().name(),
1741 error,
1742 ),
1743 };
1744 }
1745 }
1746
1747 let location = error.location;
1748 let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
1749 context.log_css_error(location, error);
1750}
1751
1752pub fn parse_property_declaration_list(
1755 context: &ParserContext,
1756 input: &mut Parser,
1757 selectors: &[SelectorList<SelectorImpl>],
1758) -> PropertyDeclarationBlock {
1759 let mut state = DeclarationParserState::default();
1760 let mut parser = PropertyDeclarationParser {
1761 context,
1762 state: &mut state,
1763 };
1764 let mut iter = RuleBodyParser::new(input, &mut parser);
1765 while let Some(declaration) = iter.next() {
1766 match declaration {
1767 Ok(()) => {},
1768 Err((error, slice)) => iter.parser.state.did_error(context, error, slice),
1769 }
1770 }
1771 parser.state.report_errors_if_needed(context, selectors);
1772 state.output_block
1773}