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::error_reporting::{ContextualParseError, ParseErrorReporter};
18use crate::parser::ParserContext;
19use crate::properties::{
20 animated_properties::{AnimationValue, AnimationValueMap},
21 StyleBuilder,
22};
23use crate::rule_cache::RuleCacheConditions;
24use crate::selector_map::PrecomputedHashSet;
25use crate::selector_parser::SelectorImpl;
26use crate::shared_lock::Locked;
27use crate::stylesheets::container_rule::ContainerSizeQuery;
28use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
29use crate::stylist::Stylist;
30use crate::values::computed::Context;
31use cssparser::{
32 parse_important, AtRuleParser, CowRcStr, DeclarationParser, Delimiter, ParseErrorKind, Parser,
33 ParserInput, ParserState, QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser,
34 SourceLocation,
35};
36use itertools::Itertools;
37use selectors::SelectorList;
38use servo_arc::Arc;
39use smallbitvec::SmallBitVec;
40use smallvec::SmallVec;
41use std::fmt::{self, Write};
42use std::iter::Zip;
43use std::slice::Iter;
44use style_traits::{
45 CssString, CssStringWriter, CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss,
46 TypedValue,
47};
48use thin_vec::ThinVec;
49
50#[derive(Default)]
52pub struct AnimationDeclarations {
53 pub animations: Option<Arc<Locked<PropertyDeclarationBlock>>>,
55 pub transitions: Option<Arc<Locked<PropertyDeclarationBlock>>>,
57}
58
59impl AnimationDeclarations {
60 pub fn is_empty(&self) -> bool {
62 self.animations.is_none() && self.transitions.is_none()
63 }
64}
65
66#[derive(Clone, Copy, Debug, Eq, PartialEq)]
69enum DeclarationUpdate {
70 None,
72 Append,
74 UpdateInPlace { pos: usize },
76 AppendAndRemove { pos: usize },
79}
80
81#[derive(Default)]
84pub struct SourcePropertyDeclarationUpdate {
85 updates: SubpropertiesVec<DeclarationUpdate>,
86 new_count: usize,
87 any_removal: bool,
88}
89
90#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
94pub enum Importance {
95 Normal,
97
98 Important,
100}
101
102impl Default for Importance {
103 fn default() -> Self {
104 Self::Normal
105 }
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)]
123pub enum PropertyTypedValue {
124 None,
126
127 Unsupported,
131
132 Typed(TypedValue),
134}
135
136#[derive(Clone, Debug, ToShmem, Default, MallocSizeOf)]
138pub struct PropertyDeclarationIdSet {
139 longhands: LonghandIdSet,
140 custom: PrecomputedHashSet<custom_properties::Name>,
141}
142
143impl PropertyDeclarationIdSet {
144 pub fn insert(&mut self, id: PropertyDeclarationId) -> bool {
146 match id {
147 PropertyDeclarationId::Longhand(id) => {
148 if self.longhands.contains(id) {
149 return false;
150 }
151 self.longhands.insert(id);
152 return true;
153 },
154 PropertyDeclarationId::Custom(name) => self.custom.insert((*name).clone()),
155 }
156 }
157
158 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
160 match id {
161 PropertyDeclarationId::Longhand(id) => self.longhands.contains(id),
162 PropertyDeclarationId::Custom(name) => self.custom.contains(name),
163 }
164 }
165
166 pub fn remove(&mut self, id: PropertyDeclarationId) {
168 match id {
169 PropertyDeclarationId::Longhand(id) => self.longhands.remove(id),
170 PropertyDeclarationId::Custom(name) => {
171 self.custom.remove(name);
172 },
173 }
174 }
175
176 pub fn clear(&mut self) {
178 self.longhands.clear();
179 self.custom.clear();
180 }
181
182 #[inline]
184 pub fn is_empty(&self) -> bool {
185 self.longhands.is_empty() && self.custom.is_empty()
186 }
187 #[inline]
189 pub fn contains_any_reset(&self) -> bool {
190 self.longhands.contains_any_reset()
191 }
192
193 #[inline]
195 pub fn contains_all_longhands(&self, longhands: &LonghandIdSet) -> bool {
196 self.longhands.contains_all(longhands)
197 }
198
199 #[inline]
201 pub fn contains_all(&self, properties: &PropertyDeclarationIdSet) -> bool {
202 if !self.longhands.contains_all(&properties.longhands) {
203 return false;
204 }
205 if properties.custom.len() > self.custom.len() {
206 return false;
207 }
208 properties
209 .custom
210 .iter()
211 .all(|item| self.custom.contains(item))
212 }
213
214 pub fn iter(&self) -> PropertyDeclarationIdSetIterator<'_> {
216 PropertyDeclarationIdSetIterator {
217 longhands: self.longhands.iter(),
218 custom: self.custom.iter(),
219 }
220 }
221}
222
223pub struct PropertyDeclarationIdSetIterator<'a> {
225 longhands: LonghandIdSetIterator<'a>,
226 custom: std::collections::hash_set::Iter<'a, custom_properties::Name>,
227}
228
229impl<'a> Iterator for PropertyDeclarationIdSetIterator<'a> {
230 type Item = PropertyDeclarationId<'a>;
231
232 fn next(&mut self) -> Option<Self::Item> {
233 match self.longhands.next() {
237 Some(id) => Some(PropertyDeclarationId::Longhand(id)),
238 None => match self.custom.next() {
239 Some(a) => Some(PropertyDeclarationId::Custom(a)),
240 None => None,
241 },
242 }
243 }
244}
245
246#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
248#[derive(Clone, ToShmem, Default)]
249pub struct PropertyDeclarationBlock {
250 declarations: ThinVec<PropertyDeclaration>,
254
255 declarations_importance: SmallBitVec,
257
258 property_ids: PropertyDeclarationIdSet,
260}
261
262pub struct DeclarationImportanceIterator<'a> {
264 iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
265}
266
267impl<'a> Default for DeclarationImportanceIterator<'a> {
268 fn default() -> Self {
269 Self {
270 iter: [].iter().zip(smallbitvec::Iter::default()),
271 }
272 }
273}
274
275impl<'a> DeclarationImportanceIterator<'a> {
276 fn new(declarations: &'a [PropertyDeclaration], important: &'a SmallBitVec) -> Self {
278 DeclarationImportanceIterator {
279 iter: declarations.iter().zip(important.iter()),
280 }
281 }
282}
283
284impl<'a> Iterator for DeclarationImportanceIterator<'a> {
285 type Item = (&'a PropertyDeclaration, Importance);
286
287 #[inline]
288 fn next(&mut self) -> Option<Self::Item> {
289 self.iter.next().map(|(decl, important)| {
290 (
291 decl,
292 if important {
293 Importance::Important
294 } else {
295 Importance::Normal
296 },
297 )
298 })
299 }
300
301 #[inline]
302 fn size_hint(&self) -> (usize, Option<usize>) {
303 self.iter.size_hint()
304 }
305}
306
307impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
308 #[inline(always)]
309 fn next_back(&mut self) -> Option<Self::Item> {
310 self.iter.next_back().map(|(decl, important)| {
311 (
312 decl,
313 if important {
314 Importance::Important
315 } else {
316 Importance::Normal
317 },
318 )
319 })
320 }
321}
322
323pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> {
325 iter: DeclarationImportanceIterator<'a>,
326 context: &'cx mut Context<'cx_a>,
327 style: &'a ComputedValues,
328 default_values: &'a ComputedValues,
329}
330
331impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
332 fn new(
333 declarations: &'a PropertyDeclarationBlock,
334 context: &'cx mut Context<'cx_a>,
335 style: &'a ComputedValues,
336 default_values: &'a ComputedValues,
337 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
338 AnimationValueIterator {
339 iter: declarations.declaration_importance_iter(),
340 context,
341 style,
342 default_values,
343 }
344 }
345}
346
347impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
348 type Item = AnimationValue;
349 #[inline]
350 fn next(&mut self) -> Option<Self::Item> {
351 loop {
352 let (decl, importance) = self.iter.next()?;
353
354 if importance.important() {
355 continue;
356 }
357
358 let animation = AnimationValue::from_declaration(
359 decl,
360 &mut self.context,
361 self.style,
362 self.default_values,
363 );
364
365 if let Some(anim) = animation {
366 return Some(anim);
367 }
368 }
369 }
370}
371
372impl fmt::Debug for PropertyDeclarationBlock {
373 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
374 self.declarations.fmt(f)
375 }
376}
377
378impl PropertyDeclarationBlock {
379 #[inline]
381 pub fn len(&self) -> usize {
382 self.declarations.len()
383 }
384
385 #[inline]
387 pub fn is_empty(&self) -> bool {
388 self.declarations.is_empty()
389 }
390
391 #[inline]
393 pub fn new() -> Self {
394 PropertyDeclarationBlock {
395 declarations: ThinVec::new(),
396 declarations_importance: SmallBitVec::new(),
397 property_ids: PropertyDeclarationIdSet::default(),
398 }
399 }
400
401 pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
403 let mut property_ids = PropertyDeclarationIdSet::default();
404 property_ids.insert(declaration.id());
405 let mut declarations = ThinVec::with_capacity(1);
406 declarations.push(declaration);
407 PropertyDeclarationBlock {
408 declarations,
409 declarations_importance: SmallBitVec::from_elem(1, importance.important()),
410 property_ids,
411 }
412 }
413
414 #[inline]
416 pub fn declarations(&self) -> &[PropertyDeclaration] {
417 &self.declarations
418 }
419
420 #[inline]
422 pub fn declarations_importance(&self) -> &SmallBitVec {
423 &self.declarations_importance
424 }
425
426 #[inline]
428 pub fn declaration_importance_iter(&self) -> DeclarationImportanceIterator<'_> {
429 DeclarationImportanceIterator::new(&self.declarations, &self.declarations_importance)
430 }
431
432 #[inline]
434 pub fn normal_declaration_iter<'a>(
435 &'a self,
436 ) -> impl DoubleEndedIterator<Item = &'a PropertyDeclaration> {
437 self.declaration_importance_iter()
438 .filter(|(_, importance)| !importance.important())
439 .map(|(declaration, _)| declaration)
440 }
441
442 #[inline]
444 pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>(
445 &'a self,
446 context: &'cx mut Context<'cx_a>,
447 style: &'a ComputedValues,
448 default_values: &'a ComputedValues,
449 ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
450 AnimationValueIterator::new(self, context, style, default_values)
451 }
452
453 #[inline]
458 pub fn any_important(&self) -> bool {
459 !self.declarations_importance.all_false()
460 }
461
462 #[inline]
467 pub fn any_normal(&self) -> bool {
468 !self.declarations_importance.all_true()
469 }
470
471 #[inline]
474 pub fn property_ids(&self) -> &PropertyDeclarationIdSet {
475 &self.property_ids
476 }
477
478 #[inline]
480 pub fn contains(&self, id: PropertyDeclarationId) -> bool {
481 self.property_ids.contains(id)
482 }
483
484 #[inline]
486 pub fn contains_any_reset(&self) -> bool {
487 self.property_ids.contains_any_reset()
488 }
489
490 #[inline]
495 pub fn get(
496 &self,
497 property: PropertyDeclarationId,
498 ) -> Option<(&PropertyDeclaration, Importance)> {
499 if !self.contains(property) {
500 return None;
501 }
502 self.declaration_importance_iter()
503 .find(|(declaration, _)| declaration.id() == property)
504 }
505
506 pub fn shorthand_to_css(
509 &self,
510 shorthand: ShorthandId,
511 dest: &mut CssStringWriter,
512 ) -> fmt::Result {
513 let mut list = SmallVec::<[&_; 10]>::new();
516 let mut important_count = 0;
517
518 for longhand in shorthand.longhands() {
520 let declaration = self.get(PropertyDeclarationId::Longhand(longhand));
522
523 match declaration {
525 Some((declaration, importance)) => {
526 list.push(declaration);
527 if importance.important() {
528 important_count += 1;
529 }
530 },
531 None => return Ok(()),
532 }
533 }
534
535 if important_count > 0 && important_count != list.len() {
538 return Ok(());
539 }
540
541 match shorthand.get_shorthand_appendable_value(&list) {
545 Some(appendable_value) => append_declaration_value(dest, appendable_value),
546 None => return Ok(()),
547 }
548 }
549
550 pub fn property_value_to_css(
554 &self,
555 property: &PropertyId,
556 dest: &mut CssStringWriter,
557 ) -> fmt::Result {
558 let longhand_or_custom = match property.as_shorthand() {
562 Ok(shorthand) => return self.shorthand_to_css(shorthand, dest),
563 Err(longhand_or_custom) => longhand_or_custom,
564 };
565
566 if let Some((value, _importance)) = self.get(longhand_or_custom) {
567 value.to_css(dest)
569 } else {
570 Ok(())
572 }
573 }
574
575 pub fn property_priority(&self, property: &PropertyId) -> Importance {
577 match property.as_shorthand() {
581 Ok(shorthand) => {
582 if shorthand.longhands().all(|l| {
584 self.get(PropertyDeclarationId::Longhand(l))
585 .map_or(false, |(_, importance)| importance.important())
586 }) {
587 Importance::Important
588 } else {
589 Importance::Normal
590 }
591 },
592 Err(longhand_or_custom) => {
593 self.get(longhand_or_custom)
595 .map_or(Importance::Normal, |(_, importance)| importance)
596 },
597 }
598 }
599
600 pub fn property_value_to_typed(&self, property: &PropertyId) -> PropertyTypedValue {
602 match property.as_shorthand() {
603 Ok(shorthand) => {
604 if shorthand
605 .longhands()
606 .all(|longhand| self.contains(PropertyDeclarationId::Longhand(longhand)))
607 {
608 PropertyTypedValue::Unsupported
609 } else {
610 PropertyTypedValue::None
611 }
612 },
613 Err(longhand_or_custom) => match self.get(longhand_or_custom) {
614 Some((value, _importance)) => {
615 if let Some(typed_value) = value.to_typed() {
616 PropertyTypedValue::Typed(typed_value)
617 } else {
618 PropertyTypedValue::Unsupported
619 }
620 },
621 None => PropertyTypedValue::None,
622 },
623 }
624 }
625
626 pub fn extend(
631 &mut self,
632 mut drain: SourcePropertyDeclarationDrain,
633 importance: Importance,
634 ) -> bool {
635 let all_shorthand_len = match drain.all_shorthand {
636 AllShorthand::NotSet => 0,
637 AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
638 property_counts::ALL_SHORTHAND_EXPANDED
639 },
640 };
641 let push_calls_count = drain.declarations.len() + all_shorthand_len;
642
643 self.declarations.reserve(push_calls_count);
645
646 let mut changed = false;
647 for decl in &mut drain.declarations {
648 changed |= self.push(decl, importance);
649 }
650 drain
651 .all_shorthand
652 .declarations()
653 .fold(changed, |changed, decl| {
654 changed | self.push(decl, importance)
655 })
656 }
657
658 pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
664 let id = declaration.id();
665 if !self.property_ids.insert(id) {
666 let mut index_to_remove = None;
667 for (i, slot) in self.declarations.iter_mut().enumerate() {
668 if slot.id() != id {
669 continue;
670 }
671
672 let important = self.declarations_importance[i];
673
674 if important && !importance.important() {
677 return false;
678 }
679
680 index_to_remove = Some(i);
681 break;
682 }
683
684 if let Some(index) = index_to_remove {
685 self.declarations.remove(index);
686 self.declarations_importance.remove(index);
687 self.declarations.push(declaration);
688 self.declarations_importance.push(importance.important());
689 return true;
690 }
691 }
692
693 self.declarations.push(declaration);
694 self.declarations_importance.push(importance.important());
695 true
696 }
697
698 pub fn prepare_for_update(
702 &self,
703 source_declarations: &SourcePropertyDeclaration,
704 importance: Importance,
705 updates: &mut SourcePropertyDeclarationUpdate,
706 ) -> bool {
707 debug_assert!(updates.updates.is_empty());
708 if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
710 debug_assert!(source_declarations.declarations.is_empty());
711 return source_declarations
712 .all_shorthand
713 .declarations()
714 .any(|decl| {
715 !self.contains(decl.id())
716 || self
717 .declarations
718 .iter()
719 .enumerate()
720 .find(|&(_, ref d)| d.id() == decl.id())
721 .map_or(true, |(i, d)| {
722 let important = self.declarations_importance[i];
723 *d != decl || important != importance.important()
724 })
725 });
726 }
727 let mut any_update = false;
729 let new_count = &mut updates.new_count;
730 let any_removal = &mut updates.any_removal;
731 let updates = &mut updates.updates;
732 updates.extend(
733 source_declarations
734 .declarations
735 .iter()
736 .map(|declaration| {
737 if !self.contains(declaration.id()) {
738 return DeclarationUpdate::Append;
739 }
740 let longhand_id = declaration.id().as_longhand();
741 if let Some(longhand_id) = longhand_id {
742 if let Some(logical_group) = longhand_id.logical_group() {
743 let mut needs_append = false;
744 for (pos, decl) in self.declarations.iter().enumerate().rev() {
745 let id = match decl.id().as_longhand() {
746 Some(id) => id,
747 None => continue,
748 };
749 if id == longhand_id {
750 if needs_append {
751 return DeclarationUpdate::AppendAndRemove { pos };
752 }
753 let important = self.declarations_importance[pos];
754 if decl == declaration && important == importance.important() {
755 return DeclarationUpdate::None;
756 }
757 return DeclarationUpdate::UpdateInPlace { pos };
758 }
759 if !needs_append
760 && id.logical_group() == Some(logical_group)
761 && id.is_logical() != longhand_id.is_logical()
762 {
763 needs_append = true;
764 }
765 }
766 unreachable!("Longhand should be found in loop above");
767 }
768 }
769 self.declarations
770 .iter()
771 .enumerate()
772 .find(|&(_, ref decl)| decl.id() == declaration.id())
773 .map_or(DeclarationUpdate::Append, |(pos, decl)| {
774 let important = self.declarations_importance[pos];
775 if decl == declaration && important == importance.important() {
776 DeclarationUpdate::None
777 } else {
778 DeclarationUpdate::UpdateInPlace { pos }
779 }
780 })
781 })
782 .inspect(|update| {
783 if matches!(update, DeclarationUpdate::None) {
784 return;
785 }
786 any_update = true;
787 match update {
788 DeclarationUpdate::Append => {
789 *new_count += 1;
790 },
791 DeclarationUpdate::AppendAndRemove { .. } => {
792 *any_removal = true;
793 },
794 _ => {},
795 }
796 }),
797 );
798 any_update
799 }
800
801 pub fn update(
803 &mut self,
804 drain: SourcePropertyDeclarationDrain,
805 importance: Importance,
806 updates: &mut SourcePropertyDeclarationUpdate,
807 ) {
808 let important = importance.important();
809 if !matches!(drain.all_shorthand, AllShorthand::NotSet) {
810 debug_assert!(updates.updates.is_empty());
811 for decl in drain.all_shorthand.declarations() {
812 let id = decl.id();
813 if self.property_ids.insert(id) {
814 self.declarations.push(decl);
815 self.declarations_importance.push(important);
816 } else {
817 let (idx, slot) = self
818 .declarations
819 .iter_mut()
820 .enumerate()
821 .find(|&(_, ref d)| d.id() == decl.id())
822 .unwrap();
823 *slot = decl;
824 self.declarations_importance.set(idx, important);
825 }
826 }
827 return;
828 }
829
830 self.declarations.reserve(updates.new_count);
831 if updates.any_removal {
832 struct UpdateOrRemoval<'a> {
834 item: &'a mut DeclarationUpdate,
835 pos: usize,
836 remove: bool,
837 }
838 let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
839 .updates
840 .iter_mut()
841 .filter_map(|item| {
842 let (pos, remove) = match *item {
843 DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
844 DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
845 _ => return None,
846 };
847 Some(UpdateOrRemoval { item, pos, remove })
848 })
849 .collect();
850 updates_and_removals.sort_unstable_by_key(|update| update.pos);
853 updates_and_removals
854 .iter()
855 .rev()
856 .filter(|update| update.remove)
857 .for_each(|update| {
858 self.declarations.remove(update.pos);
859 self.declarations_importance.remove(update.pos);
860 });
861 let mut removed_count = 0;
863 for update in updates_and_removals.iter_mut() {
864 if update.remove {
865 removed_count += 1;
866 continue;
867 }
868 debug_assert_eq!(
869 *update.item,
870 DeclarationUpdate::UpdateInPlace { pos: update.pos }
871 );
872 *update.item = DeclarationUpdate::UpdateInPlace {
873 pos: update.pos - removed_count,
874 };
875 }
876 }
877 for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
879 match *update {
880 DeclarationUpdate::None => {},
881 DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
882 self.property_ids.insert(decl.id());
883 self.declarations.push(decl);
884 self.declarations_importance.push(important);
885 },
886 DeclarationUpdate::UpdateInPlace { pos } => {
887 self.declarations[pos] = decl;
888 self.declarations_importance.set(pos, important);
889 },
890 }
891 }
892 updates.updates.clear();
893 }
894
895 #[inline]
898 pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
899 if let Err(longhand_or_custom) = property.as_shorthand() {
900 if !self.contains(longhand_or_custom) {
901 return None;
902 }
903 }
904
905 self.declarations
906 .iter()
907 .position(|declaration| declaration.id().is_or_is_longhand_of(property))
908 }
909
910 #[inline]
912 fn remove_declaration_at(&mut self, i: usize) {
913 self.property_ids.remove(self.declarations[i].id());
914 self.declarations_importance.remove(i);
915 self.declarations.remove(i);
916 }
917
918 #[inline]
920 pub fn clear(&mut self) {
921 self.declarations_importance.clear();
922 self.declarations.clear();
923 self.property_ids.clear();
924 }
925
926 #[inline]
931 pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
932 debug_assert_eq!(
933 Some(first_declaration),
934 self.first_declaration_to_remove(property)
935 );
936 debug_assert!(self.declarations[first_declaration]
937 .id()
938 .is_or_is_longhand_of(property));
939
940 self.remove_declaration_at(first_declaration);
941
942 let shorthand = match property.as_shorthand() {
943 Ok(s) => s,
944 Err(_longhand_or_custom) => return,
945 };
946
947 let mut i = first_declaration;
948 let mut len = self.len();
949 while i < len {
950 if !self.declarations[i].id().is_longhand_of(shorthand) {
951 i += 1;
952 continue;
953 }
954
955 self.remove_declaration_at(i);
956 len -= 1;
957 }
958 }
959
960 pub fn single_value_to_css(
962 &self,
963 property: &PropertyId,
964 dest: &mut CssStringWriter,
965 computed_values: Option<&ComputedValues>,
966 stylist: &Stylist,
967 ) -> fmt::Result {
968 if let Ok(shorthand) = property.as_shorthand() {
969 return self.shorthand_to_css(shorthand, dest);
970 }
971
972 let declaration = match self.declarations.get(0) {
975 Some(d) => d,
976 None => return Err(fmt::Error),
977 };
978
979 let mut rule_cache_conditions = RuleCacheConditions::default();
980 let mut context = Context::new(
981 StyleBuilder::new(
982 stylist.device(),
983 Some(stylist),
984 computed_values,
985 None,
986 None,
987 false,
988 ),
989 stylist.quirks_mode(),
990 &mut rule_cache_conditions,
991 ContainerSizeQuery::none(),
992 );
993
994 if let Some(cv) = computed_values {
995 context.builder.custom_properties = cv.custom_properties().clone();
996 };
997
998 match (declaration, computed_values) {
999 (&PropertyDeclaration::WithVariables(ref declaration), Some(_)) => declaration
1007 .value
1008 .substitute_variables(
1009 declaration.id,
1010 &context.builder.custom_properties,
1011 stylist,
1012 &context,
1013 &mut Default::default(),
1014 )
1015 .to_css(dest),
1016 (ref d, _) => d.to_css(dest),
1017 }
1018 }
1019
1020 pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
1022 let len = animation_value_map.len();
1023 let mut declarations = ThinVec::with_capacity(len);
1024 let mut property_ids = PropertyDeclarationIdSet::default();
1025
1026 for (property, animation_value) in animation_value_map.iter() {
1027 property_ids.insert(property.as_borrowed());
1028 declarations.push(animation_value.uncompute());
1029 }
1030
1031 PropertyDeclarationBlock {
1032 declarations,
1033 property_ids,
1034 declarations_importance: SmallBitVec::from_elem(len, false),
1035 }
1036 }
1037
1038 pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
1041 if let Err(longhand_or_custom) = property.as_shorthand() {
1042 if !self.property_ids.contains(longhand_or_custom) {
1043 return false;
1044 }
1045 }
1046 self.declarations.iter().any(|decl| {
1047 decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
1048 })
1049 }
1050
1051 pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
1057 let mut is_first_serialization = true; let mut already_serialized = NonCustomPropertyIdSet::new();
1069
1070 'declaration_loop: for (declaration, importance) in self.declaration_importance_iter() {
1072 let property = declaration.id();
1074 let longhand_id = match property {
1075 PropertyDeclarationId::Longhand(id) => id,
1076 PropertyDeclarationId::Custom(..) => {
1077 append_serialization(
1082 dest,
1083 &property,
1084 AppendableValue::Declaration(declaration),
1085 importance,
1086 &mut is_first_serialization,
1087 )?;
1088 continue;
1089 },
1090 };
1091
1092 if already_serialized.contains(longhand_id.into()) {
1094 continue;
1095 }
1096
1097 for shorthand in longhand_id.shorthands() {
1099 if already_serialized.contains(shorthand.into()) {
1101 continue;
1102 }
1103 already_serialized.insert(shorthand.into());
1104
1105 if shorthand.is_legacy_shorthand() {
1106 continue;
1107 }
1108
1109 let longhands = {
1116 let mut ids = LonghandIdSet::new();
1119 for longhand in shorthand.longhands() {
1120 ids.insert(longhand);
1121 }
1122 ids
1123 };
1124
1125 if !self.property_ids.contains_all_longhands(&longhands) {
1130 continue;
1131 }
1132
1133 let mut current_longhands = SmallVec::<[&_; 10]>::new();
1136 let mut logical_groups = LogicalGroupSet::new();
1137 let mut saw_one = false;
1138 let mut logical_mismatch = false;
1139 let mut seen = LonghandIdSet::new();
1140 let mut important_count = 0;
1141
1142 for (declaration, importance) in self.declaration_importance_iter() {
1146 let longhand = match declaration.id() {
1147 PropertyDeclarationId::Longhand(id) => id,
1148 PropertyDeclarationId::Custom(..) => continue,
1149 };
1150
1151 if longhands.contains(longhand) {
1152 saw_one = true;
1153 if importance.important() {
1154 important_count += 1;
1155 }
1156 current_longhands.push(declaration);
1157 if shorthand != ShorthandId::All {
1158 if let Some(g) = longhand.logical_group() {
1161 logical_groups.insert(g);
1162 }
1163 seen.insert(longhand);
1164 if seen == longhands {
1165 break;
1166 }
1167 }
1168 } else if saw_one {
1169 if let Some(g) = longhand.logical_group() {
1170 if logical_groups.contains(g) {
1171 logical_mismatch = true;
1172 break;
1173 }
1174 }
1175 }
1176 }
1177
1178 let is_important = important_count > 0;
1184 if is_important && important_count != current_longhands.len() {
1185 continue;
1186 }
1187
1188 if logical_mismatch {
1196 continue;
1197 }
1198
1199 let importance = if is_important {
1200 Importance::Important
1201 } else {
1202 Importance::Normal
1203 };
1204
1205 let appendable_value =
1209 match shorthand.get_shorthand_appendable_value(¤t_longhands) {
1210 None => continue,
1211 Some(appendable_value) => appendable_value,
1212 };
1213
1214 let mut v = CssString::new();
1217 let value = match appendable_value {
1218 AppendableValue::Css(css) => {
1219 debug_assert!(!css.is_empty());
1220 appendable_value
1221 },
1222 other => {
1223 append_declaration_value(&mut v, other)?;
1224
1225 if v.is_empty() {
1229 continue;
1230 }
1231
1232 AppendableValue::Css({
1233 #[cfg(feature = "gecko")]
1235 unsafe {
1236 v.as_str_unchecked()
1237 }
1238 #[cfg(feature = "servo")]
1239 &v
1240 })
1241 },
1242 };
1243
1244 append_serialization(
1254 dest,
1255 &shorthand,
1256 value,
1257 importance,
1258 &mut is_first_serialization,
1259 )?;
1260
1261 for current_longhand in ¤t_longhands {
1265 let longhand_id = match current_longhand.id() {
1266 PropertyDeclarationId::Longhand(id) => id,
1267 PropertyDeclarationId::Custom(..) => unreachable!(),
1268 };
1269
1270 already_serialized.insert(longhand_id.into());
1272 }
1273
1274 continue 'declaration_loop;
1277 }
1278
1279 append_serialization(
1290 dest,
1291 &property,
1292 AppendableValue::Declaration(declaration),
1293 importance,
1294 &mut is_first_serialization,
1295 )?;
1296
1297 already_serialized.insert(longhand_id.into());
1300 }
1301
1302 Ok(())
1304 }
1305}
1306
1307pub enum AppendableValue<'a, 'b: 'a> {
1310 Declaration(&'a PropertyDeclaration),
1312 DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]),
1317 Css(&'a str),
1320}
1321
1322fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
1324where
1325 W: Write,
1326{
1327 if !*is_first_serialization {
1328 dest.write_char(' ')
1329 } else {
1330 *is_first_serialization = false;
1331 Ok(())
1332 }
1333}
1334
1335pub fn append_declaration_value<'a, 'b: 'a>(
1337 dest: &mut CssStringWriter,
1338 appendable_value: AppendableValue<'a, 'b>,
1339) -> fmt::Result {
1340 match appendable_value {
1341 AppendableValue::Css(css) => dest.write_str(css),
1342 AppendableValue::Declaration(decl) => decl.to_css(dest),
1343 AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
1344 shorthand.longhands_to_css(decls, dest)
1345 },
1346 }
1347}
1348
1349pub fn append_serialization<'a, 'b: 'a, N>(
1351 dest: &mut CssStringWriter,
1352 property_name: &N,
1353 appendable_value: AppendableValue<'a, 'b>,
1354 importance: Importance,
1355 is_first_serialization: &mut bool,
1356) -> fmt::Result
1357where
1358 N: ToCss,
1359{
1360 handle_first_serialization(dest, is_first_serialization)?;
1361
1362 property_name.to_css(&mut CssWriter::new(dest))?;
1363 dest.write_str(": ")?;
1364
1365 append_declaration_value(dest, appendable_value)?;
1366
1367 if importance.important() {
1368 dest.write_str(" !important")?;
1369 }
1370
1371 dest.write_char(';')
1372}
1373
1374#[inline]
1379pub fn parse_style_attribute(
1380 input: &str,
1381 url_data: &UrlExtraData,
1382 error_reporter: Option<&dyn ParseErrorReporter>,
1383 quirks_mode: QuirksMode,
1384 rule_type: CssRuleType,
1385) -> PropertyDeclarationBlock {
1386 let context = ParserContext::new(
1387 Origin::Author,
1388 url_data,
1389 Some(rule_type),
1390 ParsingMode::DEFAULT,
1391 quirks_mode,
1392 Default::default(),
1393 error_reporter,
1394 None,
1395 );
1396
1397 let mut input = ParserInput::new(input);
1398 parse_property_declaration_list(&context, &mut Parser::new(&mut input), &[])
1399}
1400
1401#[inline]
1406pub fn parse_one_declaration_into(
1407 declarations: &mut SourcePropertyDeclaration,
1408 id: PropertyId,
1409 input: &str,
1410 origin: Origin,
1411 url_data: &UrlExtraData,
1412 error_reporter: Option<&dyn ParseErrorReporter>,
1413 parsing_mode: ParsingMode,
1414 quirks_mode: QuirksMode,
1415 rule_type: CssRuleType,
1416) -> Result<(), ()> {
1417 let context = ParserContext::new(
1418 origin,
1419 url_data,
1420 Some(rule_type),
1421 parsing_mode,
1422 quirks_mode,
1423 Default::default(),
1424 error_reporter,
1425 None,
1426 );
1427
1428 let property_id_for_error_reporting = if context.error_reporting_enabled() {
1429 Some(id.clone())
1430 } else {
1431 None
1432 };
1433
1434 let mut input = ParserInput::new(input);
1435 let mut parser = Parser::new(&mut input);
1436 let start_position = parser.position();
1437 parser
1438 .parse_entirely(|parser| {
1439 PropertyDeclaration::parse_into(declarations, id, &context, parser)
1440 })
1441 .map_err(|err| {
1442 if context.error_reporting_enabled() {
1443 report_one_css_error(
1444 &context,
1445 None,
1446 &[],
1447 err,
1448 parser.slice_from(start_position),
1449 property_id_for_error_reporting,
1450 )
1451 }
1452 })
1453}
1454
1455struct PropertyDeclarationParser<'a, 'b: 'a, 'i> {
1457 context: &'a ParserContext<'b>,
1458 state: &'a mut DeclarationParserState<'i>,
1459}
1460
1461#[derive(Default)]
1465pub struct DeclarationParserState<'i> {
1466 output_block: PropertyDeclarationBlock,
1468 declarations: SourcePropertyDeclaration,
1471 importance: Importance,
1473 errors: SmallParseErrorVec<'i>,
1475 first_declaration_start: SourceLocation,
1477 last_parsed_property_id: Option<PropertyId>,
1479}
1480
1481impl<'i> DeclarationParserState<'i> {
1482 pub fn first_declaration_start(&self) -> SourceLocation {
1484 self.first_declaration_start
1485 }
1486
1487 pub fn has_parsed_declarations(&self) -> bool {
1489 !self.output_block.is_empty()
1490 }
1491
1492 pub fn take_declarations(&mut self) -> PropertyDeclarationBlock {
1494 std::mem::take(&mut self.output_block)
1495 }
1496
1497 pub fn parse_value<'t>(
1499 &mut self,
1500 context: &ParserContext,
1501 name: CowRcStr<'i>,
1502 input: &mut Parser<'i, 't>,
1503 declaration_start: &ParserState,
1504 ) -> Result<(), ParseError<'i>> {
1505 let id = match PropertyId::parse(&name, context) {
1506 Ok(id) => id,
1507 Err(..) => {
1508 return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
1509 },
1510 };
1511 if context.error_reporting_enabled() {
1512 self.last_parsed_property_id = Some(id.clone());
1513 }
1514 input.parse_until_before(Delimiter::Bang, |input| {
1515 PropertyDeclaration::parse_into(&mut self.declarations, id, context, input)
1516 })?;
1517 self.importance = match input.try_parse(parse_important) {
1518 Ok(()) => {
1519 if !context.allows_important_declarations() {
1520 return Err(
1521 input.new_custom_error(StyleParseErrorKind::UnexpectedImportantDeclaration)
1522 );
1523 }
1524 Importance::Important
1525 },
1526 Err(_) => Importance::Normal,
1527 };
1528 input.expect_exhausted()?;
1530 let has_parsed_declarations = self.has_parsed_declarations();
1531 self.output_block
1532 .extend(self.declarations.drain(), self.importance);
1533 self.last_parsed_property_id = None;
1537
1538 if !has_parsed_declarations {
1539 self.first_declaration_start = declaration_start.source_location();
1540 }
1541
1542 Ok(())
1543 }
1544
1545 #[inline]
1547 pub fn report_errors_if_needed(
1548 &mut self,
1549 context: &ParserContext,
1550 selectors: &[SelectorList<SelectorImpl>],
1551 ) {
1552 if self.errors.is_empty() {
1553 return;
1554 }
1555 self.do_report_css_errors(context, selectors);
1556 }
1557
1558 #[cold]
1559 fn do_report_css_errors(
1560 &mut self,
1561 context: &ParserContext,
1562 selectors: &[SelectorList<SelectorImpl>],
1563 ) {
1564 for (error, slice, property) in self.errors.drain(..) {
1565 report_one_css_error(
1566 context,
1567 Some(&self.output_block),
1568 selectors,
1569 error,
1570 slice,
1571 property,
1572 )
1573 }
1574 }
1575
1576 #[inline]
1578 pub fn did_error(&mut self, context: &ParserContext, error: ParseError<'i>, slice: &'i str) {
1579 self.declarations.clear();
1580 if !context.error_reporting_enabled() {
1581 return;
1582 }
1583 let property = self.last_parsed_property_id.take();
1584 self.errors.push((error, slice, property));
1585 }
1586}
1587
1588impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1590 type Prelude = ();
1591 type AtRule = ();
1592 type Error = StyleParseErrorKind<'i>;
1593}
1594
1595impl<'a, 'b, 'i> QualifiedRuleParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1597 type Prelude = ();
1598 type QualifiedRule = ();
1599 type Error = StyleParseErrorKind<'i>;
1600}
1601
1602fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
1604 (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
1605}
1606
1607impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b, 'i> {
1608 type Declaration = ();
1609 type Error = StyleParseErrorKind<'i>;
1610
1611 fn parse_value<'t>(
1612 &mut self,
1613 name: CowRcStr<'i>,
1614 input: &mut Parser<'i, 't>,
1615 declaration_start: &ParserState,
1616 ) -> Result<(), ParseError<'i>> {
1617 self.state
1618 .parse_value(self.context, name, input, declaration_start)
1619 }
1620}
1621
1622impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>>
1623 for PropertyDeclarationParser<'a, 'b, 'i>
1624{
1625 fn parse_declarations(&self) -> bool {
1626 true
1627 }
1628 fn parse_qualified(&self) -> bool {
1630 false
1631 }
1632}
1633
1634type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
1635
1636fn alias_of_known_property(name: &str) -> Option<PropertyId> {
1637 let mut prefixed = String::with_capacity(name.len() + 5);
1638 prefixed.push_str("-moz-");
1639 prefixed.push_str(name);
1640 PropertyId::parse_enabled_for_all_content(&prefixed).ok()
1641}
1642
1643#[cold]
1644fn report_one_css_error<'i>(
1645 context: &ParserContext,
1646 block: Option<&PropertyDeclarationBlock>,
1647 selectors: &[SelectorList<SelectorImpl>],
1648 mut error: ParseError<'i>,
1649 slice: &str,
1650 property: Option<PropertyId>,
1651) {
1652 debug_assert!(context.error_reporting_enabled());
1653
1654 fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
1655 match property.as_shorthand() {
1656 Ok(id) => id
1657 .longhands()
1658 .all(|longhand| block.contains(PropertyDeclarationId::Longhand(longhand))),
1659 Err(longhand_or_custom) => block.contains(longhand_or_custom),
1660 }
1661 }
1662
1663 if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(ref name)) = error.kind {
1664 if is_non_mozilla_vendor_identifier(name) {
1665 return;
1668 }
1669 if let Some(alias) = alias_of_known_property(name) {
1670 if let Some(block) = block {
1674 if all_properties_in_block(block, &alias) {
1675 return;
1676 }
1677 }
1678 }
1679 }
1680
1681 if let Some(ref property) = property {
1682 if let Some(block) = block {
1683 if all_properties_in_block(block, property) {
1684 return;
1685 }
1686 }
1687 if !matches!(
1691 error.kind,
1692 ParseErrorKind::Custom(StyleParseErrorKind::UnexpectedImportantDeclaration)
1693 ) {
1694 error = match *property {
1695 PropertyId::Custom(ref c) => {
1696 StyleParseErrorKind::new_invalid(format!("--{}", c), error)
1697 },
1698 _ => StyleParseErrorKind::new_invalid(
1699 property.non_custom_id().unwrap().name(),
1700 error,
1701 ),
1702 };
1703 }
1704 }
1705
1706 let location = error.location;
1707 let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors);
1708 context.log_css_error(location, error);
1709}
1710
1711pub fn parse_property_declaration_list(
1714 context: &ParserContext,
1715 input: &mut Parser,
1716 selectors: &[SelectorList<SelectorImpl>],
1717) -> PropertyDeclarationBlock {
1718 let mut state = DeclarationParserState::default();
1719 let mut parser = PropertyDeclarationParser {
1720 context,
1721 state: &mut state,
1722 };
1723 let mut iter = RuleBodyParser::new(input, &mut parser);
1724 while let Some(declaration) = iter.next() {
1725 match declaration {
1726 Ok(()) => {},
1727 Err((error, slice)) => iter.parser.state.did_error(context, error, slice),
1728 }
1729 }
1730 parser.state.report_errors_if_needed(context, selectors);
1731 state.output_block
1732}