aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-10-13 22:31:20 -0500
committerGitHub <noreply@github.com>2016-10-13 22:31:20 -0500
commit41df7056610e474a9a2efe4c807f480e976d0c1d (patch)
treeeba7b6638a0c97e5454dfe81c31555445280f97d
parenta80abf6c1dd0f14b40499d55129a53d397c3a3cd (diff)
parentbb736f41d32c1cb6117bbf327f2a6efa7deebd0c (diff)
downloadservo-41df7056610e474a9a2efe4c807f480e976d0c1d.tar.gz
servo-41df7056610e474a9a2efe4c807f480e976d0c1d.zip
Auto merge of #13754 - Manishearth:refptr, r=emilio,mystor
Add sugar for RefPtr<T>; use for `quotes` property Carry-over from https://bugzilla.mozilla.org/show_bug.cgi?id=1309848 r=mystor,emilio <!-- 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/13754) <!-- Reviewable:end -->
-rwxr-xr-xcomponents/style/binding_tools/regen.py2
-rw-r--r--components/style/gecko_bindings/bindings.rs14
-rw-r--r--components/style/gecko_bindings/mod.rs1
-rw-r--r--components/style/gecko_bindings/ptr.rs64
-rw-r--r--components/style/gecko_bindings/sugar/mod.rs1
-rw-r--r--components/style/gecko_bindings/sugar/refptr.rs237
-rw-r--r--components/style/parser.rs2
-rw-r--r--components/style/properties/gecko.mako.rs29
-rw-r--r--components/style/properties/longhand/box.mako.rs2
-rw-r--r--components/style/properties/longhand/list.mako.rs2
-rw-r--r--components/style/values/specified/mod.rs2
-rw-r--r--ports/geckolib/glue.rs10
12 files changed, 287 insertions, 79 deletions
diff --git a/components/style/binding_tools/regen.py b/components/style/binding_tools/regen.py
index d179cc879f4..792b24e9656 100755
--- a/components/style/binding_tools/regen.py
+++ b/components/style/binding_tools/regen.py
@@ -228,7 +228,7 @@ COMPILATION_TARGETS = {
"StyleBasicShapeType", "StyleBasicShape", "nsCSSShadowArray",
"nsIPrincipal", "nsIURI",
"RawGeckoNode", "RawGeckoElement", "RawGeckoDocument",
- "nsString"
+ "nsString", "nsStyleQuoteValues"
],
"servo_nullable_arc_types": [
"ServoComputedValues", "RawServoStyleSheet",
diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs
index a7efe16be71..4def95850e1 100644
--- a/components/style/gecko_bindings/bindings.rs
+++ b/components/style/gecko_bindings/bindings.rs
@@ -164,6 +164,9 @@ use gecko_bindings::structs::RawGeckoNode;
use gecko_bindings::structs::RawGeckoElement;
use gecko_bindings::structs::RawGeckoDocument;
use gecko_bindings::structs::nsString;
+use gecko_bindings::structs::nsStyleQuoteValues;
+unsafe impl Send for nsStyleQuoteValues {}
+unsafe impl Sync for nsStyleQuoteValues {}
extern "C" {
pub fn Gecko_EnsureTArrayCapacity(aArray: *mut ::std::os::raw::c_void,
@@ -544,6 +547,17 @@ extern "C" {
*mut nsCSSShadowArray);
}
extern "C" {
+ pub fn Gecko_NewStyleQuoteValues(len: u32) -> *mut nsStyleQuoteValues;
+}
+extern "C" {
+ pub fn Gecko_AddRefQuoteValuesArbitraryThread(aPtr:
+ *mut nsStyleQuoteValues);
+}
+extern "C" {
+ pub fn Gecko_ReleaseQuoteValuesArbitraryThread(aPtr:
+ *mut nsStyleQuoteValues);
+}
+extern "C" {
pub fn Gecko_Construct_nsStyleFont(ptr: *mut nsStyleFont);
}
extern "C" {
diff --git a/components/style/gecko_bindings/mod.rs b/components/style/gecko_bindings/mod.rs
index 877af7b6ca9..7201bdb2668 100644
--- a/components/style/gecko_bindings/mod.rs
+++ b/components/style/gecko_bindings/mod.rs
@@ -4,7 +4,6 @@
#[allow(dead_code, improper_ctypes, non_camel_case_types)]
pub mod bindings;
-pub mod ptr;
// FIXME: We allow `improper_ctypes` (for now), because the lint doesn't allow
// foreign structs to have `PhantomData`. We should remove this once the lint
diff --git a/components/style/gecko_bindings/ptr.rs b/components/style/gecko_bindings/ptr.rs
deleted file mode 100644
index 6d97e6613d0..00000000000
--- a/components/style/gecko_bindings/ptr.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use gecko_bindings::bindings::*;
-use heapsize::HeapSizeOf;
-use std::fmt::{self, Debug};
-
-// Defines an Arc-like type that manages a refcounted Gecko object stored
-// in a ThreadSafeFooHolder smart pointer (for those Gecko classes that
-// do not have thread-safe refcounting support) or as raw pointers (for
-// those that do have thread-safe refcounting support). Used in tandem
-// with the NS_DECL_(HOLDER|THREADSAFE)_FFI_REFCOUNTING-defined types and
-// functions in Gecko.
-macro_rules! define_arc {
- ($arc_type:ident, $name:ident, $gecko_type:ident, $addref: ident, $release: ident) => (
- #[derive(PartialEq)]
- pub struct $arc_type {
- ptr: *mut $gecko_type,
- }
-
- impl $arc_type {
- pub fn new(data: *mut $gecko_type) -> $arc_type {
- debug_assert!(!data.is_null());
- unsafe { $addref(data); }
- $arc_type {
- ptr: data
- }
- }
-
- pub fn as_raw(&self) -> *mut $gecko_type { self.ptr }
- }
-
- unsafe impl Send for $arc_type {}
- unsafe impl Sync for $arc_type {}
-
- impl Clone for $arc_type {
- fn clone(&self) -> $arc_type {
- $arc_type::new(self.ptr)
- }
- }
-
- impl Drop for $arc_type {
- fn drop(&mut self) {
- unsafe { $release(self.ptr); }
- }
- }
-
- impl HeapSizeOf for $arc_type {
- fn heap_size_of_children(&self) -> usize { 0 }
- }
-
- impl Debug for $arc_type {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, stringify!($name))
- }
- }
- )
-}
-
-define_arc!(GeckoArcPrincipal, Principal, ThreadSafePrincipalHolder,
- Gecko_AddRefPrincipalArbitraryThread, Gecko_ReleasePrincipalArbitraryThread);
-define_arc!(GeckoArcURI, URI, ThreadSafeURIHolder,
- Gecko_AddRefURIArbitraryThread, Gecko_ReleaseURIArbitraryThread);
diff --git a/components/style/gecko_bindings/sugar/mod.rs b/components/style/gecko_bindings/sugar/mod.rs
index eb4460c63bc..5c7eb198184 100644
--- a/components/style/gecko_bindings/sugar/mod.rs
+++ b/components/style/gecko_bindings/sugar/mod.rs
@@ -8,4 +8,5 @@ mod ns_style_auto_array;
pub mod ns_style_coord;
mod ns_t_array;
pub mod ownership;
+pub mod refptr;
mod style_complex_color;
diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs
new file mode 100644
index 00000000000..9c7dcfddc63
--- /dev/null
+++ b/components/style/gecko_bindings/sugar/refptr.rs
@@ -0,0 +1,237 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use gecko_bindings::structs;
+use heapsize::HeapSizeOf;
+use std::{mem, ptr};
+use std::marker::PhantomData;
+use std::ops::{Deref, DerefMut};
+
+/// Trait for all objects that have Addref() and Release
+/// methods and can be placed inside RefPtr<T>
+pub unsafe trait RefCounted {
+ fn addref(&self);
+ unsafe fn release(&self);
+}
+
+/// Trait for types which can be shared across threads in RefPtr
+pub unsafe trait ThreadSafeRefCounted: RefCounted {}
+
+#[derive(Debug)]
+pub struct RefPtr<T: RefCounted> {
+ ptr: *mut T,
+ _marker: PhantomData<T>,
+}
+
+/// A RefPtr that we know is uniquely owned
+///
+/// This is basically Box<T>, with the additional
+/// guarantee that the box can be safely interpreted
+/// as a RefPtr<T> (with refcount 1)
+///
+/// This is useful when you wish to create a refptr
+/// and mutate it temporarily, while it is still
+/// uniquely owned.
+pub struct UniqueRefPtr<T: RefCounted>(RefPtr<T>);
+
+// There is no safe conversion from &T to RefPtr<T> (like Gecko has)
+// because this lets you break UniqueRefPtr's guarantee
+
+impl<T: RefCounted> RefPtr<T> {
+ /// Create a new RefPtr from an already addrefed
+ /// pointer obtained from FFI. Pointer
+ /// must be valid, non-null and have been addrefed
+ pub unsafe fn from_addrefed(ptr: *mut T) -> Self {
+ debug_assert!(!ptr.is_null());
+ RefPtr {
+ ptr: ptr,
+ _marker: PhantomData,
+ }
+ }
+
+ /// Create a new RefPtr from a pointer obtained
+ /// from FFI. Pointer must be valid and non null.
+ /// This method calls addref() internally
+ pub unsafe fn new(ptr: *mut T) -> Self {
+ debug_assert!(!ptr.is_null());
+ let ret = RefPtr {
+ ptr: ptr,
+ _marker: PhantomData,
+ };
+ ret.addref();
+ ret
+ }
+
+ /// Produces an FFI-compatible RefPtr that can be stored in
+ /// style structs.
+ ///
+ /// structs::RefPtr does not have a destructor, so this may leak
+ pub fn forget(self) -> structs::RefPtr<T> {
+ let ret = structs::RefPtr {
+ mRawPtr: self.ptr,
+ };
+ mem::forget(self);
+ ret
+ }
+
+ /// Returns the raw inner pointer
+ /// to be fed back into FFI
+ pub fn get(&self) -> *mut T {
+ self.ptr
+ }
+
+ /// Addref the inner data
+ ///
+ /// Leaky on its own
+ pub fn addref(&self) {
+ unsafe { (*self.ptr).addref(); }
+ }
+
+ /// Release the inner data
+ ///
+ /// Call only when the data actuall needs releasing
+ pub unsafe fn release(&self) {
+ (*self.ptr).release();
+ }
+}
+
+impl<T: RefCounted> UniqueRefPtr<T> {
+ /// Create a unique refptr from an already addrefed
+ /// pointer obtained from FFI. The refcount must be one.
+ /// The pointer must be valid and non null
+ pub unsafe fn from_addrefed(ptr: *mut T) -> Self {
+ UniqueRefPtr(RefPtr::from_addrefed(ptr))
+ }
+
+ /// Convert to a RefPtr so that it can be used
+ pub fn get(self) -> RefPtr<T> {
+ self.0
+ }
+}
+
+impl<T: RefCounted> Deref for RefPtr<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ unsafe { &*self.ptr }
+ }
+}
+
+impl<T: RefCounted> Deref for UniqueRefPtr<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ unsafe { &*self.0.ptr }
+ }
+}
+
+impl<T: RefCounted> DerefMut for UniqueRefPtr<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ unsafe { &mut *self.0.ptr }
+ }
+}
+
+impl<T: RefCounted> structs::RefPtr<T> {
+ /// Produces a Rust-side RefPtr from an FFI RefPtr, bumping the refcount
+ ///
+ /// Must be called on a valid, non-null structs::RefPtr<T>
+ pub unsafe fn to_safe(&self) -> RefPtr<T> {
+ debug_assert!(!self.mRawPtr.is_null());
+ let r = RefPtr {
+ ptr: self.mRawPtr,
+ _marker: PhantomData,
+ };
+ r.addref();
+ r
+ }
+ /// Produces a Rust-side RefPtr, consuming the existing one (and not bumping the refcount)
+ pub unsafe fn into_safe(self) -> RefPtr<T> {
+ debug_assert!(!self.mRawPtr.is_null());
+ RefPtr {
+ ptr: self.mRawPtr,
+ _marker: PhantomData,
+ }
+ }
+
+ /// Replace a structs::RefPtr<T> with a different one, appropriately addref/releasing
+ ///
+ /// Both `self` and `other` must be valid, but can be null
+ pub unsafe fn set(&mut self, other: &Self) {
+ if !self.mRawPtr.is_null() {
+ (*self.mRawPtr).release();
+ self.mRawPtr = ptr::null_mut();
+ }
+ if !other.mRawPtr.is_null() {
+ *self = other.to_safe().forget();
+ }
+ }
+
+ /// Replace a `structs::RefPtr<T>` with a `RefPtr<T>`,
+ /// consuming the `RefPtr<T>`, and releasing the old
+ /// value in `self` if necessary.
+ ///
+ /// `self` must be valid, possibly null
+ pub fn set_move(&mut self, other: RefPtr<T>) {
+ if !self.mRawPtr.is_null() {
+ unsafe { (*self.mRawPtr).release(); }
+ }
+ *self = other.forget();
+ }
+}
+
+impl<T: RefCounted> Drop for RefPtr<T> {
+ fn drop(&mut self) {
+ unsafe { self.release() }
+ }
+}
+
+impl<T: RefCounted> Clone for RefPtr<T> {
+ fn clone(&self) -> Self {
+ self.addref();
+ RefPtr {
+ ptr: self.ptr,
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl<T: RefCounted> HeapSizeOf for RefPtr<T> {
+ fn heap_size_of_children(&self) -> usize { 0 }
+}
+
+impl<T: RefCounted> PartialEq for RefPtr<T> {
+ fn eq(&self, other: &Self) -> bool {
+ self.ptr == other.ptr
+ }
+}
+
+unsafe impl<T: ThreadSafeRefCounted> Send for RefPtr<T> {}
+unsafe impl<T: ThreadSafeRefCounted> Sync for RefPtr<T> {}
+
+// Companion of NS_DECL_THREADSAFE_FFI_REFCOUNTING
+//
+// Gets you a free RefCounted impl
+macro_rules! impl_threadsafe_refcount {
+ ($t:ty, $addref:ident, $release:ident) => (
+ unsafe impl RefCounted for $t {
+ fn addref(&self) {
+ unsafe { ::gecko_bindings::bindings::$addref(self as *const _ as *mut _) }
+ }
+ unsafe fn release(&self) {
+ ::gecko_bindings::bindings::$release(self as *const _ as *mut _)
+ }
+ }
+ unsafe impl ThreadSafeRefCounted for $t {}
+ );
+}
+
+impl_threadsafe_refcount!(::gecko_bindings::bindings::ThreadSafePrincipalHolder,
+ Gecko_AddRefPrincipalArbitraryThread,
+ Gecko_ReleasePrincipalArbitraryThread);
+impl_threadsafe_refcount!(::gecko_bindings::bindings::ThreadSafeURIHolder,
+ Gecko_AddRefURIArbitraryThread,
+ Gecko_ReleaseURIArbitraryThread);
+impl_threadsafe_refcount!(::gecko_bindings::structs::nsStyleQuoteValues,
+ Gecko_AddRefQuoteValuesArbitraryThread,
+ Gecko_ReleaseQuoteValuesArbitraryThread);
+pub type GeckoArcPrincipal = RefPtr<::gecko_bindings::bindings::ThreadSafePrincipalHolder>;
+pub type GeckoArcURI = RefPtr<::gecko_bindings::bindings::ThreadSafeURIHolder>;
diff --git a/components/style/parser.rs b/components/style/parser.rs
index db281ec24e2..1cf46a80d09 100644
--- a/components/style/parser.rs
+++ b/components/style/parser.rs
@@ -7,7 +7,7 @@
use cssparser::{Parser, SourcePosition};
use error_reporting::ParseErrorReporter;
#[cfg(feature = "gecko")]
-use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
+use gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
use selector_impl::TheSelectorImpl;
use selectors::parser::ParserContext as SelectorParserContext;
use stylesheets::Origin;
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index 2561cd557f0..9dc9e8ceb96 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -896,9 +896,9 @@ fn static_assert() {
Gecko_SetMozBinding(&mut self.gecko,
url.as_str().as_ptr(),
url.as_str().len() as u32,
- extra_data.base.as_raw(),
- extra_data.referrer.as_raw(),
- extra_data.principal.as_raw());
+ extra_data.base.get(),
+ extra_data.referrer.get(),
+ extra_data.principal.get());
}
}
}
@@ -1448,7 +1448,7 @@ fn static_assert() {
</%self:simple_image_array_property>
</%self:impl_trait>
-<%self:impl_trait style_struct_name="List" skip_longhands="list-style-type" skip_additionals="*">
+<%self:impl_trait style_struct_name="List" skip_longhands="list-style-type quotes" skip_additionals="*">
${impl_keyword_setter("list_style_type", "__LIST_STYLE_TYPE__",
data.longhands_by_name["list-style-type"].keyword)}
@@ -1458,6 +1458,27 @@ fn static_assert() {
}
}
+ pub fn set_quotes(&mut self, other: longhands::quotes::computed_value::T) {
+ use gecko_bindings::bindings::Gecko_NewStyleQuoteValues;
+ use gecko_bindings::sugar::refptr::UniqueRefPtr;
+ use nsstring::nsCString;
+
+ let mut refptr = unsafe {
+ UniqueRefPtr::from_addrefed(Gecko_NewStyleQuoteValues(other.0.len() as u32))
+ };
+
+ for (servo, gecko) in other.0.into_iter().zip(refptr.mQuotePairs.iter_mut()) {
+ gecko.first.assign_utf8(&nsCString::from(&*servo.0));
+ gecko.second.assign_utf8(&nsCString::from(&*servo.1));
+ }
+
+ unsafe { self.gecko.mQuotes.set_move(refptr.get()) }
+ }
+
+ pub fn copy_quotes_from(&mut self, other: &Self) {
+ unsafe { self.gecko.mQuotes.set(&other.gecko.mQuotes); }
+ }
+
</%self:impl_trait>
<%self:impl_trait style_struct_name="Effects"
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index 896b5fa09ba..378cd88bc45 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -922,7 +922,7 @@ ${helpers.single_keyword("-moz-appearance",
// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding
<%helpers:longhand name="-moz-binding" products="gecko" animatable="False" disable_when_testing="True">
use cssparser::{CssStringWriter, ToCss};
- use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
+ use gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
use std::fmt::{self, Write};
use url::Url;
use values::specified::UrlExtraData;
diff --git a/components/style/properties/longhand/list.mako.rs b/components/style/properties/longhand/list.mako.rs
index 62eed32f53b..77e0af5797a 100644
--- a/components/style/properties/longhand/list.mako.rs
+++ b/components/style/properties/longhand/list.mako.rs
@@ -104,7 +104,7 @@ ${helpers.single_keyword("list-style-type", """
}
</%helpers:longhand>
-<%helpers:longhand name="quotes" products="servo" animatable="False">
+<%helpers:longhand name="quotes" animatable="False">
use std::borrow::Cow;
use std::fmt;
use values::NoViewportPercentage;
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index f1694aa340d..f8a456d2076 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -6,7 +6,7 @@ use app_units::Au;
use cssparser::{self, Parser, ToCss, Token};
use euclid::size::Size2D;
#[cfg(feature = "gecko")]
-use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
+use gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
use parser::{Parse, ParserContext};
#[cfg(feature = "gecko")]
use parser::ParserContextExtraData;
diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs
index 9238cd1e7b9..124e75072cd 100644
--- a/ports/geckolib/glue.rs
+++ b/ports/geckolib/glue.rs
@@ -31,13 +31,13 @@ use style::gecko_bindings::bindings::{ServoDeclarationBlockBorrowed, ServoDeclar
use style::gecko_bindings::bindings::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
use style::gecko_bindings::bindings::{nsHTMLCSSStyleSheet, ServoComputedValuesBorrowedOrNull};
use style::gecko_bindings::bindings::Gecko_Utf8SliceToString;
-use style::gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom};
use style::gecko_bindings::structs::ServoElementSnapshot;
use style::gecko_bindings::structs::nsRestyleHint;
use style::gecko_bindings::structs::nsString;
use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasBoxFFI};
use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
+use style::gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
use style::parallel;
use style::parser::{ParserContext, ParserContextExtraData};
use style::properties::{ComputedValues, Importance, PropertyDeclaration};
@@ -186,11 +186,11 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(bytes: *const u8,
let base_str = unsafe { from_utf8_unchecked(slice::from_raw_parts(base_bytes, base_length as usize)) };
let url = Url::parse(base_str).unwrap();
- let extra_data = ParserContextExtraData {
+ let extra_data = unsafe { ParserContextExtraData {
base: Some(GeckoArcURI::new(base)),
referrer: Some(GeckoArcURI::new(referrer)),
principal: Some(GeckoArcPrincipal::new(principal)),
- };
+ }};
let sheet = Arc::new(Stylesheet::from_str(input, url, origin, Box::new(StdoutErrorReporter),
extra_data));
unsafe {
@@ -390,11 +390,11 @@ pub extern "C" fn Servo_ParseProperty(property_bytes: *const u8,
let base_str = unsafe { from_utf8_unchecked(slice::from_raw_parts(base_bytes,
base_length as usize)) };
let base_url = Url::parse(base_str).unwrap();
- let extra_data = ParserContextExtraData {
+ let extra_data = unsafe { ParserContextExtraData {
base: Some(GeckoArcURI::new(base)),
referrer: Some(GeckoArcURI::new(referrer)),
principal: Some(GeckoArcPrincipal::new(principal)),
- };
+ }};
let context = ParserContext::new_with_extra_data(Origin::Author, &base_url,
Box::new(StdoutErrorReporter),