diff --git a/ports/geckolib/binding_tools/regen.py b/ports/geckolib/binding_tools/regen.py index d48e76c89d8..72aeef2d5ef 100755 --- a/ports/geckolib/binding_tools/regen.py +++ b/ports/geckolib/binding_tools/regen.py @@ -148,7 +148,10 @@ COMPILATION_TARGETS = { "void_types": [ "nsINode", "nsIDocument", "nsIPrincipal", "nsIURI", ], - "servo_arc_types": ["ServoComputedValues", "RawServoStyleSheet"] + "servo_arc_types": [ + "ServoComputedValues", "RawServoStyleSheet", + "ServoDeclarationBlock" + ] }, "atoms": { diff --git a/ports/geckolib/gecko_bindings/bindings.rs b/ports/geckolib/gecko_bindings/bindings.rs index 82732911007..78b5d89f25c 100644 --- a/ports/geckolib/gecko_bindings/bindings.rs +++ b/ports/geckolib/gecko_bindings/bindings.rs @@ -9,6 +9,8 @@ pub type ServoComputedValuesStrong = ::sugar::refptr::Strong = ::sugar::refptr::Borrowed<'a, ServoComputedValues>; pub type RawServoStyleSheetStrong = ::sugar::refptr::Strong; pub type RawServoStyleSheetBorrowed<'a> = ::sugar::refptr::Borrowed<'a, RawServoStyleSheet>; +pub type ServoDeclarationBlockStrong = ::sugar::refptr::Strong; +pub type ServoDeclarationBlockBorrowed<'a> = ::sugar::refptr::Borrowed<'a, ServoDeclarationBlock>; use structs::nsStyleFont; unsafe impl Send for nsStyleFont {} unsafe impl Sync for nsStyleFont {} @@ -254,7 +256,7 @@ extern "C" { classList: *mut *mut *mut nsIAtom) -> u32; pub fn Gecko_GetServoDeclarationBlock(element: *mut RawGeckoElement) - -> *mut ServoDeclarationBlock; + -> ServoDeclarationBlockBorrowed; pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData; pub fn Gecko_SetNodeData(node: *mut RawGeckoNode, data: *mut ServoNodeData); @@ -467,16 +469,18 @@ extern "C" { pub fn Servo_DropStyleSet(set: *mut RawServoStyleSet); pub fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32, cache: *mut nsHTMLCSSStyleSheet) - -> *mut ServoDeclarationBlock; - pub fn Servo_DropDeclarationBlock(declarations: - *mut ServoDeclarationBlock); + -> ServoDeclarationBlockStrong; + pub fn Servo_DeclarationBlock_AddRef(declarations: + ServoDeclarationBlockBorrowed); + pub fn Servo_DeclarationBlock_Release(declarations: + ServoDeclarationBlockBorrowed); pub fn Servo_GetDeclarationBlockCache(declarations: - *mut ServoDeclarationBlock) + ServoDeclarationBlockBorrowed) -> *mut nsHTMLCSSStyleSheet; pub fn Servo_SetDeclarationBlockImmutable(declarations: - *mut ServoDeclarationBlock); + ServoDeclarationBlockBorrowed); pub fn Servo_ClearDeclarationBlockCachePointer(declarations: - *mut ServoDeclarationBlock); + ServoDeclarationBlockBorrowed); pub fn Servo_CSSSupports(name: *const u8, name_length: u32, value: *const u8, value_length: u32) -> bool; pub fn Servo_GetComputedValues(node: *mut RawGeckoNode) diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 9a8728db6fb..810998ff9fd 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -13,6 +13,7 @@ use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode}; use gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed}; use gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong}; use gecko_bindings::bindings::{ServoDeclarationBlock, ServoNodeData, ThreadSafePrincipalHolder}; +use gecko_bindings::bindings::{ServoDeclarationBlockBorrowed, ServoDeclarationBlockStrong}; use gecko_bindings::bindings::{ThreadSafeURIHolder, nsHTMLCSSStyleSheet}; use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI}; use gecko_bindings::structs::ServoElementSnapshot; @@ -25,6 +26,7 @@ use std::mem::transmute; use std::ptr; use std::slice; use std::str::from_utf8_unchecked; +use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; use std::sync::{Arc, Mutex}; use style::arc_ptr_eq; use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext}; @@ -355,47 +357,62 @@ pub extern "C" fn Servo_DropStyleSet(data: *mut RawServoStyleSet) -> () { pub struct GeckoDeclarationBlock { pub declarations: Option, - pub cache: *mut nsHTMLCSSStyleSheet, - pub immutable: bool, + // XXX The following two fields are made atomic to work around the + // ownership system so that they can be changed inside a shared + // instance. It wouldn't provide safety as Rust usually promises, + // but it is fine as far as we only access them in a single thread. + // If we need to access them in different threads, we would need + // to redesign how it works with MiscContainer in Gecko side. + pub cache: AtomicPtr, + pub immutable: AtomicBool, +} + +unsafe impl HasArcFFI for GeckoDeclarationBlock { + type FFIType = ServoDeclarationBlock; } #[no_mangle] pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32, cache: *mut nsHTMLCSSStyleSheet) - -> *mut ServoDeclarationBlock { + -> ServoDeclarationBlockStrong { let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) }; - let declarations = Box::new(GeckoDeclarationBlock { + GeckoDeclarationBlock::from_arc(Arc::new(GeckoDeclarationBlock { declarations: GeckoElement::parse_style_attribute(value), - cache: cache, - immutable: false, - }); - Box::into_raw(declarations) as *mut ServoDeclarationBlock + cache: AtomicPtr::new(cache), + immutable: AtomicBool::new(false), + })) } #[no_mangle] -pub extern "C" fn Servo_DropDeclarationBlock(declarations: *mut ServoDeclarationBlock) { - unsafe { - let _ = Box::::from_raw(declarations as *mut GeckoDeclarationBlock); - } +pub extern "C" fn Servo_DeclarationBlock_AddRef(declarations: ServoDeclarationBlockBorrowed) { + unsafe { GeckoDeclarationBlock::addref(declarations) }; } #[no_mangle] -pub extern "C" fn Servo_GetDeclarationBlockCache(declarations: *mut ServoDeclarationBlock) +pub extern "C" fn Servo_DeclarationBlock_Release(declarations: ServoDeclarationBlockBorrowed) { + unsafe { GeckoDeclarationBlock::release(declarations) }; +} + +#[no_mangle] +pub extern "C" fn Servo_GetDeclarationBlockCache(declarations: ServoDeclarationBlockBorrowed) -> *mut nsHTMLCSSStyleSheet { - let declarations = unsafe { (declarations as *const GeckoDeclarationBlock).as_ref().unwrap() }; - declarations.cache + GeckoDeclarationBlock::with(declarations, |declarations| { + declarations.cache.load(Ordering::Relaxed) + }) } #[no_mangle] -pub extern "C" fn Servo_SetDeclarationBlockImmutable(declarations: *mut ServoDeclarationBlock) { - let declarations = unsafe { (declarations as *mut GeckoDeclarationBlock).as_mut().unwrap() }; - declarations.immutable = true; +pub extern "C" fn Servo_SetDeclarationBlockImmutable(declarations: ServoDeclarationBlockBorrowed) { + GeckoDeclarationBlock::with(declarations, |declarations| { + declarations.immutable.store(true, Ordering::Relaxed) + }) } #[no_mangle] -pub extern "C" fn Servo_ClearDeclarationBlockCachePointer(declarations: *mut ServoDeclarationBlock) { - let declarations = unsafe { (declarations as *mut GeckoDeclarationBlock).as_mut().unwrap() }; - declarations.cache = ptr::null_mut(); +pub extern "C" fn Servo_ClearDeclarationBlockCachePointer(declarations: ServoDeclarationBlockBorrowed) { + GeckoDeclarationBlock::with(declarations, |declarations| { + declarations.cache.store(ptr::null_mut(), Ordering::Relaxed) + }); } #[no_mangle] diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs index 6e4f137cfdc..b5b57d27c88 100644 --- a/ports/geckolib/wrapper.rs +++ b/ports/geckolib/wrapper.rs @@ -35,6 +35,7 @@ use snapshot::GeckoElementSnapshot; use snapshot_helpers; use std::fmt; use std::marker::PhantomData; +use std::mem::transmute; use std::ops::BitOr; use std::ptr; use std::sync::Arc; @@ -432,9 +433,13 @@ impl<'le> TElement for GeckoElement<'le> { } fn style_attribute(&self) -> &Option { - unsafe { - let ptr = Gecko_GetServoDeclarationBlock(self.element) as *mut GeckoDeclarationBlock; - ptr.as_ref().map(|d| &d.declarations).unwrap_or(&NO_STYLE_ATTRIBUTE) + let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.element) }; + if declarations.is_null() { + &NO_STYLE_ATTRIBUTE + } else { + GeckoDeclarationBlock::with(declarations, |declarations| { + unsafe { transmute(&declarations.declarations) } + }) } }