Add sugar for already_AddRefed and use it for conversion between Atom and nsIAtom pointer.

This commit is contained in:
Xidorn Quan 2017-05-21 13:06:31 +10:00
parent 1602edb04a
commit 2b1f7f6081
6 changed files with 75 additions and 25 deletions

View file

@ -54,6 +54,7 @@ use gecko_bindings::structs::ELEMENT_HAS_SNAPSHOT;
use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
use gecko_bindings::structs::NODE_IS_NATIVE_ANONYMOUS;
use gecko_bindings::structs::already_AddRefed;
use gecko_bindings::sugar::ownership::HasArcFFI;
use logical_geometry::WritingMode;
use media_queries::Device;
@ -1074,13 +1075,13 @@ impl<'le> PresentationalHintsSynthesizer for GeckoElement<'le> {
//
// http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#language
let ptr = unsafe {
bindings::Gecko_GetXMLLangValue(self.0)
already_AddRefed::new(bindings::Gecko_GetXMLLangValue(self.0))
};
if !ptr.is_null() {
if let Some(ptr) = ptr {
let global_style_data = &*GLOBAL_STYLE_DATA;
let pdb = PropertyDeclarationBlock::with_one(
PropertyDeclaration::XLang(SpecifiedLang(unsafe { Atom::from_addrefed(ptr) })),
PropertyDeclaration::XLang(SpecifiedLang(ptr.into())),
Importance::Normal
);
let arc = Arc::new(global_style_data.shared_lock.wrap(pdb));

View file

@ -0,0 +1,48 @@
/* 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/. */
//! little helpers for `already_AddRefed`.
use gecko_bindings::structs::already_AddRefed;
use std::marker::PhantomData;
use std::mem;
impl<T> already_AddRefed<T> {
/// Create an already_AddRefed from an addrefed pointer.
#[inline]
pub unsafe fn new(ptr: *mut T) -> Option<Self> {
if !ptr.is_null() {
Some(Self::new_unchecked(ptr))
} else {
None
}
}
/// Create an already_AddRefed from an non-nullable addrefed pointer.
#[inline]
pub unsafe fn new_unchecked(ptr: *mut T) -> Self {
debug_assert!(!ptr.is_null());
already_AddRefed {
mRawPtr: ptr,
_phantom_0: PhantomData,
}
}
/// Take the addrefed pointer from this struct.
#[inline]
pub fn take(self) -> *mut T {
let ptr = self.mRawPtr;
mem::forget(self);
ptr
}
}
#[cfg(debug_assertions)]
impl<T> Drop for already_AddRefed<T> {
fn drop(&mut self) {
// We really should instead mark already_AddRefed must_use, but
// we cannot currently, which is servo/rust-bindgen#710.
unreachable!("Destructor shouldn't be called, otherwise we are leaking")
}
}

View file

@ -4,6 +4,7 @@
//! Rust sugar and convenience methods for Gecko types.
mod already_addrefed;
mod ns_com_ptr;
mod ns_compatibility;
mod ns_css_shadow_array;

View file

@ -152,7 +152,7 @@ impl nsCSSValue {
/// Set to an atom identifier value
pub fn set_atom_ident(&mut self, s: Atom) {
unsafe { bindings::Gecko_CSSValue_SetAtomIdent(self, s.into_addrefed()) }
unsafe { bindings::Gecko_CSSValue_SetAtomIdent(self, s.into()) }
}
/// Set to a font format

View file

@ -10,7 +10,7 @@ use gecko_bindings::bindings::Gecko_AddRefAtom;
use gecko_bindings::bindings::Gecko_Atomize;
use gecko_bindings::bindings::Gecko_Atomize16;
use gecko_bindings::bindings::Gecko_ReleaseAtom;
use gecko_bindings::structs::nsIAtom;
use gecko_bindings::structs::{already_AddRefed, nsIAtom};
use nsstring::nsAString;
use precomputed_hash::PrecomputedHash;
use std::ascii::AsciiExt;
@ -219,24 +219,6 @@ impl Atom {
atom
}
/// Creates an atom from a dynamic atom pointer that has already had AddRef
/// called on it.
#[inline]
pub unsafe fn from_addrefed(ptr: *mut nsIAtom) -> Self {
debug_assert!(!ptr.is_null());
unsafe {
Atom(WeakAtom::new(ptr))
}
}
/// Convert this atom into an addrefed nsIAtom pointer.
#[inline]
pub fn into_addrefed(self) -> *mut nsIAtom {
let ptr = self.as_ptr();
mem::forget(self);
ptr
}
/// Return whether two atoms are ASCII-case-insensitive matches
pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
let a = self.as_slice();
@ -358,3 +340,19 @@ impl From<*mut nsIAtom> for Atom {
}
}
}
impl From<already_AddRefed<nsIAtom>> for Atom {
#[inline]
fn from(ptr: already_AddRefed<nsIAtom>) -> Atom {
unsafe { Atom(WeakAtom::new(ptr.take())) }
}
}
impl From<Atom> for already_AddRefed<nsIAtom> {
#[inline]
fn from(atom: Atom) -> already_AddRefed<nsIAtom> {
let ptr = atom.as_ptr();
mem::forget(atom);
unsafe { already_AddRefed::new_unchecked(ptr) }
}
}

View file

@ -72,6 +72,7 @@ use style::gecko_bindings::structs::Loader;
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
use style::gecko_bindings::structs::ServoElementSnapshotTable;
use style::gecko_bindings::structs::URLExtraData;
use style::gecko_bindings::structs::already_AddRefed;
use style::gecko_bindings::structs::nsCSSValueSharedList;
use style::gecko_bindings::structs::nsCompatibility;
use style::gecko_bindings::structs::nsresult;
@ -1004,9 +1005,10 @@ pub extern "C" fn Servo_KeyframesRule_GetName(rule: RawServoKeyframesRuleBorrowe
}
#[no_mangle]
pub extern "C" fn Servo_KeyframesRule_SetName(rule: RawServoKeyframesRuleBorrowed, name: *mut nsIAtom) {
pub extern "C" fn Servo_KeyframesRule_SetName(rule: RawServoKeyframesRuleBorrowed,
name: already_AddRefed<nsIAtom>) {
write_locked_arc(rule, |rule: &mut KeyframesRule| {
rule.name = KeyframesName::Ident(CustomIdent(unsafe { Atom::from_addrefed(name) }));
rule.name = KeyframesName::Ident(CustomIdent(name.into()));
})
}