diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-05-24 23:26:23 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-24 23:26:23 -0500 |
commit | 0d6b0da3544359343b191354ecc258e42394c5dd (patch) | |
tree | d72d13a20f7e751268140c676cba9bd5d06d608b | |
parent | 8d950bd62036cebeb6596e74f412444061e59512 (diff) | |
parent | 31584e3c14310491f5b1269164cb774079fc285d (diff) | |
download | servo-0d6b0da3544359343b191354ecc258e42394c5dd.tar.gz servo-0d6b0da3544359343b191354ecc258e42394c5dd.zip |
Auto merge of #17028 - bradwerth:innerClone, r=heycam
Stylo: Deep clone ServoStyleSheets.
MozReview-Commit-ID: 6hYIcOa86Y
<!-- Please describe your changes on the following line: -->
https://bugzilla.mozilla.org/show_bug.cgi?id=1339629
https://reviewboard.mozilla.org/r/135314/
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17028)
<!-- Reviewable:end -->
-rw-r--r-- | components/style/counter_style/mod.rs | 2 | ||||
-rw-r--r-- | components/style/document_condition.rs | 4 | ||||
-rw-r--r-- | components/style/font_face.rs | 2 | ||||
-rw-r--r-- | components/style/gecko/generated/bindings.rs | 4 | ||||
-rw-r--r-- | components/style/keyframes.rs | 12 | ||||
-rw-r--r-- | components/style/stylesheets.rs | 195 | ||||
-rw-r--r-- | components/style/supports.rs | 4 | ||||
-rw-r--r-- | components/style/viewport.rs | 2 | ||||
-rw-r--r-- | ports/geckolib/glue.rs | 6 |
9 files changed, 221 insertions, 10 deletions
diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index b1c461b4301..20cd638b758 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -142,7 +142,7 @@ macro_rules! counter_style_descriptors { $( #[$doc: meta] $name: tt $ident: ident / $gecko_ident: ident: $ty: ty = $initial: tt )+ ) => { /// An @counter-style rule - #[derive(Debug)] + #[derive(Clone, Debug)] pub struct CounterStyleRuleData { name: CustomIdent, $( diff --git a/components/style/document_condition.rs b/components/style/document_condition.rs index aef034f2eeb..b4e89adcce7 100644 --- a/components/style/document_condition.rs +++ b/components/style/document_condition.rs @@ -20,7 +20,7 @@ use style_traits::ToCss; use values::specified::url::SpecifiedUrl; /// A URL matching function for a `@document` rule's condition. -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum UrlMatchingFunction { /// Exact URL matching function. It evaluates to true whenever the /// URL of the document being styled is exactly the URL given. @@ -141,7 +141,7 @@ impl ToCss for UrlMatchingFunction { /// The `@document` rule's condition is written as a comma-separated list of /// URL matching functions, and the condition evaluates to true whenever any /// one of those functions evaluates to true. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct DocumentCondition(Vec<UrlMatchingFunction>); impl DocumentCondition { diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 4c953c3b028..439642f68c9 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -194,7 +194,7 @@ macro_rules! font_face_descriptors_common { /// Data inside a `@font-face` rule. /// /// https://drafts.csswg.org/css-fonts/#font-face-rule - #[derive(Debug, PartialEq, Eq)] + #[derive(Clone, Debug, PartialEq, Eq)] pub struct FontFaceRuleData { $( #[$doc] diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs index 028b4678c3f..a03c8ff8feb 100644 --- a/components/style/gecko/generated/bindings.rs +++ b/components/style/gecko/generated/bindings.rs @@ -1737,6 +1737,10 @@ extern "C" { -> ServoCssRulesStrong; } extern "C" { + pub fn Servo_StyleSheet_Clone(sheet: RawServoStyleSheetBorrowed) + -> RawServoStyleSheetStrong; +} +extern "C" { pub fn Servo_StyleSet_Init(pres_context: RawGeckoPresContextOwned) -> RawServoStyleSetOwned; } diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs index db60c86aa9e..e0c589a1c32 100644 --- a/components/style/keyframes.rs +++ b/components/style/keyframes.rs @@ -71,7 +71,7 @@ impl KeyframePercentage { /// A keyframes selector is a list of percentages or from/to symbols, which are /// converted at parse time to percentages. -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct KeyframeSelector(Vec<KeyframePercentage>); impl ToCss for KeyframeSelector { @@ -150,6 +150,16 @@ impl Keyframe { }; parse_one_rule(&mut input, &mut rule_parser) } + + /// Deep clones this Keyframe. + pub fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> Keyframe { + let guard = lock.read(); + Keyframe { + selector: self.selector.clone(), + block: Arc::new(lock.wrap(self.block.read_with(&guard).clone())), + } + } } /// A keyframes step value. This can be a synthetised keyframes animation, that diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 2c55c73fd8d..81a5fbc98dd 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -37,6 +37,7 @@ use servo_config::prefs::PREFS; #[cfg(not(feature = "gecko"))] use servo_url::ServoUrl; use shared_lock::{SharedRwLock, Locked, ToCssWithGuard, SharedRwLockReadGuard}; +use std::borrow::Borrow; use std::cell::Cell; use std::fmt; use std::sync::atomic::{AtomicBool, Ordering}; @@ -91,7 +92,7 @@ pub enum Origin { } /// A set of namespaces applying to a given stylesheet. -#[derive(Default, Debug)] +#[derive(Clone, Default, Debug)] #[allow(missing_docs)] pub struct Namespaces { pub default: Option<Namespace>, @@ -107,6 +108,15 @@ impl CssRules { pub fn is_empty(&self) -> bool { self.0.is_empty() } + + /// Creates a deep clone where each CssRule has also been cloned with + /// the provided lock. + fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> CssRules { + CssRules( + self.0.iter().map(|ref x| x.deep_clone_with_lock(lock)).collect() + ) + } } #[allow(missing_docs)] @@ -469,6 +479,64 @@ impl CssRule { } } } + + /// Deep clones this CssRule. + fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> CssRule { + let guard = lock.read(); + match *self { + CssRule::Namespace(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Namespace(Arc::new(lock.wrap(rule.clone()))) + }, + CssRule::Import(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Import(Arc::new(lock.wrap(rule.clone()))) + }, + CssRule::Style(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Style(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock)))) + }, + CssRule::Media(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Media(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock)))) + }, + CssRule::FontFace(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::FontFace(Arc::new(lock.wrap(rule.clone()))) + }, + CssRule::CounterStyle(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::CounterStyle(Arc::new(lock.wrap(rule.clone()))) + }, + CssRule::Viewport(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Viewport(Arc::new(lock.wrap(rule.clone()))) + }, + CssRule::Keyframes(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Keyframes(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock)))) + }, + CssRule::Supports(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Supports(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock)))) + }, + CssRule::Page(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Page(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock)))) + }, + CssRule::Document(ref arc) => { + let rule = arc.read_with(&guard); + CssRule::Document(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock)))) + }, + } + } } impl ToCssWithGuard for CssRule { @@ -500,7 +568,7 @@ fn get_location_with_offset(location: SourceLocation, offset: u64) } } -#[derive(Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] #[allow(missing_docs)] pub struct NamespaceRule { /// `None` for the default Namespace @@ -540,6 +608,16 @@ pub struct ImportRule { pub stylesheet: Arc<Stylesheet>, } +impl Clone for ImportRule { + fn clone(&self) -> ImportRule { + let stylesheet: &Stylesheet = self.stylesheet.borrow(); + ImportRule { + url: self.url.clone(), + stylesheet: Arc::new(stylesheet.clone()), + } + } +} + impl ToCssWithGuard for ImportRule { fn to_css<W>(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result where W: fmt::Write { @@ -604,6 +682,23 @@ impl KeyframesRule { } } +impl KeyframesRule { + /// Deep clones this KeyframesRule. + fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> KeyframesRule { + let guard = lock.read(); + KeyframesRule { + name: self.name.clone(), + keyframes: self.keyframes.iter() + .map(|ref x| Arc::new(lock.wrap( + x.read_with(&guard).deep_clone_with_lock(lock)))) + .collect(), + vendor_prefix: self.vendor_prefix.clone(), + source_location: self.source_location.clone(), + } + } +} + #[allow(missing_docs)] #[derive(Debug)] pub struct MediaRule { @@ -628,6 +723,21 @@ impl ToCssWithGuard for MediaRule { } } +impl MediaRule { + /// Deep clones this MediaRule. + fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> MediaRule { + let guard = lock.read(); + let media_queries = self.media_queries.read_with(&guard); + let rules = self.rules.read_with(&guard); + MediaRule { + media_queries: Arc::new(lock.wrap(media_queries.clone())), + rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock))), + source_location: self.source_location.clone(), + } + } +} + #[derive(Debug)] /// An @supports rule @@ -656,6 +766,20 @@ impl ToCssWithGuard for SupportsRule { } } +impl SupportsRule { + fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> SupportsRule { + let guard = lock.read(); + let rules = self.rules.read_with(&guard); + SupportsRule { + condition: self.condition.clone(), + rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock))), + enabled: self.enabled, + source_location: self.source_location.clone(), + } + } +} + /// A [`@page`][page] rule. This implements only a limited subset of the CSS 2.2 syntax. In this /// subset, [page selectors][page-selectors] are not implemented. /// @@ -682,6 +806,17 @@ impl ToCssWithGuard for PageRule { } } +impl PageRule { + fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> PageRule { + let guard = lock.read(); + PageRule { + block: Arc::new(lock.wrap(self.block.read_with(&guard).clone())), + source_location: self.source_location.clone(), + } + } +} + #[allow(missing_docs)] #[derive(Debug)] pub struct StyleRule { @@ -711,6 +846,19 @@ impl ToCssWithGuard for StyleRule { } } +impl StyleRule { + /// Deep clones this StyleRule. + fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> StyleRule { + let guard = lock.read(); + StyleRule { + selectors: self.selectors.clone(), + block: Arc::new(lock.wrap(self.block.read_with(&guard).clone())), + source_location: self.source_location.clone(), + } + } +} + /// A @font-face rule #[cfg(feature = "servo")] pub type FontFaceRule = FontFaceRuleData; @@ -744,6 +892,20 @@ impl ToCssWithGuard for DocumentRule { } } +impl DocumentRule { + /// Deep clones this DocumentRule. + fn deep_clone_with_lock(&self, + lock: &SharedRwLock) -> DocumentRule { + let guard = lock.read(); + let rules = self.rules.read_with(&guard); + DocumentRule { + condition: self.condition.clone(), + rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock))), + source_location: self.source_location.clone(), + } + } +} + impl Stylesheet { /// Updates an empty stylesheet from a given string of text. pub fn update_from_str(existing: &Stylesheet, @@ -901,6 +1063,35 @@ impl Stylesheet { } } +impl Clone for Stylesheet { + fn clone(&self) -> Stylesheet { + // Create a new lock for our clone. + let lock = self.shared_lock.clone(); + let guard = self.shared_lock.read(); + + // Make a deep clone of the rules, using the new lock. + let rules = self.rules.read_with(&guard); + let cloned_rules = rules.deep_clone_with_lock(&lock); + + // Make a deep clone of the media, using the new lock. + let media = self.media.read_with(&guard); + let cloned_media = media.clone(); + + Stylesheet { + rules: Arc::new(lock.wrap(cloned_rules)), + media: Arc::new(lock.wrap(cloned_media)), + origin: self.origin, + url_data: self.url_data.clone(), + shared_lock: lock, + namespaces: RwLock::new((*self.namespaces.read()).clone()), + dirty_on_viewport_size_change: AtomicBool::new( + self.dirty_on_viewport_size_change.load(Ordering::SeqCst)), + disabled: AtomicBool::new(self.disabled.load(Ordering::SeqCst)), + quirks_mode: self.quirks_mode, + } + } +} + fn effective_rules<F>(rules: &[CssRule], device: &Device, quirks_mode: QuirksMode, diff --git a/components/style/supports.rs b/components/style/supports.rs index 3b651ba9264..9b297963056 100644 --- a/components/style/supports.rs +++ b/components/style/supports.rs @@ -11,7 +11,7 @@ use std::fmt; use style_traits::ToCss; use stylesheets::CssRuleType; -#[derive(Debug)] +#[derive(Clone, Debug)] /// An @supports condition /// /// https://drafts.csswg.org/css-conditional-3/#at-supports @@ -162,7 +162,7 @@ impl ToCss for SupportsCondition { } } -#[derive(Debug)] +#[derive(Clone, Debug)] /// A possibly-invalid property declaration pub struct Declaration { /// The property name diff --git a/components/style/viewport.rs b/components/style/viewport.rs index 0953d9a4b7a..68ea6a3033f 100644 --- a/components/style/viewport.rs +++ b/components/style/viewport.rs @@ -309,7 +309,7 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> { } /// A `@viewport` rule. -#[derive(Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct ViewportRule { /// The declarations contained in this @viewport rule. diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 401cdac1a1f..0614858ad7a 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -792,6 +792,12 @@ pub extern "C" fn Servo_StyleSheet_GetRules(sheet: RawServoStyleSheetBorrowed) - Stylesheet::as_arc(&sheet).rules.clone().into_strong() } +#[no_mangle] +pub extern "C" fn Servo_StyleSheet_Clone(raw_sheet: RawServoStyleSheetBorrowed) -> RawServoStyleSheetStrong { + let sheet: &Arc<Stylesheet> = HasArcFFI::as_arc(&raw_sheet); + Arc::new(sheet.as_ref().clone()).into_strong() +} + fn read_locked_arc<T, R, F>(raw: &<Locked<T> as HasFFI>::FFIType, func: F) -> R where Locked<T>: HasArcFFI, F: FnOnce(&T) -> R { |