1mod appearance_base_rule;
8pub mod container_rule;
9mod counter_style_rule;
10mod document_rule;
11mod font_face_rule;
12pub mod font_feature_values_rule;
13pub mod font_palette_values_rule;
14pub mod import_rule;
15pub mod keyframes_rule;
16pub mod layer_rule;
17mod loader;
18mod margin_rule;
19mod media_rule;
20mod namespace_rule;
21mod nested_declarations_rule;
22pub mod origin;
23mod page_rule;
24pub mod position_try_rule;
25mod property_rule;
26mod rule_list;
27mod rule_parser;
28mod rules_iterator;
29pub mod scope_rule;
30mod starting_style_rule;
31mod style_rule;
32mod stylesheet;
33pub mod supports_rule;
34pub mod view_transition_rule;
35
36use crate::derives::*;
37#[cfg(feature = "gecko")]
38use crate::gecko_bindings::sugar::refptr::RefCounted;
39#[cfg(feature = "gecko")]
40use crate::gecko_bindings::{bindings, structs};
41use crate::parser::{NestingContext, ParserContext};
42use crate::properties::{parse_property_declaration_list, PropertyDeclarationBlock};
43use crate::shared_lock::{DeepCloneWithLock, Locked};
44use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
45use cssparser::{parse_one_rule, Parser, ParserInput};
46#[cfg(feature = "gecko")]
47use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
48use servo_arc::Arc;
49use std::borrow::Cow;
50use std::fmt::{self, Write};
51#[cfg(feature = "gecko")]
52use std::mem::{self, ManuallyDrop};
53use style_traits::{CssStringWriter, ParsingMode};
54use to_shmem::{SharedMemoryBuilder, ToShmem};
55
56pub use self::appearance_base_rule::AppearanceBaseRule;
57pub use self::container_rule::ContainerRule;
58pub use self::counter_style_rule::CounterStyleRule;
59pub use self::document_rule::DocumentRule;
60pub use self::font_face_rule::FontFaceRule;
61pub use self::font_feature_values_rule::FontFeatureValuesRule;
62pub use self::font_palette_values_rule::FontPaletteValuesRule;
63pub use self::import_rule::ImportRule;
64pub use self::keyframes_rule::KeyframesRule;
65pub use self::layer_rule::{LayerBlockRule, LayerStatementRule};
66pub use self::loader::StylesheetLoader;
67pub use self::margin_rule::{MarginRule, MarginRuleType};
68pub use self::media_rule::{
69 CustomMediaCondition, CustomMediaEvaluator, CustomMediaMap, CustomMediaRule, MediaRule,
70};
71pub use self::namespace_rule::NamespaceRule;
72pub use self::nested_declarations_rule::NestedDeclarationsRule;
73pub use self::origin::{Origin, OriginSet, OriginSetIterator, PerOrigin, PerOriginIter};
74pub use self::page_rule::{PagePseudoClassFlags, PageRule, PageSelector, PageSelectors};
75pub use self::position_try_rule::PositionTryRule;
76pub use self::property_rule::PropertyRule;
77pub use self::rule_list::CssRules;
78pub use self::rule_parser::{InsertRuleContext, State, TopLevelRuleParser};
79pub use self::rules_iterator::{AllRules, EffectiveRules};
80pub use self::rules_iterator::{
81 EffectiveRulesIterator, NestedRuleIterationCondition, RulesIterator,
82};
83pub use self::scope_rule::ScopeRule;
84pub use self::starting_style_rule::StartingStyleRule;
85pub use self::style_rule::StyleRule;
86pub use self::stylesheet::{AllowImportRules, SanitizationData, SanitizationKind};
87pub use self::stylesheet::{DocumentStyleSheet, Namespaces, Stylesheet};
88pub use self::stylesheet::{StylesheetContents, StylesheetInDocument};
89pub use self::supports_rule::SupportsRule;
90pub use self::view_transition_rule::{NavigationType, ViewTransitionRule};
91
92#[repr(u8)]
94#[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
95pub enum CorsMode {
96 None,
98 Anonymous,
100}
101
102#[cfg(feature = "gecko")]
116#[derive(MallocSizeOf, PartialEq)]
119#[repr(C)]
120pub struct UrlExtraData(usize);
121
122#[cfg(feature = "servo")]
124#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
125pub struct UrlExtraData(#[ignore_malloc_size_of = "Arc"] pub Arc<::url::Url>);
126
127#[cfg(feature = "servo")]
128impl UrlExtraData {
129 pub fn chrome_rules_enabled(&self) -> bool {
131 self.0.scheme() == "chrome"
132 }
133
134 pub fn as_str(&self) -> &str {
136 self.0.as_str()
137 }
138}
139
140#[cfg(feature = "servo")]
141impl From<::url::Url> for UrlExtraData {
142 fn from(url: ::url::Url) -> Self {
143 Self(Arc::new(url))
144 }
145}
146
147#[cfg(not(feature = "gecko"))]
148impl ToShmem for UrlExtraData {
149 fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> to_shmem::Result<Self> {
150 unimplemented!("If servo wants to share stylesheets across processes, ToShmem for Url must be implemented");
151 }
152}
153
154#[cfg(feature = "gecko")]
155impl Clone for UrlExtraData {
156 fn clone(&self) -> UrlExtraData {
157 UrlExtraData::new(self.ptr())
158 }
159}
160
161#[cfg(feature = "gecko")]
162impl Drop for UrlExtraData {
163 fn drop(&mut self) {
164 if self.0 & 1 == 0 {
166 unsafe {
167 self.as_ref().release();
168 }
169 }
170 }
171}
172
173#[cfg(feature = "gecko")]
174impl ToShmem for UrlExtraData {
175 fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> to_shmem::Result<Self> {
176 if self.0 & 1 == 0 {
177 let shared_extra_datas = unsafe {
178 std::ptr::addr_of!(structs::URLExtraData_sShared)
179 .as_ref()
180 .unwrap()
181 };
182 let self_ptr = self.as_ref() as *const _ as *mut _;
183 let sheet_id = shared_extra_datas
184 .iter()
185 .position(|r| r.mRawPtr == self_ptr);
186 let sheet_id = match sheet_id {
187 Some(id) => id,
188 None => {
189 return Err(String::from(
190 "ToShmem failed for UrlExtraData: expected sheet's URLExtraData to be in \
191 URLExtraData::sShared",
192 ));
193 },
194 };
195 Ok(ManuallyDrop::new(UrlExtraData((sheet_id << 1) | 1)))
196 } else {
197 Ok(ManuallyDrop::new(UrlExtraData(self.0)))
198 }
199 }
200}
201
202#[cfg(feature = "gecko")]
203impl UrlExtraData {
204 pub fn new(ptr: *mut structs::URLExtraData) -> UrlExtraData {
207 unsafe {
208 (*ptr).addref();
209 }
210 UrlExtraData(ptr as usize)
211 }
212
213 #[inline]
215 pub fn chrome_rules_enabled(&self) -> bool {
216 self.as_ref().mChromeRulesEnabled
217 }
218
219 #[inline]
225 pub unsafe fn from_ptr_ref(ptr: &*mut structs::URLExtraData) -> &Self {
226 mem::transmute(ptr)
227 }
228
229 pub fn ptr(&self) -> *mut structs::URLExtraData {
231 if self.0 & 1 == 0 {
232 self.0 as *mut structs::URLExtraData
233 } else {
234 unsafe {
235 let sheet_id = self.0 >> 1;
236 structs::URLExtraData_sShared[sheet_id].mRawPtr
237 }
238 }
239 }
240
241 fn as_ref(&self) -> &structs::URLExtraData {
242 unsafe { &*(self.ptr() as *const structs::URLExtraData) }
243 }
244}
245
246#[cfg(feature = "gecko")]
247impl fmt::Debug for UrlExtraData {
248 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
249 macro_rules! define_debug_struct {
250 ($struct_name:ident, $gecko_class:ident, $debug_fn:ident) => {
251 struct $struct_name(*mut structs::$gecko_class);
252 impl fmt::Debug for $struct_name {
253 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
254 use nsstring::nsCString;
255 let mut spec = nsCString::new();
256 unsafe {
257 bindings::$debug_fn(self.0, &mut spec);
258 }
259 spec.fmt(formatter)
260 }
261 }
262 };
263 }
264
265 define_debug_struct!(DebugURI, nsIURI, Gecko_nsIURI_Debug);
266 define_debug_struct!(
267 DebugReferrerInfo,
268 nsIReferrerInfo,
269 Gecko_nsIReferrerInfo_Debug
270 );
271
272 formatter
273 .debug_struct("URLExtraData")
274 .field("chrome_rules_enabled", &self.chrome_rules_enabled())
275 .field("base", &DebugURI(self.as_ref().mBaseURI.raw()))
276 .field(
277 "referrer",
278 &DebugReferrerInfo(self.as_ref().mReferrerInfo.raw()),
279 )
280 .finish()
281 }
282}
283
284#[cfg(feature = "gecko")]
287impl Eq for UrlExtraData {}
288
289fn style_or_page_rule_to_css(
296 rules: Option<&Arc<Locked<CssRules>>>,
297 block: &Locked<PropertyDeclarationBlock>,
298 guard: &SharedRwLockReadGuard,
299 dest: &mut CssStringWriter,
300) -> fmt::Result {
301 dest.write_char('{')?;
303
304 let declaration_block = block.read_with(guard);
306 let has_declarations = !declaration_block.declarations().is_empty();
307
308 if let Some(ref rules) = rules {
310 let rules = rules.read_with(guard);
311 if !rules.is_empty() {
313 if has_declarations {
314 dest.write_str("\n ")?;
315 declaration_block.to_css(dest)?;
316 }
317 return rules.to_css_block_without_opening(guard, dest);
318 }
319 }
320
321 if has_declarations {
323 dest.write_char(' ')?;
324 declaration_block.to_css(dest)?;
325 }
326 dest.write_str(" }")
327}
328
329#[derive(Clone, Debug, ToShmem)]
333#[allow(missing_docs)]
334pub enum CssRule {
335 Style(Arc<Locked<StyleRule>>),
336 Namespace(Arc<NamespaceRule>),
339 Import(Arc<Locked<ImportRule>>),
340 Media(Arc<MediaRule>),
341 CustomMedia(Arc<CustomMediaRule>),
342 Container(Arc<ContainerRule>),
343 FontFace(Arc<Locked<FontFaceRule>>),
344 FontFeatureValues(Arc<FontFeatureValuesRule>),
345 FontPaletteValues(Arc<FontPaletteValuesRule>),
346 CounterStyle(Arc<Locked<CounterStyleRule>>),
347 Keyframes(Arc<Locked<KeyframesRule>>),
348 Margin(Arc<MarginRule>),
349 Supports(Arc<SupportsRule>),
350 Page(Arc<Locked<PageRule>>),
351 Property(Arc<PropertyRule>),
352 Document(Arc<DocumentRule>),
353 LayerBlock(Arc<LayerBlockRule>),
354 LayerStatement(Arc<LayerStatementRule>),
355 Scope(Arc<ScopeRule>),
356 StartingStyle(Arc<StartingStyleRule>),
357 AppearanceBase(Arc<AppearanceBaseRule>),
358 PositionTry(Arc<Locked<PositionTryRule>>),
359 NestedDeclarations(Arc<Locked<NestedDeclarationsRule>>),
360 ViewTransition(Arc<ViewTransitionRule>),
361}
362
363impl CssRule {
364 #[cfg(feature = "gecko")]
366 fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
367 match *self {
368 CssRule::Namespace(_) => 0,
371
372 CssRule::Import(_) => 0,
375
376 CssRule::Style(ref lock) => {
377 lock.unconditional_shallow_size_of(ops) + lock.read_with(guard).size_of(guard, ops)
378 },
379 CssRule::Media(ref arc) => {
380 arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
381 },
382 CssRule::CustomMedia(ref arc) => {
383 arc.unconditional_shallow_size_of(ops)
385 },
386 CssRule::Container(ref arc) => {
387 arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
388 },
389 CssRule::FontFace(_) => 0,
390 CssRule::FontFeatureValues(_) => 0,
391 CssRule::FontPaletteValues(_) => 0,
392 CssRule::CounterStyle(_) => 0,
393 CssRule::Keyframes(_) => 0,
394 CssRule::Margin(ref arc) => {
395 arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
396 },
397 CssRule::Supports(ref arc) => {
398 arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
399 },
400 CssRule::Page(ref lock) => {
401 lock.unconditional_shallow_size_of(ops) + lock.read_with(guard).size_of(guard, ops)
402 },
403 CssRule::Property(ref rule) => {
404 rule.unconditional_shallow_size_of(ops) + rule.size_of(guard, ops)
405 },
406 CssRule::Document(ref arc) => {
407 arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
408 },
409 CssRule::StartingStyle(ref arc) => {
410 arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
411 },
412 CssRule::AppearanceBase(ref arc) => {
413 arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
414 },
415 CssRule::LayerBlock(_) | CssRule::LayerStatement(_) => 0,
417 CssRule::Scope(ref rule) => {
418 rule.unconditional_shallow_size_of(ops) + rule.size_of(guard, ops)
419 },
420 CssRule::PositionTry(ref lock) => {
421 lock.unconditional_shallow_size_of(ops) + lock.read_with(guard).size_of(guard, ops)
422 },
423 CssRule::NestedDeclarations(ref lock) => {
424 lock.unconditional_shallow_size_of(ops) + lock.read_with(guard).size_of(guard, ops)
425 },
426 CssRule::ViewTransition(ref rule) => {
427 use malloc_size_of::MallocSizeOf;
428
429 rule.unconditional_shallow_size_of(ops) + rule.size_of(ops)
430 },
431 }
432 }
433
434 fn is_empty_nested_declarations(&self, guard: &SharedRwLockReadGuard) -> bool {
435 match *self {
436 CssRule::NestedDeclarations(ref lock) => {
437 lock.read_with(guard).block.read_with(guard).is_empty()
438 },
439 _ => false,
440 }
441 }
442
443 pub fn children<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a [CssRule] {
445 match *self {
446 CssRule::Namespace(_)
447 | CssRule::FontFace(_)
448 | CssRule::CounterStyle(_)
449 | CssRule::CustomMedia(_)
450 | CssRule::Keyframes(_)
451 | CssRule::Margin(_)
452 | CssRule::Property(_)
453 | CssRule::LayerStatement(_)
454 | CssRule::FontFeatureValues(_)
455 | CssRule::FontPaletteValues(_)
456 | CssRule::NestedDeclarations(_)
457 | CssRule::PositionTry(_)
458 | CssRule::ViewTransition(_) => &[],
459 CssRule::Page(ref page_rule) => {
460 let page_rule = page_rule.read_with(guard);
461 let rules = page_rule.rules.read_with(guard);
462 rules.0.as_slice()
463 },
464 CssRule::Style(ref style_rule) => {
465 let style_rule = style_rule.read_with(guard);
466 match style_rule.rules.as_ref() {
467 Some(r) => r.read_with(guard).0.as_slice(),
468 None => &[],
469 }
470 },
471 CssRule::Import(ref import_rule) => {
472 let import_rule = import_rule.read_with(guard);
473 import_rule.stylesheet.rules(guard)
474 },
475 CssRule::Document(ref doc_rule) => doc_rule.rules.read_with(guard).0.as_slice(),
476 CssRule::Container(ref container_rule) => {
477 container_rule.rules.read_with(guard).0.as_slice()
478 },
479 CssRule::Media(ref media_rule) => media_rule.rules.read_with(guard).0.as_slice(),
480 CssRule::Supports(ref supports_rule) => {
481 supports_rule.rules.read_with(guard).0.as_slice()
482 },
483 CssRule::LayerBlock(ref layer_rule) => layer_rule.rules.read_with(guard).0.as_slice(),
484 CssRule::Scope(ref rule) => rule.rules.read_with(guard).0.as_slice(),
485 CssRule::StartingStyle(ref rule) => rule.rules.read_with(guard).0.as_slice(),
486 CssRule::AppearanceBase(ref rule) => rule.rules.read_with(guard).0.as_slice(),
487 }
488 }
489}
490
491pub type LockedStyleRule = Locked<StyleRule>;
494pub type LockedImportRule = Locked<ImportRule>;
496pub type LockedFontFaceRule = Locked<FontFaceRule>;
498pub type LockedCounterStyleRule = Locked<CounterStyleRule>;
500pub type LockedKeyframesRule = Locked<KeyframesRule>;
502pub type LockedPageRule = Locked<PageRule>;
504pub type LockedPositionTryRule = Locked<PositionTryRule>;
506pub type LockedNestedDeclarationsRule = Locked<NestedDeclarationsRule>;
508
509#[repr(C)]
511#[allow(missing_docs)]
512pub enum CssRuleRef<'a> {
513 Style(&'a LockedStyleRule),
514 Namespace(&'a NamespaceRule),
515 Import(&'a LockedImportRule),
516 Media(&'a MediaRule),
517 CustomMedia(&'a CustomMediaRule),
518 Container(&'a ContainerRule),
519 FontFace(&'a LockedFontFaceRule),
520 FontFeatureValues(&'a FontFeatureValuesRule),
521 FontPaletteValues(&'a FontPaletteValuesRule),
522 CounterStyle(&'a LockedCounterStyleRule),
523 Keyframes(&'a LockedKeyframesRule),
524 Margin(&'a MarginRule),
525 Supports(&'a SupportsRule),
526 Page(&'a LockedPageRule),
527 Property(&'a PropertyRule),
528 Document(&'a DocumentRule),
529 LayerBlock(&'a LayerBlockRule),
530 LayerStatement(&'a LayerStatementRule),
531 Scope(&'a ScopeRule),
532 StartingStyle(&'a StartingStyleRule),
533 AppearanceBase(&'a AppearanceBaseRule),
534 PositionTry(&'a LockedPositionTryRule),
535 NestedDeclarations(&'a LockedNestedDeclarationsRule),
536 ViewTransition(&'a ViewTransitionRule),
537}
538
539impl<'a> From<&'a CssRule> for CssRuleRef<'a> {
540 fn from(value: &'a CssRule) -> Self {
541 match value {
542 CssRule::Style(r) => CssRuleRef::Style(r.as_ref()),
543 CssRule::Namespace(r) => CssRuleRef::Namespace(r.as_ref()),
544 CssRule::Import(r) => CssRuleRef::Import(r.as_ref()),
545 CssRule::Media(r) => CssRuleRef::Media(r.as_ref()),
546 CssRule::CustomMedia(r) => CssRuleRef::CustomMedia(r.as_ref()),
547 CssRule::Container(r) => CssRuleRef::Container(r.as_ref()),
548 CssRule::FontFace(r) => CssRuleRef::FontFace(r.as_ref()),
549 CssRule::FontFeatureValues(r) => CssRuleRef::FontFeatureValues(r.as_ref()),
550 CssRule::FontPaletteValues(r) => CssRuleRef::FontPaletteValues(r.as_ref()),
551 CssRule::CounterStyle(r) => CssRuleRef::CounterStyle(r.as_ref()),
552 CssRule::Keyframes(r) => CssRuleRef::Keyframes(r.as_ref()),
553 CssRule::Margin(r) => CssRuleRef::Margin(r.as_ref()),
554 CssRule::Supports(r) => CssRuleRef::Supports(r.as_ref()),
555 CssRule::Page(r) => CssRuleRef::Page(r.as_ref()),
556 CssRule::Property(r) => CssRuleRef::Property(r.as_ref()),
557 CssRule::Document(r) => CssRuleRef::Document(r.as_ref()),
558 CssRule::LayerBlock(r) => CssRuleRef::LayerBlock(r.as_ref()),
559 CssRule::LayerStatement(r) => CssRuleRef::LayerStatement(r.as_ref()),
560 CssRule::Scope(r) => CssRuleRef::Scope(r.as_ref()),
561 CssRule::StartingStyle(r) => CssRuleRef::StartingStyle(r.as_ref()),
562 CssRule::AppearanceBase(r) => CssRuleRef::AppearanceBase(r.as_ref()),
563 CssRule::PositionTry(r) => CssRuleRef::PositionTry(r.as_ref()),
564 CssRule::NestedDeclarations(r) => CssRuleRef::NestedDeclarations(r.as_ref()),
565 CssRule::ViewTransition(r) => CssRuleRef::ViewTransition(r.as_ref()),
566 }
567 }
568}
569
570#[allow(missing_docs)]
572#[derive(Clone, Copy, Debug, Eq, FromPrimitive, PartialEq)]
573#[repr(u8)]
574pub enum CssRuleType {
575 Style = 1,
577 Import = 3,
579 Media = 4,
580 FontFace = 5,
581 Page = 6,
582 Keyframes = 7,
584 Keyframe = 8,
585 Margin = 9,
587 Namespace = 10,
588 CounterStyle = 11,
590 Supports = 12,
592 Document = 13,
594 FontFeatureValues = 14,
596 LayerBlock = 16,
599 LayerStatement = 17,
600 Container = 18,
601 FontPaletteValues = 19,
602 Property = 20,
604 Scope = 21,
605 StartingStyle = 22,
607 PositionTry = 23,
609 NestedDeclarations = 24,
611 CustomMedia = 25,
612 AppearanceBase = 26,
614 ViewTransition = 27,
616}
617
618impl CssRuleType {
619 #[inline]
621 pub const fn bit(self) -> u32 {
622 1 << self as u32
623 }
624}
625
626#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
628pub struct CssRuleTypes(u32);
629
630impl From<CssRuleType> for CssRuleTypes {
631 fn from(ty: CssRuleType) -> Self {
632 Self(ty.bit())
633 }
634}
635
636impl CssRuleTypes {
637 pub const IMPORTANT_FORBIDDEN: Self =
639 Self(CssRuleType::PositionTry.bit() | CssRuleType::Keyframe.bit());
640
641 #[inline]
643 pub fn contains(self, ty: CssRuleType) -> bool {
644 self.0 & ty.bit() != 0
645 }
646
647 #[inline]
649 pub fn bits(self) -> u32 {
650 self.0
651 }
652
653 #[inline]
655 pub fn from_bits(bits: u32) -> Self {
656 Self(bits)
657 }
658
659 #[inline]
661 pub fn is_empty(self) -> bool {
662 self.0 == 0
663 }
664
665 #[inline]
667 pub fn insert(&mut self, ty: CssRuleType) {
668 self.0 |= ty.bit()
669 }
670
671 #[inline]
673 pub fn intersects(self, other: Self) -> bool {
674 self.0 & other.0 != 0
675 }
676}
677
678#[allow(missing_docs)]
679pub enum RulesMutateError {
680 Syntax,
681 IndexSize,
682 HierarchyRequest,
683 InvalidState,
684}
685
686impl CssRule {
687 pub fn rule_type(&self) -> CssRuleType {
689 match *self {
690 CssRule::Style(_) => CssRuleType::Style,
691 CssRule::Import(_) => CssRuleType::Import,
692 CssRule::Media(_) => CssRuleType::Media,
693 CssRule::CustomMedia(_) => CssRuleType::CustomMedia,
694 CssRule::FontFace(_) => CssRuleType::FontFace,
695 CssRule::FontFeatureValues(_) => CssRuleType::FontFeatureValues,
696 CssRule::FontPaletteValues(_) => CssRuleType::FontPaletteValues,
697 CssRule::CounterStyle(_) => CssRuleType::CounterStyle,
698 CssRule::Keyframes(_) => CssRuleType::Keyframes,
699 CssRule::Margin(_) => CssRuleType::Margin,
700 CssRule::Namespace(_) => CssRuleType::Namespace,
701 CssRule::Supports(_) => CssRuleType::Supports,
702 CssRule::Page(_) => CssRuleType::Page,
703 CssRule::Property(_) => CssRuleType::Property,
704 CssRule::Document(_) => CssRuleType::Document,
705 CssRule::LayerBlock(_) => CssRuleType::LayerBlock,
706 CssRule::LayerStatement(_) => CssRuleType::LayerStatement,
707 CssRule::Container(_) => CssRuleType::Container,
708 CssRule::Scope(_) => CssRuleType::Scope,
709 CssRule::StartingStyle(_) => CssRuleType::StartingStyle,
710 CssRule::AppearanceBase(_) => CssRuleType::AppearanceBase,
711 CssRule::PositionTry(_) => CssRuleType::PositionTry,
712 CssRule::NestedDeclarations(_) => CssRuleType::NestedDeclarations,
713 CssRule::ViewTransition(_) => CssRuleType::ViewTransition,
714 }
715 }
716
717 pub fn parse(
721 css: &str,
722 insert_rule_context: InsertRuleContext,
723 parent_stylesheet_contents: &StylesheetContents,
724 shared_lock: &SharedRwLock,
725 loader: Option<&dyn StylesheetLoader>,
726 allow_import_rules: AllowImportRules,
727 ) -> Result<Self, RulesMutateError> {
728 let url_data = &parent_stylesheet_contents.url_data;
729 let namespaces = &parent_stylesheet_contents.namespaces;
730 let mut context = ParserContext::new(
731 parent_stylesheet_contents.origin,
732 &url_data,
733 None,
734 ParsingMode::DEFAULT,
735 parent_stylesheet_contents.quirks_mode,
736 Cow::Borrowed(&*namespaces),
737 None,
738 None,
739 );
740 context.nesting_context = NestingContext::new(
742 insert_rule_context.containing_rule_types,
743 insert_rule_context.parse_relative_rule_type,
744 );
745
746 let state = if !insert_rule_context.containing_rule_types.is_empty() {
747 State::Body
748 } else if insert_rule_context.index == 0 {
749 State::Start
750 } else {
751 let index = insert_rule_context.index;
752 insert_rule_context.max_rule_state_at_index(index - 1)
753 };
754
755 let mut input = ParserInput::new(css);
756 let mut input = Parser::new(&mut input);
757
758 let mut parser = TopLevelRuleParser {
760 context,
761 shared_lock: &shared_lock,
762 loader,
763 state,
764 dom_error: None,
765 insert_rule_context: Some(insert_rule_context),
766 allow_import_rules,
767 declaration_parser_state: Default::default(),
768 first_declaration_block: Default::default(),
769 wants_first_declaration_block: false,
770 error_reporting_state: Default::default(),
771 rules: Default::default(),
772 };
773
774 if input
775 .try_parse(|input| parse_one_rule(input, &mut parser))
776 .is_ok()
777 {
778 return Ok(parser.rules.pop().unwrap());
779 }
780
781 let error = parser.dom_error.take().unwrap_or(RulesMutateError::Syntax);
782 if matches!(error, RulesMutateError::Syntax) && parser.can_parse_declarations() {
784 let declarations = parse_property_declaration_list(&parser.context, &mut input, &[]);
785 if !declarations.is_empty() {
786 return Ok(CssRule::NestedDeclarations(Arc::new(
787 parser.shared_lock.wrap(NestedDeclarationsRule {
788 block: Arc::new(parser.shared_lock.wrap(declarations)),
789 source_location: input.current_source_location(),
790 }),
791 )));
792 }
793 }
794 Err(error)
795 }
796}
797
798impl DeepCloneWithLock for CssRule {
799 fn deep_clone_with_lock(&self, lock: &SharedRwLock, guard: &SharedRwLockReadGuard) -> CssRule {
801 match *self {
802 CssRule::Namespace(ref arc) => CssRule::Namespace(arc.clone()),
803 CssRule::Import(ref arc) => {
804 let rule = arc.read_with(guard).deep_clone_with_lock(lock, guard);
805 CssRule::Import(Arc::new(lock.wrap(rule)))
806 },
807 CssRule::Style(ref arc) => {
808 let rule = arc.read_with(guard);
809 CssRule::Style(Arc::new(lock.wrap(rule.deep_clone_with_lock(lock, guard))))
810 },
811 CssRule::Container(ref arc) => {
812 CssRule::Container(Arc::new(arc.deep_clone_with_lock(lock, guard)))
813 },
814 CssRule::Media(ref arc) => {
815 CssRule::Media(Arc::new(arc.deep_clone_with_lock(lock, guard)))
816 },
817 CssRule::CustomMedia(ref arc) => {
818 CssRule::CustomMedia(Arc::new(arc.deep_clone_with_lock(lock, guard)))
819 },
820 CssRule::FontFace(ref arc) => {
821 let rule = arc.read_with(guard);
822 CssRule::FontFace(Arc::new(lock.wrap(rule.clone())))
823 },
824 CssRule::FontFeatureValues(ref arc) => CssRule::FontFeatureValues(arc.clone()),
825 CssRule::FontPaletteValues(ref arc) => CssRule::FontPaletteValues(arc.clone()),
826 CssRule::CounterStyle(ref arc) => {
827 let rule = arc.read_with(guard);
828 CssRule::CounterStyle(Arc::new(lock.wrap(rule.clone())))
829 },
830 CssRule::Keyframes(ref arc) => {
831 let rule = arc.read_with(guard);
832 CssRule::Keyframes(Arc::new(lock.wrap(rule.deep_clone_with_lock(lock, guard))))
833 },
834 CssRule::Margin(ref arc) => {
835 CssRule::Margin(Arc::new(arc.deep_clone_with_lock(lock, guard)))
836 },
837 CssRule::Supports(ref arc) => {
838 CssRule::Supports(Arc::new(arc.deep_clone_with_lock(lock, guard)))
839 },
840 CssRule::Page(ref arc) => {
841 let rule = arc.read_with(guard);
842 CssRule::Page(Arc::new(lock.wrap(rule.deep_clone_with_lock(lock, guard))))
843 },
844 CssRule::Property(ref arc) => {
845 CssRule::Property(arc.clone())
848 },
849 CssRule::Document(ref arc) => {
850 CssRule::Document(Arc::new(arc.deep_clone_with_lock(lock, guard)))
851 },
852 CssRule::LayerStatement(ref arc) => CssRule::LayerStatement(arc.clone()),
853 CssRule::LayerBlock(ref arc) => {
854 CssRule::LayerBlock(Arc::new(arc.deep_clone_with_lock(lock, guard)))
855 },
856 CssRule::Scope(ref arc) => {
857 CssRule::Scope(Arc::new(arc.deep_clone_with_lock(lock, guard)))
858 },
859 CssRule::StartingStyle(ref arc) => {
860 CssRule::StartingStyle(Arc::new(arc.deep_clone_with_lock(lock, guard)))
861 },
862 CssRule::AppearanceBase(ref arc) => {
863 CssRule::AppearanceBase(Arc::new(arc.deep_clone_with_lock(lock, guard)))
864 },
865 CssRule::PositionTry(ref arc) => {
866 let rule = arc.read_with(guard);
867 CssRule::PositionTry(Arc::new(lock.wrap(rule.deep_clone_with_lock(lock, guard))))
868 },
869 CssRule::NestedDeclarations(ref arc) => {
870 let decls = arc.read_with(guard);
871 CssRule::NestedDeclarations(Arc::new(lock.wrap(decls.clone())))
872 },
873 CssRule::ViewTransition(ref arc) => {
874 CssRule::ViewTransition(Arc::new(arc.deep_clone_with_lock(lock, guard)))
875 },
876 }
877 }
878}
879
880impl ToCssWithGuard for CssRule {
881 fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
883 match *self {
884 CssRule::Namespace(ref rule) => rule.to_css(guard, dest),
885 CssRule::Import(ref lock) => lock.read_with(guard).to_css(guard, dest),
886 CssRule::Style(ref lock) => lock.read_with(guard).to_css(guard, dest),
887 CssRule::FontFace(ref lock) => lock.read_with(guard).to_css(guard, dest),
888 CssRule::FontFeatureValues(ref rule) => rule.to_css(guard, dest),
889 CssRule::FontPaletteValues(ref rule) => rule.to_css(guard, dest),
890 CssRule::CounterStyle(ref lock) => lock.read_with(guard).to_css(guard, dest),
891 CssRule::Keyframes(ref lock) => lock.read_with(guard).to_css(guard, dest),
892 CssRule::Margin(ref rule) => rule.to_css(guard, dest),
893 CssRule::Media(ref rule) => rule.to_css(guard, dest),
894 CssRule::CustomMedia(ref rule) => rule.to_css(guard, dest),
895 CssRule::Supports(ref rule) => rule.to_css(guard, dest),
896 CssRule::Page(ref lock) => lock.read_with(guard).to_css(guard, dest),
897 CssRule::Property(ref rule) => rule.to_css(guard, dest),
898 CssRule::Document(ref rule) => rule.to_css(guard, dest),
899 CssRule::LayerBlock(ref rule) => rule.to_css(guard, dest),
900 CssRule::LayerStatement(ref rule) => rule.to_css(guard, dest),
901 CssRule::Container(ref rule) => rule.to_css(guard, dest),
902 CssRule::Scope(ref rule) => rule.to_css(guard, dest),
903 CssRule::StartingStyle(ref rule) => rule.to_css(guard, dest),
904 CssRule::AppearanceBase(ref rule) => rule.to_css(guard, dest),
905 CssRule::PositionTry(ref lock) => lock.read_with(guard).to_css(guard, dest),
906 CssRule::NestedDeclarations(ref lock) => lock.read_with(guard).to_css(guard, dest),
907 CssRule::ViewTransition(ref rule) => rule.to_css(guard, dest),
908 }
909 }
910}