aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-05-24 23:26:23 -0500
committerGitHub <noreply@github.com>2017-05-24 23:26:23 -0500
commit0d6b0da3544359343b191354ecc258e42394c5dd (patch)
treed72d13a20f7e751268140c676cba9bd5d06d608b
parent8d950bd62036cebeb6596e74f412444061e59512 (diff)
parent31584e3c14310491f5b1269164cb774079fc285d (diff)
downloadservo-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.rs2
-rw-r--r--components/style/document_condition.rs4
-rw-r--r--components/style/font_face.rs2
-rw-r--r--components/style/gecko/generated/bindings.rs4
-rw-r--r--components/style/keyframes.rs12
-rw-r--r--components/style/stylesheets.rs195
-rw-r--r--components/style/supports.rs4
-rw-r--r--components/style/viewport.rs2
-rw-r--r--ports/geckolib/glue.rs6
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
{