mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #12991 - Manishearth:more-arc-safety, r=mystor,emilio
Add sugar for handling borrowed and owned types Implements the changes outlined in https://github.com/servo/servo/pull/12826#discussion_r75074985 <s>Also gets things ready for the Unique/Borrowed bindings</s> WIP for borrowed and unique in the same PR. Still need to convert all the rest of the gecko types to use the new wrappers. r? @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/12991) <!-- Reviewable:end -->
This commit is contained in:
commit
927cd8ebf7
10 changed files with 805 additions and 449 deletions
|
@ -11,17 +11,19 @@
|
|||
use app_units::Au;
|
||||
use gecko_bindings::bindings::{RawServoStyleSheet, ServoComputedValues};
|
||||
use gecko_bindings::structs::nsStyleCoord_CalcValue;
|
||||
use gecko_bindings::sugar::refptr::HasArcFFI;
|
||||
use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI};
|
||||
use properties::ComputedValues;
|
||||
use stylesheets::Stylesheet;
|
||||
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage};
|
||||
|
||||
unsafe impl HasArcFFI for Stylesheet {
|
||||
unsafe impl HasFFI for Stylesheet {
|
||||
type FFIType = RawServoStyleSheet;
|
||||
}
|
||||
unsafe impl HasArcFFI for ComputedValues {
|
||||
unsafe impl HasArcFFI for Stylesheet {}
|
||||
unsafe impl HasFFI for ComputedValues {
|
||||
type FFIType = ServoComputedValues;
|
||||
}
|
||||
unsafe impl HasArcFFI for ComputedValues {}
|
||||
|
||||
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
|
||||
|
|
|
@ -24,10 +24,9 @@ use gecko_bindings::bindings::{Gecko_EnsureImageLayersLength, Gecko_CreateGradie
|
|||
use gecko_bindings::bindings::{Gecko_CopyImageValueFrom, Gecko_CopyFontFamilyFrom};
|
||||
use gecko_bindings::bindings::{Gecko_FontFamilyList_AppendGeneric, Gecko_FontFamilyList_AppendNamed};
|
||||
use gecko_bindings::bindings::{Gecko_FontFamilyList_Clear, Gecko_InitializeImageLayer};
|
||||
use gecko_bindings::bindings::ServoComputedValuesBorrowed;
|
||||
use gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
|
||||
use gecko_bindings::structs;
|
||||
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
|
||||
use gecko_bindings::sugar::refptr::HasArcFFI;
|
||||
use gecko_values::{StyleCoordHelpers, GeckoStyleCoordConvertible, convert_nscolor_to_rgba};
|
||||
use gecko_values::convert_rgba_to_nscolor;
|
||||
use gecko_values::round_border_to_device_pixels;
|
||||
|
@ -1744,10 +1743,10 @@ fn static_assert() {
|
|||
<%def name="define_ffi_struct_accessor(style_struct)">
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case, unused_variables)]
|
||||
pub extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values: ServoComputedValuesBorrowed)
|
||||
-> *const ${style_struct.gecko_ffi_name} {
|
||||
ComputedValues::with(computed_values, |values| values.get_${style_struct.name_lower}().get_gecko()
|
||||
as *const ${style_struct.gecko_ffi_name})
|
||||
pub extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values:
|
||||
ServoComputedValuesBorrowedOrNull) -> *const ${style_struct.gecko_ffi_name} {
|
||||
computed_values.as_arc::<ComputedValues>().get_${style_struct.name_lower}().get_gecko()
|
||||
as *const ${style_struct.gecko_ffi_name}
|
||||
}
|
||||
</%def>
|
||||
|
||||
|
|
|
@ -150,10 +150,20 @@ COMPILATION_TARGETS = {
|
|||
"void_types": [
|
||||
"nsINode", "nsIDocument", "nsIPrincipal", "nsIURI",
|
||||
],
|
||||
"servo_arc_types": [
|
||||
"servo_nullable_arc_types": [
|
||||
"ServoComputedValues", "RawServoStyleSheet",
|
||||
"ServoDeclarationBlock"
|
||||
]
|
||||
],
|
||||
"servo_owned_types": [
|
||||
"RawServoStyleSet",
|
||||
"ServoNodeData",
|
||||
"StyleChildrenIterator",
|
||||
],
|
||||
"servo_immutable_borrow_types": [
|
||||
"RawGeckoNode",
|
||||
"RawGeckoElement",
|
||||
"RawGeckoDocument",
|
||||
],
|
||||
},
|
||||
|
||||
"atoms": {
|
||||
|
@ -272,6 +282,22 @@ def build(objdir, target_name, debug, debugger, kind_name=None,
|
|||
|
||||
flags = []
|
||||
|
||||
# This makes an FFI-safe void type that can't be matched on
|
||||
# &VoidType is UB to have, because you can match on it
|
||||
# to produce a reachable unreachable. If it's wrapped in
|
||||
# a struct as a private field it becomes okay again
|
||||
#
|
||||
# Not 100% sure of how safe this is, but it's what we're using
|
||||
# in the XPCOM ffi too
|
||||
# https://github.com/nikomatsakis/rust-memory-model/issues/2
|
||||
def zero_size_type(ty, flags):
|
||||
flags.append("--blacklist-type")
|
||||
flags.append(ty)
|
||||
flags.append("--raw-line")
|
||||
flags.append("enum {0}Void{{ }}".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub struct {0}({0}Void);".format(ty))
|
||||
|
||||
if "flags" in current_target:
|
||||
flags.extend(current_target["flags"])
|
||||
|
||||
|
@ -315,16 +341,61 @@ def build(objdir, target_name, debug, debugger, kind_name=None,
|
|||
for ty in current_target["void_types"]:
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub enum {} {{}}".format(ty))
|
||||
if "servo_arc_types" in current_target:
|
||||
for ty in current_target["servo_arc_types"]:
|
||||
if "servo_nullable_arc_types" in current_target:
|
||||
for ty in current_target["servo_nullable_arc_types"]:
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}Strong".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}Strong = ::sugar::refptr::Strong<{0}>;".format(ty))
|
||||
flags.append("pub type {0}Strong = ::sugar::ownership::Strong<{0}>;".format(ty))
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}BorrowedOrNull".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}BorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, {0}>;".format(ty))
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}Borrowed".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}Borrowed<'a> = ::sugar::refptr::Borrowed<'a, {0}>;".format(ty))
|
||||
flags.append("pub type {0}Borrowed<'a> = &'a {0};".format(ty))
|
||||
zero_size_type(ty, flags)
|
||||
if "servo_immutable_borrow_types" in current_target:
|
||||
for ty in current_target["servo_immutable_borrow_types"]:
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}Borrowed".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}Borrowed<'a> = &'a {0};".format(ty))
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}BorrowedOrNull".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}BorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, {0}>;".format(ty))
|
||||
zero_size_type(ty, flags)
|
||||
if "servo_owned_types" in current_target:
|
||||
for ty in current_target["servo_owned_types"]:
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}Borrowed".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}Borrowed<'a> = &'a {0};".format(ty))
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}BorrowedMut".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}BorrowedMut<'a> = &'a mut {0};".format(ty))
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}Owned".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}Owned = ::sugar::ownership::Owned<{0}>;".format(ty))
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}BorrowedOrNull".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}BorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, {0}>;"
|
||||
.format(ty))
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}BorrowedMutOrNull".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}BorrowedMutOrNull<'a> = ::sugar::ownership::BorrowedMut<'a, {0}>;"
|
||||
.format(ty))
|
||||
flags.append("--blacklist-type")
|
||||
flags.append("{}OwnedOrNull".format(ty))
|
||||
flags.append("--raw-line")
|
||||
flags.append("pub type {0}OwnedOrNull = ::sugar::ownership::OwnedOrNull<{0}>;".format(ty))
|
||||
zero_size_type(ty, flags)
|
||||
if "structs_types" in current_target:
|
||||
for ty in current_target["structs_types"]:
|
||||
ty_fragments = ty.split("::")
|
||||
|
@ -354,7 +425,7 @@ def build(objdir, target_name, debug, debugger, kind_name=None,
|
|||
|
||||
# TODO: support more files, that's the whole point of this.
|
||||
assert len(current_target["files"]) == 1
|
||||
clang_flags.append(current_target["files"][0].format(objdir))
|
||||
flags.append(current_target["files"][0].format(objdir))
|
||||
|
||||
flags = bindgen + flags + ["--"] + clang_flags
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use euclid::size::TypedSize2D;
|
||||
use gecko_bindings::bindings::RawServoStyleSet;
|
||||
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||
use num_cpus;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
|
@ -77,10 +78,6 @@ impl PerDocumentStyleData {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn borrow_mut_from_raw<'a>(data: *mut RawServoStyleSet) -> &'a mut Self {
|
||||
unsafe { &mut *(data as *mut PerDocumentStyleData) }
|
||||
}
|
||||
|
||||
pub fn flush_stylesheets(&mut self) {
|
||||
// The stylist wants to be flushed if either the stylesheets change or the
|
||||
// device dimensions change. When we add support for media queries, we'll
|
||||
|
@ -93,6 +90,12 @@ impl PerDocumentStyleData {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl HasFFI for PerDocumentStyleData {
|
||||
type FFIType = RawServoStyleSet;
|
||||
}
|
||||
unsafe impl HasSimpleFFI for PerDocumentStyleData {}
|
||||
unsafe impl HasBoxFFI for PerDocumentStyleData {}
|
||||
|
||||
impl Drop for PerDocumentStyleData {
|
||||
fn drop(&mut self) {
|
||||
if let Some(ref mut queue) = self.work_queue {
|
||||
|
|
|
@ -5,12 +5,57 @@ pub enum nsINode {}
|
|||
pub enum nsIDocument {}
|
||||
pub enum nsIPrincipal {}
|
||||
pub enum nsIURI {}
|
||||
pub type ServoComputedValuesStrong = ::sugar::refptr::Strong<ServoComputedValues>;
|
||||
pub type ServoComputedValuesBorrowed<'a> = ::sugar::refptr::Borrowed<'a, ServoComputedValues>;
|
||||
pub type RawServoStyleSheetStrong = ::sugar::refptr::Strong<RawServoStyleSheet>;
|
||||
pub type RawServoStyleSheetBorrowed<'a> = ::sugar::refptr::Borrowed<'a, RawServoStyleSheet>;
|
||||
pub type ServoDeclarationBlockStrong = ::sugar::refptr::Strong<ServoDeclarationBlock>;
|
||||
pub type ServoDeclarationBlockBorrowed<'a> = ::sugar::refptr::Borrowed<'a, ServoDeclarationBlock>;
|
||||
pub type ServoComputedValuesStrong = ::sugar::ownership::Strong<ServoComputedValues>;
|
||||
pub type ServoComputedValuesBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, ServoComputedValues>;
|
||||
pub type ServoComputedValuesBorrowed<'a> = &'a ServoComputedValues;
|
||||
enum ServoComputedValuesVoid{ }
|
||||
pub struct ServoComputedValues(ServoComputedValuesVoid);
|
||||
pub type RawServoStyleSheetStrong = ::sugar::ownership::Strong<RawServoStyleSheet>;
|
||||
pub type RawServoStyleSheetBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, RawServoStyleSheet>;
|
||||
pub type RawServoStyleSheetBorrowed<'a> = &'a RawServoStyleSheet;
|
||||
enum RawServoStyleSheetVoid{ }
|
||||
pub struct RawServoStyleSheet(RawServoStyleSheetVoid);
|
||||
pub type ServoDeclarationBlockStrong = ::sugar::ownership::Strong<ServoDeclarationBlock>;
|
||||
pub type ServoDeclarationBlockBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, ServoDeclarationBlock>;
|
||||
pub type ServoDeclarationBlockBorrowed<'a> = &'a ServoDeclarationBlock;
|
||||
enum ServoDeclarationBlockVoid{ }
|
||||
pub struct ServoDeclarationBlock(ServoDeclarationBlockVoid);
|
||||
pub type RawGeckoNodeBorrowed<'a> = &'a RawGeckoNode;
|
||||
pub type RawGeckoNodeBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, RawGeckoNode>;
|
||||
enum RawGeckoNodeVoid{ }
|
||||
pub struct RawGeckoNode(RawGeckoNodeVoid);
|
||||
pub type RawGeckoElementBorrowed<'a> = &'a RawGeckoElement;
|
||||
pub type RawGeckoElementBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, RawGeckoElement>;
|
||||
enum RawGeckoElementVoid{ }
|
||||
pub struct RawGeckoElement(RawGeckoElementVoid);
|
||||
pub type RawGeckoDocumentBorrowed<'a> = &'a RawGeckoDocument;
|
||||
pub type RawGeckoDocumentBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, RawGeckoDocument>;
|
||||
enum RawGeckoDocumentVoid{ }
|
||||
pub struct RawGeckoDocument(RawGeckoDocumentVoid);
|
||||
pub type RawServoStyleSetBorrowed<'a> = &'a RawServoStyleSet;
|
||||
pub type RawServoStyleSetBorrowedMut<'a> = &'a mut RawServoStyleSet;
|
||||
pub type RawServoStyleSetOwned = ::sugar::ownership::Owned<RawServoStyleSet>;
|
||||
pub type RawServoStyleSetBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, RawServoStyleSet>;
|
||||
pub type RawServoStyleSetBorrowedMutOrNull<'a> = ::sugar::ownership::BorrowedMut<'a, RawServoStyleSet>;
|
||||
pub type RawServoStyleSetOwnedOrNull = ::sugar::ownership::OwnedOrNull<RawServoStyleSet>;
|
||||
enum RawServoStyleSetVoid{ }
|
||||
pub struct RawServoStyleSet(RawServoStyleSetVoid);
|
||||
pub type ServoNodeDataBorrowed<'a> = &'a ServoNodeData;
|
||||
pub type ServoNodeDataBorrowedMut<'a> = &'a mut ServoNodeData;
|
||||
pub type ServoNodeDataOwned = ::sugar::ownership::Owned<ServoNodeData>;
|
||||
pub type ServoNodeDataBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, ServoNodeData>;
|
||||
pub type ServoNodeDataBorrowedMutOrNull<'a> = ::sugar::ownership::BorrowedMut<'a, ServoNodeData>;
|
||||
pub type ServoNodeDataOwnedOrNull = ::sugar::ownership::OwnedOrNull<ServoNodeData>;
|
||||
enum ServoNodeDataVoid{ }
|
||||
pub struct ServoNodeData(ServoNodeDataVoid);
|
||||
pub type StyleChildrenIteratorBorrowed<'a> = &'a StyleChildrenIterator;
|
||||
pub type StyleChildrenIteratorBorrowedMut<'a> = &'a mut StyleChildrenIterator;
|
||||
pub type StyleChildrenIteratorOwned = ::sugar::ownership::Owned<StyleChildrenIterator>;
|
||||
pub type StyleChildrenIteratorBorrowedOrNull<'a> = ::sugar::ownership::Borrowed<'a, StyleChildrenIterator>;
|
||||
pub type StyleChildrenIteratorBorrowedMutOrNull<'a> = ::sugar::ownership::BorrowedMut<'a, StyleChildrenIterator>;
|
||||
pub type StyleChildrenIteratorOwnedOrNull = ::sugar::ownership::OwnedOrNull<StyleChildrenIterator>;
|
||||
enum StyleChildrenIteratorVoid{ }
|
||||
pub struct StyleChildrenIterator(StyleChildrenIteratorVoid);
|
||||
use structs::nsStyleFont;
|
||||
unsafe impl Send for nsStyleFont {}
|
||||
unsafe impl Sync for nsStyleFont {}
|
||||
|
@ -159,77 +204,75 @@ use structs::StyleBasicShapeType;
|
|||
use structs::StyleBasicShape;
|
||||
use structs::nsCSSShadowArray;
|
||||
|
||||
pub type RawGeckoNode = nsINode;
|
||||
pub enum Element { }
|
||||
pub type RawGeckoElement = Element;
|
||||
pub type RawGeckoDocument = nsIDocument;
|
||||
pub enum ServoNodeData { }
|
||||
pub enum ServoComputedValues { }
|
||||
pub enum RawServoStyleSheet { }
|
||||
pub enum RawServoStyleSet { }
|
||||
pub enum nsHTMLCSSStyleSheet { }
|
||||
pub enum ServoDeclarationBlock { }
|
||||
pub enum StyleChildrenIterator { }
|
||||
pub type ThreadSafePrincipalHolder = nsMainThreadPtrHolder<nsIPrincipal>;
|
||||
pub type ThreadSafeURIHolder = nsMainThreadPtrHolder<nsIURI>;
|
||||
extern "C" {
|
||||
pub fn Gecko_ChildrenCount(node: *mut RawGeckoNode) -> u32;
|
||||
pub fn Gecko_NodeIsElement(node: *mut RawGeckoNode) -> bool;
|
||||
pub fn Gecko_GetParentNode(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetFirstChild(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetLastChild(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetPrevSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetNextSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetParentElement(element: *mut RawGeckoElement)
|
||||
-> *mut RawGeckoElement;
|
||||
pub fn Gecko_GetFirstChildElement(element: *mut RawGeckoElement)
|
||||
-> *mut RawGeckoElement;
|
||||
pub fn Gecko_GetLastChildElement(element: *mut RawGeckoElement)
|
||||
-> *mut RawGeckoElement;
|
||||
pub fn Gecko_GetPrevSiblingElement(element: *mut RawGeckoElement)
|
||||
-> *mut RawGeckoElement;
|
||||
pub fn Gecko_GetNextSiblingElement(element: *mut RawGeckoElement)
|
||||
-> *mut RawGeckoElement;
|
||||
pub fn Gecko_GetDocumentElement(document: *mut RawGeckoDocument)
|
||||
-> *mut RawGeckoElement;
|
||||
pub fn Gecko_MaybeCreateStyleChildrenIterator(node: *mut RawGeckoNode)
|
||||
-> *mut StyleChildrenIterator;
|
||||
pub fn Gecko_DropStyleChildrenIterator(it: *mut StyleChildrenIterator);
|
||||
pub fn Gecko_GetNextStyleChild(it: *mut StyleChildrenIterator)
|
||||
-> *mut RawGeckoNode;
|
||||
pub fn Gecko_ElementState(element: *mut RawGeckoElement) -> u8;
|
||||
pub fn Gecko_IsHTMLElementInHTMLDocument(element: *mut RawGeckoElement)
|
||||
pub fn Gecko_ChildrenCount(node: RawGeckoNodeBorrowed) -> u32;
|
||||
pub fn Gecko_NodeIsElement(node: RawGeckoNodeBorrowed) -> bool;
|
||||
pub fn Gecko_GetParentNode(node: RawGeckoNodeBorrowed)
|
||||
-> RawGeckoNodeBorrowedOrNull;
|
||||
pub fn Gecko_GetFirstChild(node: RawGeckoNodeBorrowed)
|
||||
-> RawGeckoNodeBorrowedOrNull;
|
||||
pub fn Gecko_GetLastChild(node: RawGeckoNodeBorrowed)
|
||||
-> RawGeckoNodeBorrowedOrNull;
|
||||
pub fn Gecko_GetPrevSibling(node: RawGeckoNodeBorrowed)
|
||||
-> RawGeckoNodeBorrowedOrNull;
|
||||
pub fn Gecko_GetNextSibling(node: RawGeckoNodeBorrowed)
|
||||
-> RawGeckoNodeBorrowedOrNull;
|
||||
pub fn Gecko_GetParentElement(element: RawGeckoElementBorrowed)
|
||||
-> RawGeckoElementBorrowedOrNull;
|
||||
pub fn Gecko_GetFirstChildElement(element: RawGeckoElementBorrowed)
|
||||
-> RawGeckoElementBorrowedOrNull;
|
||||
pub fn Gecko_GetLastChildElement(element: RawGeckoElementBorrowed)
|
||||
-> RawGeckoElementBorrowedOrNull;
|
||||
pub fn Gecko_GetPrevSiblingElement(element: RawGeckoElementBorrowed)
|
||||
-> RawGeckoElementBorrowedOrNull;
|
||||
pub fn Gecko_GetNextSiblingElement(element: RawGeckoElementBorrowed)
|
||||
-> RawGeckoElementBorrowedOrNull;
|
||||
pub fn Gecko_GetDocumentElement(document: RawGeckoDocumentBorrowed)
|
||||
-> RawGeckoElementBorrowedOrNull;
|
||||
pub fn Gecko_MaybeCreateStyleChildrenIterator(node: RawGeckoNodeBorrowed)
|
||||
-> StyleChildrenIteratorOwnedOrNull;
|
||||
pub fn Gecko_DropStyleChildrenIterator(it: StyleChildrenIteratorOwned);
|
||||
pub fn Gecko_GetNextStyleChild(it: StyleChildrenIteratorBorrowed)
|
||||
-> RawGeckoNodeBorrowedOrNull;
|
||||
pub fn Gecko_ElementState(element: RawGeckoElementBorrowed) -> u8;
|
||||
pub fn Gecko_IsHTMLElementInHTMLDocument(element: RawGeckoElementBorrowed)
|
||||
-> bool;
|
||||
pub fn Gecko_IsLink(element: *mut RawGeckoElement) -> bool;
|
||||
pub fn Gecko_IsTextNode(node: *mut RawGeckoNode) -> bool;
|
||||
pub fn Gecko_IsVisitedLink(element: *mut RawGeckoElement) -> bool;
|
||||
pub fn Gecko_IsUnvisitedLink(element: *mut RawGeckoElement) -> bool;
|
||||
pub fn Gecko_IsRootElement(element: *mut RawGeckoElement) -> bool;
|
||||
pub fn Gecko_LocalName(element: *mut RawGeckoElement) -> *mut nsIAtom;
|
||||
pub fn Gecko_Namespace(element: *mut RawGeckoElement) -> *mut nsIAtom;
|
||||
pub fn Gecko_GetElementId(element: *mut RawGeckoElement) -> *mut nsIAtom;
|
||||
pub fn Gecko_AtomAttrValue(element: *mut RawGeckoElement,
|
||||
pub fn Gecko_IsLink(element: RawGeckoElementBorrowed) -> bool;
|
||||
pub fn Gecko_IsTextNode(node: RawGeckoNodeBorrowed) -> bool;
|
||||
pub fn Gecko_IsVisitedLink(element: RawGeckoElementBorrowed) -> bool;
|
||||
pub fn Gecko_IsUnvisitedLink(element: RawGeckoElementBorrowed) -> bool;
|
||||
pub fn Gecko_IsRootElement(element: RawGeckoElementBorrowed) -> bool;
|
||||
pub fn Gecko_LocalName(element: RawGeckoElementBorrowed) -> *mut nsIAtom;
|
||||
pub fn Gecko_Namespace(element: RawGeckoElementBorrowed) -> *mut nsIAtom;
|
||||
pub fn Gecko_GetElementId(element: RawGeckoElementBorrowed)
|
||||
-> *mut nsIAtom;
|
||||
pub fn Gecko_AtomAttrValue(element: RawGeckoElementBorrowed,
|
||||
attribute: *mut nsIAtom) -> *mut nsIAtom;
|
||||
pub fn Gecko_HasAttr(element: *mut RawGeckoElement, ns: *mut nsIAtom,
|
||||
pub fn Gecko_HasAttr(element: RawGeckoElementBorrowed, ns: *mut nsIAtom,
|
||||
name: *mut nsIAtom) -> bool;
|
||||
pub fn Gecko_AttrEquals(element: *mut RawGeckoElement, ns: *mut nsIAtom,
|
||||
name: *mut nsIAtom, str: *mut nsIAtom,
|
||||
ignoreCase: bool) -> bool;
|
||||
pub fn Gecko_AttrDashEquals(element: *mut RawGeckoElement,
|
||||
pub fn Gecko_AttrEquals(element: RawGeckoElementBorrowed,
|
||||
ns: *mut nsIAtom, name: *mut nsIAtom,
|
||||
str: *mut nsIAtom, ignoreCase: bool) -> bool;
|
||||
pub fn Gecko_AttrDashEquals(element: RawGeckoElementBorrowed,
|
||||
ns: *mut nsIAtom, name: *mut nsIAtom,
|
||||
str: *mut nsIAtom) -> bool;
|
||||
pub fn Gecko_AttrIncludes(element: *mut RawGeckoElement, ns: *mut nsIAtom,
|
||||
name: *mut nsIAtom, str: *mut nsIAtom) -> bool;
|
||||
pub fn Gecko_AttrHasSubstring(element: *mut RawGeckoElement,
|
||||
pub fn Gecko_AttrIncludes(element: RawGeckoElementBorrowed,
|
||||
ns: *mut nsIAtom, name: *mut nsIAtom,
|
||||
str: *mut nsIAtom) -> bool;
|
||||
pub fn Gecko_AttrHasSubstring(element: RawGeckoElementBorrowed,
|
||||
ns: *mut nsIAtom, name: *mut nsIAtom,
|
||||
str: *mut nsIAtom) -> bool;
|
||||
pub fn Gecko_AttrHasPrefix(element: *mut RawGeckoElement,
|
||||
pub fn Gecko_AttrHasPrefix(element: RawGeckoElementBorrowed,
|
||||
ns: *mut nsIAtom, name: *mut nsIAtom,
|
||||
str: *mut nsIAtom) -> bool;
|
||||
pub fn Gecko_AttrHasSuffix(element: *mut RawGeckoElement,
|
||||
pub fn Gecko_AttrHasSuffix(element: RawGeckoElementBorrowed,
|
||||
ns: *mut nsIAtom, name: *mut nsIAtom,
|
||||
str: *mut nsIAtom) -> bool;
|
||||
pub fn Gecko_ClassOrClassList(element: *mut RawGeckoElement,
|
||||
pub fn Gecko_ClassOrClassList(element: RawGeckoElementBorrowed,
|
||||
class_: *mut *mut nsIAtom,
|
||||
classList: *mut *mut *mut nsIAtom) -> u32;
|
||||
pub fn Gecko_SnapshotAtomAttrValue(element: *mut ServoElementSnapshot,
|
||||
|
@ -262,11 +305,12 @@ extern "C" {
|
|||
class_: *mut *mut nsIAtom,
|
||||
classList: *mut *mut *mut nsIAtom)
|
||||
-> u32;
|
||||
pub fn Gecko_GetServoDeclarationBlock(element: *mut RawGeckoElement)
|
||||
-> ServoDeclarationBlockBorrowed;
|
||||
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
|
||||
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
|
||||
data: *mut ServoNodeData);
|
||||
pub fn Gecko_GetServoDeclarationBlock(element: RawGeckoElementBorrowed)
|
||||
-> ServoDeclarationBlockBorrowedOrNull;
|
||||
pub fn Gecko_GetNodeData(node: RawGeckoNodeBorrowed)
|
||||
-> ServoNodeDataBorrowedOrNull;
|
||||
pub fn Gecko_SetNodeData(node: RawGeckoNodeBorrowed,
|
||||
data: ServoNodeDataOwned);
|
||||
pub fn Gecko_Atomize(aString: *const ::std::os::raw::c_char, aLength: u32)
|
||||
-> *mut nsIAtom;
|
||||
pub fn Gecko_AddRefAtom(aAtom: *mut nsIAtom);
|
||||
|
@ -310,16 +354,16 @@ extern "C" {
|
|||
principal: *mut ThreadSafePrincipalHolder);
|
||||
pub fn Gecko_CopyMozBindingFrom(des: *mut nsStyleDisplay,
|
||||
src: *const nsStyleDisplay);
|
||||
pub fn Gecko_GetNodeFlags(node: *mut RawGeckoNode) -> u32;
|
||||
pub fn Gecko_SetNodeFlags(node: *mut RawGeckoNode, flags: u32);
|
||||
pub fn Gecko_UnsetNodeFlags(node: *mut RawGeckoNode, flags: u32);
|
||||
pub fn Gecko_GetStyleContext(node: *mut RawGeckoNode,
|
||||
pub fn Gecko_GetNodeFlags(node: RawGeckoNodeBorrowed) -> u32;
|
||||
pub fn Gecko_SetNodeFlags(node: RawGeckoNodeBorrowed, flags: u32);
|
||||
pub fn Gecko_UnsetNodeFlags(node: RawGeckoNodeBorrowed, flags: u32);
|
||||
pub fn Gecko_GetStyleContext(node: RawGeckoNodeBorrowed,
|
||||
aPseudoTagOrNull: *mut nsIAtom)
|
||||
-> *mut nsStyleContext;
|
||||
pub fn Gecko_CalcStyleDifference(oldstyle: *mut nsStyleContext,
|
||||
newstyle: ServoComputedValuesBorrowed)
|
||||
-> nsChangeHint;
|
||||
pub fn Gecko_StoreStyleDifference(node: *mut RawGeckoNode,
|
||||
pub fn Gecko_StoreStyleDifference(node: RawGeckoNodeBorrowed,
|
||||
change: nsChangeHint);
|
||||
pub fn Gecko_EnsureTArrayCapacity(array: *mut ::std::os::raw::c_void,
|
||||
capacity: usize, elem_size: usize);
|
||||
|
@ -456,7 +500,7 @@ extern "C" {
|
|||
pub fn Gecko_CopyConstruct_nsStyleEffects(ptr: *mut nsStyleEffects,
|
||||
other: *const nsStyleEffects);
|
||||
pub fn Gecko_Destroy_nsStyleEffects(ptr: *mut nsStyleEffects);
|
||||
pub fn Servo_NodeData_Drop(data: *mut ServoNodeData);
|
||||
pub fn Servo_NodeData_Drop(data: ServoNodeDataOwned);
|
||||
pub fn Servo_StyleSheet_FromUTF8Bytes(bytes: *const u8, length: u32,
|
||||
parsing_mode: SheetParsingMode,
|
||||
base_bytes: *const u8,
|
||||
|
@ -470,16 +514,17 @@ extern "C" {
|
|||
pub fn Servo_StyleSheet_Release(sheet: RawServoStyleSheetBorrowed);
|
||||
pub fn Servo_StyleSheet_HasRules(sheet: RawServoStyleSheetBorrowed)
|
||||
-> bool;
|
||||
pub fn Servo_StyleSet_Init() -> *mut RawServoStyleSet;
|
||||
pub fn Servo_StyleSet_Drop(set: *mut RawServoStyleSet);
|
||||
pub fn Servo_StyleSet_AppendStyleSheet(set: *mut RawServoStyleSet,
|
||||
pub fn Servo_StyleSet_Init() -> RawServoStyleSetOwned;
|
||||
pub fn Servo_StyleSet_Drop(set: RawServoStyleSetOwned);
|
||||
pub fn Servo_StyleSet_AppendStyleSheet(set: RawServoStyleSetBorrowedMut,
|
||||
sheet: RawServoStyleSheetBorrowed);
|
||||
pub fn Servo_StyleSet_PrependStyleSheet(set: *mut RawServoStyleSet,
|
||||
pub fn Servo_StyleSet_PrependStyleSheet(set: RawServoStyleSetBorrowedMut,
|
||||
sheet:
|
||||
RawServoStyleSheetBorrowed);
|
||||
pub fn Servo_StyleSet_RemoveStyleSheet(set: *mut RawServoStyleSet,
|
||||
pub fn Servo_StyleSet_RemoveStyleSheet(set: RawServoStyleSetBorrowedMut,
|
||||
sheet: RawServoStyleSheetBorrowed);
|
||||
pub fn Servo_StyleSet_InsertStyleSheetBefore(set: *mut RawServoStyleSet,
|
||||
pub fn Servo_StyleSet_InsertStyleSheetBefore(set:
|
||||
RawServoStyleSetBorrowedMut,
|
||||
sheet:
|
||||
RawServoStyleSheetBorrowed,
|
||||
reference:
|
||||
|
@ -500,24 +545,25 @@ extern "C" {
|
|||
ServoDeclarationBlockBorrowed);
|
||||
pub fn Servo_CSSSupports(name: *const u8, name_length: u32,
|
||||
value: *const u8, value_length: u32) -> bool;
|
||||
pub fn Servo_ComputedValues_Get(node: *mut RawGeckoNode)
|
||||
pub fn Servo_ComputedValues_Get(node: RawGeckoNodeBorrowed)
|
||||
-> ServoComputedValuesStrong;
|
||||
pub fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
|
||||
ServoComputedValuesBorrowed,
|
||||
ServoComputedValuesBorrowedOrNull,
|
||||
pseudoTag: *mut nsIAtom,
|
||||
set: *mut RawServoStyleSet)
|
||||
set:
|
||||
RawServoStyleSetBorrowedMut)
|
||||
-> ServoComputedValuesStrong;
|
||||
pub fn Servo_ComputedValues_GetForPseudoElement(parent_style:
|
||||
ServoComputedValuesBorrowed,
|
||||
match_element:
|
||||
*mut RawGeckoElement,
|
||||
RawGeckoElementBorrowed,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
set:
|
||||
*mut RawServoStyleSet,
|
||||
RawServoStyleSetBorrowedMut,
|
||||
is_probe: bool)
|
||||
-> ServoComputedValuesStrong;
|
||||
pub fn Servo_ComputedValues_Inherit(parent_style:
|
||||
ServoComputedValuesBorrowed)
|
||||
ServoComputedValuesBorrowedOrNull)
|
||||
-> ServoComputedValuesStrong;
|
||||
pub fn Servo_ComputedValues_AddRef(computed_values:
|
||||
ServoComputedValuesBorrowed);
|
||||
|
@ -527,12 +573,12 @@ extern "C" {
|
|||
pub fn Servo_Shutdown();
|
||||
pub fn Servo_ComputeRestyleHint(element: *mut RawGeckoElement,
|
||||
snapshot: *mut ServoElementSnapshot,
|
||||
set: *mut RawServoStyleSet)
|
||||
set: RawServoStyleSetBorrowed)
|
||||
-> nsRestyleHint;
|
||||
pub fn Servo_RestyleDocument(doc: *mut RawGeckoDocument,
|
||||
set: *mut RawServoStyleSet);
|
||||
pub fn Servo_RestyleSubtree(node: *mut RawGeckoNode,
|
||||
set: *mut RawServoStyleSet);
|
||||
pub fn Servo_RestyleDocument(doc: RawGeckoDocumentBorrowed,
|
||||
set: RawServoStyleSetBorrowedMut);
|
||||
pub fn Servo_RestyleSubtree(node: RawGeckoNodeBorrowed,
|
||||
set: RawServoStyleSetBorrowedMut);
|
||||
pub fn Servo_GetStyleFont(computed_values: ServoComputedValuesBorrowed)
|
||||
-> *const nsStyleFont;
|
||||
pub fn Servo_GetStyleColor(computed_values: ServoComputedValuesBorrowed)
|
||||
|
|
|
@ -6,4 +6,4 @@ mod ns_css_shadow_array;
|
|||
mod ns_style_auto_array;
|
||||
pub mod ns_style_coord;
|
||||
mod ns_t_array;
|
||||
pub mod refptr;
|
||||
pub mod ownership;
|
||||
|
|
397
ports/geckolib/gecko_bindings/sugar/ownership.rs
Normal file
397
ports/geckolib/gecko_bindings/sugar/ownership.rs
Normal file
|
@ -0,0 +1,397 @@
|
|||
/* 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 std::marker::PhantomData;
|
||||
use std::mem::{forget, transmute};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Indicates that a given Servo type has a corresponding
|
||||
/// Gecko FFI type
|
||||
/// The correspondence is not defined at this stage,
|
||||
/// use HasArcFFI or similar traits to define it
|
||||
pub unsafe trait HasFFI : Sized {
|
||||
type FFIType: Sized;
|
||||
}
|
||||
|
||||
/// Indicates that a given Servo type has the same layout
|
||||
/// as the corresponding HasFFI::FFIType type
|
||||
pub unsafe trait HasSimpleFFI : HasFFI {
|
||||
#[inline]
|
||||
/// Given a Servo-side reference, converts it to an
|
||||
/// FFI-safe reference which can be passed to Gecko
|
||||
///
|
||||
/// &ServoType -> &GeckoType
|
||||
fn as_ffi(&self) -> &Self::FFIType {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
#[inline]
|
||||
/// Given a Servo-side mutable reference, converts it to an
|
||||
/// FFI-safe mutable reference which can be passed to Gecko
|
||||
///
|
||||
/// &mut ServoType -> &mut GeckoType
|
||||
fn as_ffi_mut(&mut self) -> &mut Self::FFIType {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
#[inline]
|
||||
/// Given an FFI-safe reference obtained from Gecko
|
||||
/// converts it to a Servo-side reference
|
||||
///
|
||||
/// &GeckoType -> &ServoType
|
||||
fn from_ffi(ffi: &Self::FFIType) -> &Self {
|
||||
unsafe { transmute(ffi) }
|
||||
}
|
||||
#[inline]
|
||||
/// Given an FFI-safe mutable reference obtained from Gecko
|
||||
/// converts it to a Servo-side mutable reference
|
||||
///
|
||||
/// &mut GeckoType -> &mut ServoType
|
||||
fn from_ffi_mut(ffi: &mut Self::FFIType) -> &mut Self {
|
||||
unsafe { transmute(ffi) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates that the given Servo type is passed over FFI
|
||||
/// as a Box
|
||||
pub unsafe trait HasBoxFFI : HasSimpleFFI {
|
||||
#[inline]
|
||||
fn into_ffi(self: Box<Self>) -> Owned<Self::FFIType> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait for conversions between FFI Strong/Borrowed types and Arcs
|
||||
///
|
||||
/// Should be implemented by types which are passed over FFI as Arcs
|
||||
/// via Strong and Borrowed
|
||||
///
|
||||
/// In this case, the FFIType is the rough equivalent of ArcInner<Self>
|
||||
pub unsafe trait HasArcFFI : HasFFI {
|
||||
// these methods can't be on Borrowed because it leads to an unspecified
|
||||
// impl parameter
|
||||
/// Artificially increments the refcount of a (possibly null) borrowed Arc over FFI.
|
||||
unsafe fn addref_opt(ptr: Borrowed<Self::FFIType>) {
|
||||
forget(ptr.as_arc_opt::<Self>().clone())
|
||||
}
|
||||
|
||||
/// Given a (possibly null) borrowed FFI reference, decrements the refcount.
|
||||
/// Unsafe since it doesn't consume the backing Arc. Run it only when you
|
||||
/// know that a strong reference to the backing Arc is disappearing
|
||||
/// (usually on the C++ side) without running the Arc destructor.
|
||||
unsafe fn release_opt(ptr: Borrowed<Self::FFIType>) {
|
||||
if let Some(arc) = ptr.as_arc_opt::<Self>() {
|
||||
let _: Arc<_> = ptr::read(arc as *const Arc<_>);
|
||||
}
|
||||
}
|
||||
|
||||
/// Artificially increments the refcount of a borrowed Arc over FFI.
|
||||
unsafe fn addref(ptr: &Self::FFIType) {
|
||||
forget(Self::as_arc(&ptr).clone())
|
||||
}
|
||||
|
||||
/// Given a non-null borrowed FFI reference, decrements the refcount.
|
||||
/// Unsafe since it doesn't consume the backing Arc. Run it only when you
|
||||
/// know that a strong reference to the backing Arc is disappearing
|
||||
/// (usually on the C++ side) without running the Arc destructor.
|
||||
unsafe fn release(ptr: &Self::FFIType) {
|
||||
let _: Arc<_> = ptr::read(Self::as_arc(&ptr) as *const Arc<_>);
|
||||
}
|
||||
#[inline]
|
||||
/// Converts a borrowed FFI reference to a borrowed Arc.
|
||||
///
|
||||
/// &GeckoType -> &Arc<ServoType>
|
||||
fn as_arc<'a>(ptr: &'a &Self::FFIType) -> &'a Arc<Self> {
|
||||
debug_assert!(!(ptr as *const _).is_null());
|
||||
unsafe {
|
||||
transmute::<&&Self::FFIType, &Arc<Self>>(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe borrowed type
|
||||
/// This can be null.
|
||||
pub struct Borrowed<'a, T: 'a> {
|
||||
ptr: *const T,
|
||||
_marker: PhantomData<&'a T>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe mutably borrowed type
|
||||
/// This can be null.
|
||||
pub struct BorrowedMut<'a, T: 'a> {
|
||||
ptr: *mut T,
|
||||
_marker: PhantomData<&'a mut T>,
|
||||
}
|
||||
|
||||
// manual impls because derive doesn't realize that `T: Clone` isn't necessary
|
||||
impl<'a, T> Copy for Borrowed<'a, T> {}
|
||||
|
||||
impl<'a, T> Clone for Borrowed<'a, T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
impl<'a, T> Borrowed<'a, T> {
|
||||
#[inline]
|
||||
pub fn is_null(self) -> bool {
|
||||
self.ptr == ptr::null()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Like Deref, but gives an Option
|
||||
pub fn borrow_opt(self) -> Option<&'a T> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { &*self.ptr })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Borrowed<GeckoType> -> Option<&Arc<ServoType>>
|
||||
pub fn as_arc_opt<U>(&self) -> Option<&Arc<U>> where U: HasArcFFI<FFIType = T> {
|
||||
unsafe {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(transmute::<&Borrowed<_>, &Arc<_>>(self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Converts a borrowed FFI reference to a borrowed Arc.
|
||||
/// Panics on null.
|
||||
///
|
||||
/// &Borrowed<GeckoType> -> &Arc<ServoType>
|
||||
pub fn as_arc<U>(&self) -> &Arc<U> where U: HasArcFFI<FFIType = T> {
|
||||
self.as_arc_opt().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Borrowed<ServoType> -> Borrowed<GeckoType>
|
||||
pub fn as_ffi(self) -> Borrowed<'a, <Self as HasFFI>::FFIType> where Self: HasSimpleFFI {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Borrowed<GeckoType> -> Borrowed<ServoType>
|
||||
pub fn from_ffi<U>(self) -> Borrowed<'a, U> where U: HasSimpleFFI<FFIType = T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Borrowed<GeckoType> -> &ServoType
|
||||
pub fn as_servo_ref<U>(self) -> Option<&'a U> where U: HasSimpleFFI<FFIType = T> {
|
||||
self.borrow_opt().map(HasSimpleFFI::from_ffi)
|
||||
}
|
||||
|
||||
pub fn null() -> Borrowed<'static, T> {
|
||||
Borrowed {
|
||||
ptr: ptr::null_mut(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> BorrowedMut<'a, T> {
|
||||
#[inline]
|
||||
/// Like DerefMut, but gives an Option
|
||||
pub fn borrow_mut_opt(self) -> Option<&'a mut T> {
|
||||
// We have two choices for the signature here, it can either be
|
||||
// Self -> Option<&'a mut T> or
|
||||
// &'b mut Self -> Option<'b mut T>
|
||||
// The former consumes the BorrowedMut (which isn't Copy),
|
||||
// which can be annoying. The latter only temporarily
|
||||
// borrows it, so the return value can't exit the scope
|
||||
// even if Self has a longer lifetime ('a)
|
||||
//
|
||||
// This is basically the implicit "reborrow" pattern used with &mut
|
||||
// not cleanly translating to our custom types.
|
||||
|
||||
// I've chosen the former solution -- you can manually convert back
|
||||
// if you need to reuse the BorrowedMut.
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { &mut *self.ptr })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// BorrowedMut<GeckoType> -> &mut ServoType
|
||||
pub fn as_servo_mut_ref<U>(self) -> Option<&'a mut U> where U: HasSimpleFFI<FFIType = T> {
|
||||
self.borrow_mut_opt().map(HasSimpleFFI::from_ffi_mut)
|
||||
}
|
||||
|
||||
pub fn null_mut() -> BorrowedMut<'static, T> {
|
||||
BorrowedMut {
|
||||
ptr: ptr::null_mut(),
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// technically not how we're supposed to use
|
||||
// Deref, but that's a minor style issue
|
||||
impl<'a, T> Deref for BorrowedMut<'a, T> {
|
||||
type Target = Borrowed<'a, T>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe Arc (T is an ArcInner).
|
||||
/// This can be null.
|
||||
/// Leaks on drop. Please don't drop this.
|
||||
/// TODO: Add destructor bomb once drop flags are gone
|
||||
pub struct Strong<T> {
|
||||
ptr: *const T,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Strong<T> {
|
||||
#[inline]
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ptr == ptr::null()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Given a non-null strong FFI reference,
|
||||
/// converts it into a servo-side Arc
|
||||
/// Panics on null.
|
||||
///
|
||||
/// Strong<GeckoType> -> Arc<ServoType>
|
||||
pub fn into_arc<U>(self) -> Arc<U> where U: HasArcFFI<FFIType = T> {
|
||||
self.into_arc_opt().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Given a strong FFI reference,
|
||||
/// converts it into a servo-side Arc
|
||||
/// Returns None on null.
|
||||
///
|
||||
/// Strong<GeckoType> -> Arc<ServoType>
|
||||
pub fn into_arc_opt<U>(self) -> Option<Arc<U>> where U: HasArcFFI<FFIType = T> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(transmute(self)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Produces a null strong FFI reference
|
||||
pub fn null() -> Self {
|
||||
unsafe { transmute(ptr::null::<T>()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe trait FFIArcHelpers {
|
||||
type Inner: HasArcFFI;
|
||||
/// Converts an Arc into a strong FFI reference.
|
||||
///
|
||||
/// Arc<ServoType> -> Strong<GeckoType>
|
||||
fn into_strong(self) -> Strong<<Self::Inner as HasFFI>::FFIType>;
|
||||
/// Produces a (nullable) borrowed FFI reference by borrowing an Arc.
|
||||
///
|
||||
/// &Arc<ServoType> -> Borrowed<GeckoType>
|
||||
fn as_borrowed_opt(&self) -> Borrowed<<Self::Inner as HasFFI>::FFIType>;
|
||||
/// Produces a borrowed FFI reference by borrowing an Arc.
|
||||
///
|
||||
/// &Arc<ServoType> -> &GeckoType
|
||||
fn as_borrowed(&self) -> &<Self::Inner as HasFFI>::FFIType;
|
||||
}
|
||||
|
||||
unsafe impl<T: HasArcFFI> FFIArcHelpers for Arc<T> {
|
||||
type Inner = T;
|
||||
#[inline]
|
||||
fn into_strong(self) -> Strong<T::FFIType> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
#[inline]
|
||||
fn as_borrowed_opt(&self) -> Borrowed<T::FFIType> {
|
||||
let borrowedptr = self as *const Arc<T> as *const Borrowed<T::FFIType>;
|
||||
unsafe { ptr::read(borrowedptr) }
|
||||
}
|
||||
#[inline]
|
||||
fn as_borrowed(&self) -> &T::FFIType {
|
||||
let borrowedptr = self as *const Arc<T> as *const & T::FFIType;
|
||||
unsafe { ptr::read(borrowedptr) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe owned pointer
|
||||
/// Cannot be null
|
||||
/// Leaks on drop. Please don't drop this.
|
||||
pub struct Owned<T> {
|
||||
ptr: *mut T,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Owned<T> {
|
||||
/// Owned<GeckoType> -> Box<ServoType>
|
||||
pub fn into_box<U>(self) -> Box<T> where U: HasBoxFFI<FFIType = T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
pub fn maybe(self) -> OwnedOrNull<T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Owned<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for Owned<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.ptr }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe owned pointer
|
||||
/// Can be null
|
||||
pub struct OwnedOrNull<T> {
|
||||
ptr: *mut T,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> OwnedOrNull<T> {
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ptr == ptr::null_mut()
|
||||
}
|
||||
/// OwnedOrNull<GeckoType> -> Option<Box<ServoType>>
|
||||
pub fn into_box_opt<U>(self) -> Option<Box<T>> where U: HasBoxFFI<FFIType = T> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { transmute(self) })
|
||||
}
|
||||
}
|
||||
|
||||
/// OwnedOrNull<GeckoType> -> Option<Owned<GeckoType>>
|
||||
pub fn into_owned_opt(self) -> Option<Owned<T>> {
|
||||
if self.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { transmute(self) })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow(&self) -> Borrowed<T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
|
||||
pub fn borrow_mut(&self) -> BorrowedMut<T> {
|
||||
unsafe { transmute(self) }
|
||||
}
|
||||
}
|
|
@ -1,117 +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 std::marker::PhantomData;
|
||||
use std::mem::{forget, transmute};
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Helper trait for conversions between FFI Strong/Borrowed types and Arcs
|
||||
///
|
||||
/// Should be implemented by types which are passed over FFI as Arcs
|
||||
/// via Strong and Borrowed
|
||||
pub unsafe trait HasArcFFI where Self: Sized {
|
||||
/// Gecko's name for the type
|
||||
/// This is equivalent to ArcInner<Self>
|
||||
type FFIType: Sized;
|
||||
|
||||
/// Given a non-null borrowed FFI reference, this produces a temporary
|
||||
/// Arc which is borrowed by the given closure and used.
|
||||
/// Panics on null.
|
||||
fn with<F, Output>(raw: Borrowed<Self::FFIType>, cb: F) -> Output
|
||||
where F: FnOnce(&Arc<Self>) -> Output {
|
||||
Self::maybe_with(raw, |opt| cb(opt.unwrap()))
|
||||
}
|
||||
|
||||
/// Given a maybe-null borrowed FFI reference, this produces a temporary
|
||||
/// Option<Arc> (None if null) which is borrowed by the given closure and used
|
||||
fn maybe_with<F, Output>(maybe_raw: Borrowed<Self::FFIType>, cb: F) -> Output
|
||||
where F: FnOnce(Option<&Arc<Self>>) -> Output {
|
||||
cb(Self::borrowed_as(&maybe_raw))
|
||||
}
|
||||
|
||||
/// Given a non-null strong FFI reference, converts it into an Arc.
|
||||
/// Panics on null.
|
||||
fn into(ptr: Strong<Self::FFIType>) -> Arc<Self> {
|
||||
assert!(!ptr.is_null());
|
||||
unsafe { transmute(ptr) }
|
||||
}
|
||||
|
||||
fn borrowed_as<'a>(ptr: &'a Borrowed<'a, Self::FFIType>) -> Option<&'a Arc<Self>> {
|
||||
unsafe {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(transmute::<&Borrowed<_>, &Arc<_>>(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an Arc into a strong FFI reference.
|
||||
fn from_arc(owned: Arc<Self>) -> Strong<Self::FFIType> {
|
||||
unsafe { transmute(owned) }
|
||||
}
|
||||
|
||||
/// Artificially increments the refcount of a borrowed Arc over FFI.
|
||||
unsafe fn addref(ptr: Borrowed<Self::FFIType>) {
|
||||
Self::with(ptr, |arc| forget(arc.clone()));
|
||||
}
|
||||
|
||||
/// Given a (possibly null) borrowed FFI reference, decrements the refcount.
|
||||
/// Unsafe since it doesn't consume the backing Arc. Run it only when you
|
||||
/// know that a strong reference to the backing Arc is disappearing
|
||||
/// (usually on the C++ side) without running the Arc destructor.
|
||||
unsafe fn release(ptr: Borrowed<Self::FFIType>) {
|
||||
if let Some(arc) = Self::borrowed_as(&ptr) {
|
||||
let _: Arc<_> = ptr::read(arc as *const Arc<_>);
|
||||
}
|
||||
}
|
||||
|
||||
/// Produces a borrowed FFI reference by borrowing an Arc.
|
||||
fn to_borrowed<'a>(arc: &'a Arc<Self>)
|
||||
-> Borrowed<'a, Self::FFIType> {
|
||||
let borrowedptr = arc as *const Arc<Self> as *const Borrowed<'a, Self::FFIType>;
|
||||
unsafe { ptr::read(borrowedptr) }
|
||||
}
|
||||
|
||||
/// Produces a null strong FFI reference
|
||||
fn null_strong() -> Strong<Self::FFIType> {
|
||||
unsafe { transmute(ptr::null::<Self::FFIType>()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe borrowed Arc (&T where T is an ArcInner).
|
||||
/// This can be null.
|
||||
pub struct Borrowed<'a, T: 'a> {
|
||||
ptr: *const T,
|
||||
_marker: PhantomData<&'a T>,
|
||||
}
|
||||
|
||||
// manual impls because derive doesn't realize that `T: Clone` isn't necessary
|
||||
impl<'a, T> Copy for Borrowed<'a, T> {}
|
||||
|
||||
impl<'a, T> Clone for Borrowed<'a, T> {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
impl<'a, T> Borrowed<'a, T> {
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ptr == ptr::null()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Gecko-FFI-safe Arc (T is an ArcInner).
|
||||
/// This can be null.
|
||||
pub struct Strong<T> {
|
||||
ptr: *const T,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Strong<T> {
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ptr == ptr::null()
|
||||
}
|
||||
}
|
|
@ -8,18 +8,22 @@ use app_units::Au;
|
|||
use data::{NUM_THREADS, PerDocumentStyleData};
|
||||
use env_logger;
|
||||
use euclid::Size2D;
|
||||
use gecko_bindings::bindings::RawServoStyleSet;
|
||||
use gecko_bindings::bindings::RawGeckoDocumentBorrowed;
|
||||
use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
|
||||
use gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoNodeBorrowed};
|
||||
use gecko_bindings::bindings::{RawServoStyleSet, RawServoStyleSetBorrowedMut};
|
||||
use gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned, ServoNodeDataOwned};
|
||||
use gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
|
||||
use gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
|
||||
use gecko_bindings::bindings::{ServoDeclarationBlock, ServoNodeData, ThreadSafePrincipalHolder};
|
||||
use gecko_bindings::bindings::{ServoComputedValuesBorrowedOrNull, ServoDeclarationBlock};
|
||||
use gecko_bindings::bindings::{ServoDeclarationBlockBorrowed, ServoDeclarationBlockStrong};
|
||||
use gecko_bindings::bindings::{ThreadSafeURIHolder, nsHTMLCSSStyleSheet};
|
||||
use gecko_bindings::bindings::{ThreadSafePrincipalHolder, ThreadSafeURIHolder, nsHTMLCSSStyleSheet};
|
||||
use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
|
||||
use gecko_bindings::structs::ServoElementSnapshot;
|
||||
use gecko_bindings::structs::nsRestyleHint;
|
||||
use gecko_bindings::structs::{SheetParsingMode, nsIAtom};
|
||||
use gecko_bindings::sugar::refptr::HasArcFFI;
|
||||
use gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasBoxFFI};
|
||||
use gecko_bindings::sugar::ownership::{HasSimpleFFI, HasFFI, Strong};
|
||||
use gecko_string_cache::Atom;
|
||||
use snapshot::GeckoElementSnapshot;
|
||||
use std::mem::transmute;
|
||||
|
@ -69,7 +73,7 @@ pub extern "C" fn Servo_Shutdown() -> () {
|
|||
unsafe { ComputedValues::shutdown(); }
|
||||
}
|
||||
|
||||
fn restyle_subtree(node: GeckoNode, raw_data: *mut RawServoStyleSet) {
|
||||
fn restyle_subtree(node: GeckoNode, raw_data: RawServoStyleSetBorrowedMut) {
|
||||
debug_assert!(node.is_element() || node.is_text_node());
|
||||
|
||||
// Force the creation of our lazily-constructed initial computed values on
|
||||
|
@ -82,7 +86,7 @@ fn restyle_subtree(node: GeckoNode, raw_data: *mut RawServoStyleSet) {
|
|||
ComputedValues::initial_values();
|
||||
|
||||
// The stylist consumes stylesheets lazily.
|
||||
let per_doc_data = unsafe { &mut *(raw_data as *mut PerDocumentStyleData) };
|
||||
let per_doc_data = PerDocumentStyleData::from_ffi_mut(raw_data);
|
||||
per_doc_data.flush_stylesheets();
|
||||
|
||||
let local_context_data =
|
||||
|
@ -112,15 +116,15 @@ fn restyle_subtree(node: GeckoNode, raw_data: *mut RawServoStyleSet) {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_RestyleSubtree(node: *mut RawGeckoNode,
|
||||
raw_data: *mut RawServoStyleSet) -> () {
|
||||
let node = unsafe { GeckoNode::from_raw(node) };
|
||||
pub extern "C" fn Servo_RestyleSubtree(node: RawGeckoNodeBorrowed,
|
||||
raw_data: RawServoStyleSetBorrowedMut) -> () {
|
||||
let node = GeckoNode(node);
|
||||
restyle_subtree(node, raw_data);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_RestyleDocument(doc: *mut RawGeckoDocument, raw_data: *mut RawServoStyleSet) -> () {
|
||||
let document = unsafe { GeckoDocument::from_raw(doc) };
|
||||
pub extern "C" fn Servo_RestyleDocument(doc: RawGeckoDocumentBorrowed, raw_data: RawServoStyleSetBorrowedMut) -> () {
|
||||
let document = GeckoDocument(doc);
|
||||
let node = match document.root_node() {
|
||||
Some(x) => x,
|
||||
None => return,
|
||||
|
@ -134,10 +138,8 @@ pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_NodeData_Drop(data: *mut ServoNodeData) -> () {
|
||||
unsafe {
|
||||
let _ = Box::<NonOpaqueStyleData>::from_raw(data as *mut NonOpaqueStyleData);
|
||||
}
|
||||
pub extern "C" fn Servo_NodeData_Drop(data: ServoNodeDataOwned) -> () {
|
||||
let _ = data.into_box::<NonOpaqueStyleData>();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -173,55 +175,50 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(bytes: *const u8,
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: *mut RawServoStyleSet,
|
||||
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: RawServoStyleSetBorrowedMut,
|
||||
raw_sheet: RawServoStyleSheetBorrowed) {
|
||||
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||
Stylesheet::with(raw_sheet, |sheet| {
|
||||
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||
data.stylesheets.push(sheet.clone());
|
||||
data.stylesheets_changed = true;
|
||||
});
|
||||
let data = PerDocumentStyleData::from_ffi_mut(raw_data);
|
||||
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
||||
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||
data.stylesheets.push(sheet.clone());
|
||||
data.stylesheets_changed = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: *mut RawServoStyleSet,
|
||||
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: RawServoStyleSetBorrowedMut,
|
||||
raw_sheet: RawServoStyleSheetBorrowed) {
|
||||
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||
Stylesheet::with(raw_sheet, |sheet| {
|
||||
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||
data.stylesheets.insert(0, sheet.clone());
|
||||
data.stylesheets_changed = true;
|
||||
})
|
||||
let data = PerDocumentStyleData::from_ffi_mut(raw_data);
|
||||
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
||||
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||
data.stylesheets.insert(0, sheet.clone());
|
||||
data.stylesheets_changed = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: *mut RawServoStyleSet,
|
||||
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: RawServoStyleSetBorrowedMut,
|
||||
raw_sheet: RawServoStyleSheetBorrowed,
|
||||
raw_reference: RawServoStyleSheetBorrowed) {
|
||||
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||
Stylesheet::with(raw_sheet, |sheet| {
|
||||
Stylesheet::with(raw_reference, |reference| {
|
||||
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||
let index = data.stylesheets.iter().position(|x| arc_ptr_eq(x, reference)).unwrap();
|
||||
data.stylesheets.insert(index, sheet.clone());
|
||||
data.stylesheets_changed = true;
|
||||
})
|
||||
})
|
||||
let data = PerDocumentStyleData::from_ffi_mut(raw_data);
|
||||
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
||||
let reference = HasArcFFI::as_arc(&raw_reference);
|
||||
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||
let index = data.stylesheets.iter().position(|x| arc_ptr_eq(x, reference)).unwrap();
|
||||
data.stylesheets.insert(index, sheet.clone());
|
||||
data.stylesheets_changed = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(raw_data: *mut RawServoStyleSet,
|
||||
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(raw_data: RawServoStyleSetBorrowedMut,
|
||||
raw_sheet: RawServoStyleSheetBorrowed) {
|
||||
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||
Stylesheet::with(raw_sheet, |sheet| {
|
||||
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||
data.stylesheets_changed = true;
|
||||
});
|
||||
let data = PerDocumentStyleData::from_ffi_mut(raw_data);
|
||||
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
||||
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||
data.stylesheets_changed = true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSheet_HasRules(raw_sheet: RawServoStyleSheetBorrowed) -> bool {
|
||||
Stylesheet::with(raw_sheet, |sheet| !sheet.rules.is_empty())
|
||||
!Stylesheet::as_arc(&raw_sheet).rules.is_empty()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -235,9 +232,9 @@ pub extern "C" fn Servo_StyleSheet_Release(sheet: RawServoStyleSheetBorrowed) ->
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ComputedValues_Get(node: *mut RawGeckoNode)
|
||||
pub extern "C" fn Servo_ComputedValues_Get(node: RawGeckoNodeBorrowed)
|
||||
-> ServoComputedValuesStrong {
|
||||
let node = unsafe { GeckoNode::from_raw(node) };
|
||||
let node = unsafe { GeckoNode(node) };
|
||||
let arc_cv = match node.borrow_data().map_or(None, |data| data.style.clone()) {
|
||||
Some(style) => style,
|
||||
None => {
|
||||
|
@ -249,42 +246,41 @@ pub extern "C" fn Servo_ComputedValues_Get(node: *mut RawGeckoNode)
|
|||
Arc::new(ComputedValues::initial_values().clone())
|
||||
},
|
||||
};
|
||||
ComputedValues::from_arc(arc_cv)
|
||||
arc_cv.into_strong()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoComputedValuesBorrowed,
|
||||
pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoComputedValuesBorrowedOrNull,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
raw_data: *mut RawServoStyleSet)
|
||||
raw_data: RawServoStyleSetBorrowedMut)
|
||||
-> ServoComputedValuesStrong {
|
||||
// The stylist consumes stylesheets lazily.
|
||||
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||
let data = PerDocumentStyleData::from_ffi_mut(raw_data);
|
||||
data.flush_stylesheets();
|
||||
|
||||
let atom = Atom::from(pseudo_tag);
|
||||
let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
|
||||
|
||||
|
||||
ComputedValues::maybe_with(parent_style_or_null, |maybe_parent| {
|
||||
let new_computed = data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent);
|
||||
new_computed.map_or(ComputedValues::null_strong(), |c| ComputedValues::from_arc(c))
|
||||
})
|
||||
let maybe_parent = parent_style_or_null.as_arc_opt();
|
||||
let new_computed = data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent);
|
||||
new_computed.map_or(Strong::null(), |c| c.into_strong())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ComputedValues_GetForPseudoElement(parent_style: ServoComputedValuesBorrowed,
|
||||
match_element: *mut RawGeckoElement,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
raw_data: *mut RawServoStyleSet,
|
||||
is_probe: bool)
|
||||
match_element: RawGeckoElementBorrowed,
|
||||
pseudo_tag: *mut nsIAtom,
|
||||
raw_data: RawServoStyleSetBorrowedMut,
|
||||
is_probe: bool)
|
||||
-> ServoComputedValuesStrong {
|
||||
debug_assert!(!match_element.is_null());
|
||||
debug_assert!(!(match_element as *const _).is_null());
|
||||
|
||||
let parent_or_null = || {
|
||||
if is_probe {
|
||||
ComputedValues::null_strong()
|
||||
Strong::null()
|
||||
} else {
|
||||
ComputedValues::from_arc(ComputedValues::with(parent_style, |parent| parent.clone()))
|
||||
ComputedValues::as_arc(&parent_style).clone().into_strong()
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -292,10 +288,10 @@ pub extern "C" fn Servo_ComputedValues_GetForPseudoElement(parent_style: ServoCo
|
|||
let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ false);
|
||||
|
||||
// The stylist consumes stylesheets lazily.
|
||||
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||
let data = PerDocumentStyleData::from_ffi_mut(raw_data);
|
||||
data.flush_stylesheets();
|
||||
|
||||
let element = unsafe { GeckoElement::from_raw(match_element) };
|
||||
let element = unsafe { GeckoElement(match_element) };
|
||||
|
||||
|
||||
match GeckoSelectorImpl::pseudo_element_cascade_type(&pseudo) {
|
||||
|
@ -305,14 +301,13 @@ pub extern "C" fn Servo_ComputedValues_GetForPseudoElement(parent_style: ServoCo
|
|||
.and_then(|data| {
|
||||
data.per_pseudo.get(&pseudo).map(|c| c.clone())
|
||||
});
|
||||
maybe_computed.map_or_else(parent_or_null, ComputedValues::from_arc)
|
||||
maybe_computed.map_or_else(parent_or_null, FFIArcHelpers::into_strong)
|
||||
}
|
||||
PseudoElementCascadeType::Lazy => {
|
||||
ComputedValues::with(parent_style, |parent| {
|
||||
data.stylist
|
||||
.lazily_compute_pseudo_element_style(&element, &pseudo, parent)
|
||||
.map_or_else(parent_or_null, ComputedValues::from_arc)
|
||||
})
|
||||
let parent = ComputedValues::as_arc(&parent_style);
|
||||
data.stylist
|
||||
.lazily_compute_pseudo_element_style(&element, &pseudo, parent)
|
||||
.map_or_else(parent_or_null, FFIArcHelpers::into_strong)
|
||||
}
|
||||
PseudoElementCascadeType::Precomputed => {
|
||||
unreachable!("Anonymous pseudo found in \
|
||||
|
@ -322,14 +317,14 @@ pub extern "C" fn Servo_ComputedValues_GetForPseudoElement(parent_style: ServoCo
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ComputedValues_Inherit(parent_style: ServoComputedValuesBorrowed)
|
||||
pub extern "C" fn Servo_ComputedValues_Inherit(parent_style: ServoComputedValuesBorrowedOrNull)
|
||||
-> ServoComputedValuesStrong {
|
||||
let style = if parent_style.is_null() {
|
||||
Arc::new(ComputedValues::initial_values().clone())
|
||||
} else {
|
||||
ComputedValues::with(parent_style, ComputedValues::inherit_from)
|
||||
ComputedValues::inherit_from(parent_style.as_arc())
|
||||
};
|
||||
ComputedValues::from_arc(style)
|
||||
style.into_strong()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -343,16 +338,14 @@ pub extern "C" fn Servo_ComputedValues_Release(ptr: ServoComputedValuesBorrowed)
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_Init() -> *mut RawServoStyleSet {
|
||||
pub extern "C" fn Servo_StyleSet_Init() -> RawServoStyleSetOwned {
|
||||
let data = Box::new(PerDocumentStyleData::new());
|
||||
Box::into_raw(data) as *mut RawServoStyleSet
|
||||
data.into_ffi()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_Drop(data: *mut RawServoStyleSet) -> () {
|
||||
unsafe {
|
||||
let _ = Box::<PerDocumentStyleData>::from_raw(data as *mut PerDocumentStyleData);
|
||||
}
|
||||
pub extern "C" fn Servo_StyleSet_Drop(data: RawServoStyleSetOwned) -> () {
|
||||
let _ = data.into_box::<PerDocumentStyleData>();
|
||||
}
|
||||
|
||||
pub struct GeckoDeclarationBlock {
|
||||
|
@ -367,20 +360,21 @@ pub struct GeckoDeclarationBlock {
|
|||
pub immutable: AtomicBool,
|
||||
}
|
||||
|
||||
unsafe impl HasArcFFI for GeckoDeclarationBlock {
|
||||
unsafe impl HasFFI for GeckoDeclarationBlock {
|
||||
type FFIType = ServoDeclarationBlock;
|
||||
}
|
||||
unsafe impl HasArcFFI for GeckoDeclarationBlock {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
|
||||
cache: *mut nsHTMLCSSStyleSheet)
|
||||
-> ServoDeclarationBlockStrong {
|
||||
let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
|
||||
GeckoDeclarationBlock::from_arc(Arc::new(GeckoDeclarationBlock {
|
||||
Arc::new(GeckoDeclarationBlock {
|
||||
declarations: GeckoElement::parse_style_attribute(value).map(Arc::new),
|
||||
cache: AtomicPtr::new(cache),
|
||||
immutable: AtomicBool::new(false),
|
||||
}))
|
||||
}).into_strong()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -396,23 +390,17 @@ pub extern "C" fn Servo_DeclarationBlock_Release(declarations: ServoDeclarationB
|
|||
#[no_mangle]
|
||||
pub extern "C" fn Servo_DeclarationBlock_GetCache(declarations: ServoDeclarationBlockBorrowed)
|
||||
-> *mut nsHTMLCSSStyleSheet {
|
||||
GeckoDeclarationBlock::with(declarations, |declarations| {
|
||||
declarations.cache.load(Ordering::Relaxed)
|
||||
})
|
||||
GeckoDeclarationBlock::as_arc(&declarations).cache.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_DeclarationBlock_SetImmutable(declarations: ServoDeclarationBlockBorrowed) {
|
||||
GeckoDeclarationBlock::with(declarations, |declarations| {
|
||||
declarations.immutable.store(true, Ordering::Relaxed)
|
||||
})
|
||||
GeckoDeclarationBlock::as_arc(&declarations).immutable.store(true, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_DeclarationBlock_ClearCachePointer(declarations: ServoDeclarationBlockBorrowed) {
|
||||
GeckoDeclarationBlock::with(declarations, |declarations| {
|
||||
declarations.cache.store(ptr::null_mut(), Ordering::Relaxed)
|
||||
});
|
||||
GeckoDeclarationBlock::as_arc(&declarations).cache.store(ptr::null_mut(), Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -431,12 +419,12 @@ pub extern "C" fn Servo_CSSSupports(property: *const u8, property_length: u32,
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ComputeRestyleHint(element: *mut RawGeckoElement,
|
||||
pub extern "C" fn Servo_ComputeRestyleHint(element: RawGeckoElementBorrowed,
|
||||
snapshot: *mut ServoElementSnapshot,
|
||||
raw_data: *mut RawServoStyleSet) -> nsRestyleHint {
|
||||
let per_doc_data = unsafe { &mut *(raw_data as *mut PerDocumentStyleData) };
|
||||
raw_data: RawServoStyleSetBorrowed) -> nsRestyleHint {
|
||||
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
||||
let snapshot = unsafe { GeckoElementSnapshot::from_raw(snapshot) };
|
||||
let element = unsafe { GeckoElement::from_raw(element) };
|
||||
let element = unsafe { GeckoElement(element) };
|
||||
|
||||
// NB: This involves an FFI call, we can get rid of it easily if needed.
|
||||
let current_state = element.get_state();
|
||||
|
|
|
@ -23,9 +23,11 @@ use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement, Gecko_IsTextNo
|
|||
use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
|
||||
use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
|
||||
use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
|
||||
use gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoNodeBorrowed};
|
||||
use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
|
||||
use gecko_bindings::structs::{nsIAtom, nsChangeHint, nsStyleContext};
|
||||
use gecko_bindings::sugar::refptr::HasArcFFI;
|
||||
use gecko_bindings::sugar::ownership::Borrowed;
|
||||
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI, FFIArcHelpers};
|
||||
use gecko_string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||
use glue::GeckoDeclarationBlock;
|
||||
use libc::uintptr_t;
|
||||
|
@ -53,8 +55,19 @@ use style::selector_matching::DeclarationBlock;
|
|||
use style::sink::Push;
|
||||
use url::Url;
|
||||
|
||||
pub type NonOpaqueStyleData = RefCell<PrivateStyleData>;
|
||||
pub type NonOpaqueStyleDataPtr = *mut NonOpaqueStyleData;
|
||||
pub struct NonOpaqueStyleData(RefCell<PrivateStyleData>);
|
||||
|
||||
unsafe impl HasFFI for NonOpaqueStyleData {
|
||||
type FFIType = ServoNodeData;
|
||||
}
|
||||
unsafe impl HasSimpleFFI for NonOpaqueStyleData {}
|
||||
unsafe impl HasBoxFFI for NonOpaqueStyleData {}
|
||||
|
||||
impl NonOpaqueStyleData {
|
||||
pub fn new() -> Self {
|
||||
NonOpaqueStyleData(RefCell::new(PrivateStyleData::new()))
|
||||
}
|
||||
}
|
||||
|
||||
// Important: We don't currently refcount the DOM, because the wrapper lifetime
|
||||
// magic guarantees that our LayoutFoo references won't outlive the root, and
|
||||
|
@ -62,34 +75,20 @@ pub type NonOpaqueStyleDataPtr = *mut NonOpaqueStyleData;
|
|||
// could implement refcounting if need be (at a potentially non-trivial
|
||||
// performance cost) by implementing Drop and making LayoutFoo non-Copy.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GeckoNode<'ln> {
|
||||
node: *mut RawGeckoNode,
|
||||
chain: PhantomData<&'ln ()>,
|
||||
}
|
||||
pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
|
||||
|
||||
impl<'ln> GeckoNode<'ln> {
|
||||
pub unsafe fn from_raw(n: *mut RawGeckoNode) -> GeckoNode<'ln> {
|
||||
GeckoNode {
|
||||
node: n,
|
||||
chain: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn from_ref(n: &RawGeckoNode) -> GeckoNode<'ln> {
|
||||
GeckoNode::from_raw(n as *const RawGeckoNode as *mut RawGeckoNode)
|
||||
}
|
||||
|
||||
fn get_node_data(&self) -> NonOpaqueStyleDataPtr {
|
||||
unsafe {
|
||||
Gecko_GetNodeData(self.node) as NonOpaqueStyleDataPtr
|
||||
}
|
||||
fn get_node_data(&self) -> Borrowed<NonOpaqueStyleData> {
|
||||
unsafe {
|
||||
Borrowed::from_ffi(Gecko_GetNodeData(&*self.0))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize_data(self) {
|
||||
unsafe {
|
||||
if self.get_node_data().is_null() {
|
||||
let ptr: NonOpaqueStyleDataPtr = Box::into_raw(Box::new(RefCell::new(PrivateStyleData::new())));
|
||||
Gecko_SetNodeData(self.node, ptr as *mut ServoNodeData);
|
||||
let ptr = Box::new(NonOpaqueStyleData::new());
|
||||
Gecko_SetNodeData(self.0, ptr.into_ffi());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +108,7 @@ impl TRestyleDamage for GeckoRestyleDamage {
|
|||
fn compute(source: &nsStyleContext,
|
||||
new_style: &Arc<ComputedValues>) -> Self {
|
||||
let context = source as *const nsStyleContext as *mut nsStyleContext;
|
||||
let hint = unsafe { Gecko_CalcStyleDifference(context, ComputedValues::to_borrowed(new_style)) };
|
||||
let hint = unsafe { Gecko_CalcStyleDifference(context, new_style.as_borrowed()) };
|
||||
GeckoRestyleDamage(hint)
|
||||
}
|
||||
|
||||
|
@ -136,22 +135,22 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
type ConcreteChildrenIterator = GeckoChildrenIterator<'ln>;
|
||||
|
||||
fn to_unsafe(&self) -> UnsafeNode {
|
||||
(self.node as usize, 0)
|
||||
(self.0 as *const _ as usize, 0)
|
||||
}
|
||||
|
||||
unsafe fn from_unsafe(n: &UnsafeNode) -> Self {
|
||||
GeckoNode::from_raw(n.0 as *mut RawGeckoNode)
|
||||
GeckoNode(&*(n.0 as *mut RawGeckoNode))
|
||||
}
|
||||
|
||||
fn is_text_node(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_IsTextNode(self.node)
|
||||
Gecko_IsTextNode(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_element(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_NodeIsElement(self.node)
|
||||
Gecko_NodeIsElement(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,16 +163,16 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
}
|
||||
|
||||
fn children(self) -> GeckoChildrenIterator<'ln> {
|
||||
let maybe_iter = unsafe { Gecko_MaybeCreateStyleChildrenIterator(self.node) };
|
||||
if !maybe_iter.is_null() {
|
||||
GeckoChildrenIterator::GeckoIterator(maybe_iter)
|
||||
let maybe_iter = unsafe { Gecko_MaybeCreateStyleChildrenIterator(self.0) };
|
||||
if let Some(iter) = maybe_iter.into_owned_opt() {
|
||||
GeckoChildrenIterator::GeckoIterator(iter)
|
||||
} else {
|
||||
GeckoChildrenIterator::Current(self.first_child())
|
||||
}
|
||||
}
|
||||
|
||||
fn opaque(&self) -> OpaqueNode {
|
||||
let ptr: uintptr_t = self.node as uintptr_t;
|
||||
let ptr: uintptr_t = self.0 as *const _ as uintptr_t;
|
||||
OpaqueNode(ptr)
|
||||
}
|
||||
|
||||
|
@ -191,7 +190,7 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
|
||||
fn as_element(&self) -> Option<GeckoElement<'ln>> {
|
||||
if self.is_element() {
|
||||
unsafe { Some(GeckoElement::from_raw(self.node as *mut RawGeckoElement)) }
|
||||
unsafe { Some(GeckoElement(&*(self.0 as *const _ as *const RawGeckoElement))) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -212,37 +211,37 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
fn is_dirty(&self) -> bool {
|
||||
// Return true unconditionally if we're not yet styled. This is a hack
|
||||
// and should go away soon.
|
||||
if unsafe { Gecko_GetNodeData(self.node) }.is_null() {
|
||||
if self.get_node_data().is_null() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let flags = unsafe { Gecko_GetNodeFlags(self.node) };
|
||||
let flags = unsafe { Gecko_GetNodeFlags(self.0) };
|
||||
flags & (NODE_IS_DIRTY_FOR_SERVO as u32) != 0
|
||||
}
|
||||
|
||||
unsafe fn set_dirty(&self, value: bool) {
|
||||
if value {
|
||||
Gecko_SetNodeFlags(self.node, NODE_IS_DIRTY_FOR_SERVO as u32)
|
||||
Gecko_SetNodeFlags(self.0, NODE_IS_DIRTY_FOR_SERVO as u32)
|
||||
} else {
|
||||
Gecko_UnsetNodeFlags(self.node, NODE_IS_DIRTY_FOR_SERVO as u32)
|
||||
Gecko_UnsetNodeFlags(self.0, NODE_IS_DIRTY_FOR_SERVO as u32)
|
||||
}
|
||||
}
|
||||
|
||||
fn has_dirty_descendants(&self) -> bool {
|
||||
// Return true unconditionally if we're not yet styled. This is a hack
|
||||
// and should go away soon.
|
||||
if unsafe { Gecko_GetNodeData(self.node) }.is_null() {
|
||||
if self.get_node_data().is_null() {
|
||||
return true;
|
||||
}
|
||||
let flags = unsafe { Gecko_GetNodeFlags(self.node) };
|
||||
let flags = unsafe { Gecko_GetNodeFlags(self.0) };
|
||||
flags & (NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0
|
||||
}
|
||||
|
||||
unsafe fn set_dirty_descendants(&self, value: bool) {
|
||||
if value {
|
||||
Gecko_SetNodeFlags(self.node, NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
|
||||
Gecko_SetNodeFlags(self.0, NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
|
||||
} else {
|
||||
Gecko_UnsetNodeFlags(self.node, NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
|
||||
Gecko_UnsetNodeFlags(self.0, NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,21 +258,18 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
|
||||
#[inline(always)]
|
||||
unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData> {
|
||||
self.get_node_data().as_ref().map(|d| d.as_unsafe_cell().get() as *const PrivateStyleData)
|
||||
self.get_node_data().borrow_opt().map(|d| d.0.as_unsafe_cell().get()
|
||||
as *const PrivateStyleData)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn borrow_data(&self) -> Option<Ref<PrivateStyleData>> {
|
||||
unsafe {
|
||||
self.get_node_data().as_ref().map(|d| d.borrow())
|
||||
}
|
||||
self.get_node_data().borrow_opt().map(|d| d.0.borrow())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>> {
|
||||
unsafe {
|
||||
self.get_node_data().as_ref().map(|d| d.borrow_mut())
|
||||
}
|
||||
self.get_node_data().borrow_opt().map(|d| d.0.borrow_mut())
|
||||
}
|
||||
|
||||
fn restyle_damage(self) -> Self::ConcreteRestyleDamage {
|
||||
|
@ -282,36 +278,36 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
}
|
||||
|
||||
fn set_restyle_damage(self, damage: Self::ConcreteRestyleDamage) {
|
||||
unsafe { Gecko_StoreStyleDifference(self.node, damage.0) }
|
||||
unsafe { Gecko_StoreStyleDifference(self.0, damage.0) }
|
||||
}
|
||||
|
||||
fn parent_node(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetParentNode(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
Gecko_GetParentNode(self.0).borrow_opt().map(|n| GeckoNode(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn first_child(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetFirstChild(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
Gecko_GetFirstChild(self.0).borrow_opt().map(|n| GeckoNode(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn last_child(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetLastChild(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
Gecko_GetLastChild(self.0).borrow_opt().map(|n| GeckoNode(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn prev_sibling(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetPrevSibling(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
Gecko_GetPrevSibling(self.0).borrow_opt().map(|n| GeckoNode(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn next_sibling(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetNextSibling(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
Gecko_GetNextSibling(self.0).borrow_opt().map(|n| GeckoNode(n))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,7 +323,7 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
unsafe {
|
||||
let atom_ptr = pseudo.map(|p| p.as_atom().as_ptr())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
let context_ptr = Gecko_GetStyleContext(self.node, atom_ptr);
|
||||
let context_ptr = Gecko_GetStyleContext(self.0, atom_ptr);
|
||||
context_ptr.as_ref()
|
||||
}
|
||||
}
|
||||
|
@ -349,14 +345,14 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
// (heavier-weight) Gecko-implemented iterator.
|
||||
pub enum GeckoChildrenIterator<'a> {
|
||||
Current(Option<GeckoNode<'a>>),
|
||||
GeckoIterator(*mut bindings::StyleChildrenIterator),
|
||||
GeckoIterator(bindings::StyleChildrenIteratorOwned),
|
||||
}
|
||||
|
||||
impl<'a> Drop for GeckoChildrenIterator<'a> {
|
||||
fn drop(&mut self) {
|
||||
if let GeckoChildrenIterator::GeckoIterator(it) = *self {
|
||||
if let GeckoChildrenIterator::GeckoIterator(ref it) = *self {
|
||||
unsafe {
|
||||
Gecko_DropStyleChildrenIterator(it);
|
||||
Gecko_DropStyleChildrenIterator(ptr::read(it as *const _));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -371,46 +367,34 @@ impl<'a> Iterator for GeckoChildrenIterator<'a> {
|
|||
*self = GeckoChildrenIterator::Current(next);
|
||||
curr
|
||||
},
|
||||
GeckoChildrenIterator::GeckoIterator(it) => unsafe {
|
||||
Gecko_GetNextStyleChild(it).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
GeckoChildrenIterator::GeckoIterator(ref it) => unsafe {
|
||||
Gecko_GetNextStyleChild(&it).borrow_opt().map(GeckoNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GeckoDocument<'ld> {
|
||||
document: *mut RawGeckoDocument,
|
||||
chain: PhantomData<&'ld ()>,
|
||||
}
|
||||
|
||||
impl<'ld> GeckoDocument<'ld> {
|
||||
pub unsafe fn from_raw(doc: *mut RawGeckoDocument) -> GeckoDocument<'ld> {
|
||||
GeckoDocument {
|
||||
document: doc,
|
||||
chain: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct GeckoDocument<'ld>(pub &'ld RawGeckoDocument);
|
||||
|
||||
impl<'ld> TDocument for GeckoDocument<'ld> {
|
||||
type ConcreteNode = GeckoNode<'ld>;
|
||||
type ConcreteElement = GeckoElement<'ld>;
|
||||
|
||||
fn as_node(&self) -> GeckoNode<'ld> {
|
||||
unsafe { GeckoNode::from_raw(self.document as *mut RawGeckoNode) }
|
||||
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
|
||||
}
|
||||
|
||||
fn root_node(&self) -> Option<GeckoNode<'ld>> {
|
||||
unsafe {
|
||||
Gecko_GetDocumentElement(self.document).as_ref().map(|el| GeckoElement::from_ref(el).as_node())
|
||||
Gecko_GetDocumentElement(self.0).borrow_opt().map(|el| GeckoElement(el).as_node())
|
||||
}
|
||||
}
|
||||
|
||||
fn drain_modified_elements(&self) -> Vec<(GeckoElement<'ld>, GeckoElementSnapshot)> {
|
||||
unimplemented!()
|
||||
/*
|
||||
let elements = unsafe { self.document.drain_modified_elements() };
|
||||
let elements = unsafe { self.0.drain_modified_elements() };
|
||||
elements.into_iter().map(|(el, snapshot)| (ServoLayoutElement::from_layout_js(el), snapshot)).collect()*/
|
||||
}
|
||||
fn will_paint(&self) { unimplemented!() }
|
||||
|
@ -418,10 +402,7 @@ impl<'ld> TDocument for GeckoDocument<'ld> {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GeckoElement<'le> {
|
||||
element: *mut RawGeckoElement,
|
||||
chain: PhantomData<&'le ()>,
|
||||
}
|
||||
pub struct GeckoElement<'le>(pub &'le RawGeckoElement);
|
||||
|
||||
impl<'le> fmt::Debug for GeckoElement<'le> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -434,17 +415,6 @@ impl<'le> fmt::Debug for GeckoElement<'le> {
|
|||
}
|
||||
|
||||
impl<'le> GeckoElement<'le> {
|
||||
pub unsafe fn from_raw(el: *mut RawGeckoElement) -> GeckoElement<'le> {
|
||||
GeckoElement {
|
||||
element: el,
|
||||
chain: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn from_ref(el: &RawGeckoElement) -> GeckoElement<'le> {
|
||||
GeckoElement::from_raw(el as *const RawGeckoElement as *mut RawGeckoElement)
|
||||
}
|
||||
|
||||
pub fn parse_style_attribute(value: &str) -> Option<PropertyDeclarationBlock> {
|
||||
// FIXME(bholley): Real base URL and error reporter.
|
||||
let base_url = &*DUMMY_BASE_URL;
|
||||
|
@ -466,32 +436,29 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
type ConcreteDocument = GeckoDocument<'le>;
|
||||
|
||||
fn as_node(&self) -> Self::ConcreteNode {
|
||||
unsafe { GeckoNode::from_raw(self.element as *mut RawGeckoNode) }
|
||||
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
|
||||
}
|
||||
|
||||
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
|
||||
let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.element) };
|
||||
let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.0) };
|
||||
if declarations.is_null() {
|
||||
None
|
||||
} else {
|
||||
let opt_ptr = GeckoDeclarationBlock::with(declarations, |declarations| {
|
||||
// Use a raw pointer to extend the lifetime
|
||||
declarations.declarations.as_ref().map(|r| r as *const Arc<_>)
|
||||
});
|
||||
opt_ptr.map(|ptr| unsafe { &*ptr })
|
||||
let declarations = declarations.as_arc::<GeckoDeclarationBlock>();
|
||||
declarations.declarations.as_ref().map(|r| r as *const Arc<_>).map(|ptr| unsafe { &*ptr })
|
||||
}
|
||||
}
|
||||
|
||||
fn get_state(&self) -> ElementState {
|
||||
unsafe {
|
||||
ElementState::from_bits_truncate(Gecko_ElementState(self.element) as u16)
|
||||
ElementState::from_bits_truncate(Gecko_ElementState(self.0) as u16)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_attr(&self, namespace: &Namespace, attr: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_HasAttr(self.element,
|
||||
bindings::Gecko_HasAttr(self.0,
|
||||
namespace.0.as_ptr(),
|
||||
attr.as_ptr())
|
||||
}
|
||||
|
@ -500,7 +467,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
#[inline]
|
||||
fn attr_equals(&self, namespace: &Namespace, attr: &Atom, val: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_AttrEquals(self.element,
|
||||
bindings::Gecko_AttrEquals(self.0,
|
||||
namespace.0.as_ptr(),
|
||||
attr.as_ptr(),
|
||||
val.as_ptr(),
|
||||
|
@ -511,7 +478,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
|
||||
impl<'le> PartialEq for GeckoElement<'le> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.element == other.element
|
||||
self.0 as *const _ == other.0 as *const _
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,37 +493,37 @@ impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
|
|||
impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||
fn parent_element(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
Gecko_GetParentElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||
Gecko_GetParentElement(self.0).borrow_opt().map(|el| GeckoElement(el))
|
||||
}
|
||||
}
|
||||
|
||||
fn first_child_element(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
Gecko_GetFirstChildElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||
Gecko_GetFirstChildElement(self.0).borrow_opt().map(|el| GeckoElement(el))
|
||||
}
|
||||
}
|
||||
|
||||
fn last_child_element(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
Gecko_GetLastChildElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||
Gecko_GetLastChildElement(self.0).borrow_opt().map(|el| GeckoElement(el))
|
||||
}
|
||||
}
|
||||
|
||||
fn prev_sibling_element(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
Gecko_GetPrevSiblingElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||
Gecko_GetPrevSiblingElement(self.0).borrow_opt().map(|el| GeckoElement(el))
|
||||
}
|
||||
}
|
||||
|
||||
fn next_sibling_element(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
Gecko_GetNextSiblingElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||
Gecko_GetNextSiblingElement(self.0).borrow_opt().map(|el| GeckoElement(el))
|
||||
}
|
||||
}
|
||||
|
||||
fn is_root(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_IsRootElement(self.element)
|
||||
Gecko_IsRootElement(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,22 +534,22 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
|
||||
fn get_local_name(&self) -> &WeakAtom {
|
||||
unsafe {
|
||||
WeakAtom::new(Gecko_LocalName(self.element))
|
||||
WeakAtom::new(Gecko_LocalName(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_namespace(&self) -> &WeakNamespace {
|
||||
unsafe {
|
||||
WeakNamespace::new(Gecko_Namespace(self.element))
|
||||
WeakNamespace::new(Gecko_Namespace(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
fn match_non_ts_pseudo_class(&self, pseudo_class: NonTSPseudoClass) -> bool {
|
||||
match pseudo_class {
|
||||
// https://github.com/servo/servo/issues/8718
|
||||
NonTSPseudoClass::AnyLink => unsafe { Gecko_IsLink(self.element) },
|
||||
NonTSPseudoClass::Link => unsafe { Gecko_IsUnvisitedLink(self.element) },
|
||||
NonTSPseudoClass::Visited => unsafe { Gecko_IsVisitedLink(self.element) },
|
||||
NonTSPseudoClass::AnyLink => unsafe { Gecko_IsLink(self.0) },
|
||||
NonTSPseudoClass::Link => unsafe { Gecko_IsUnvisitedLink(self.0) },
|
||||
NonTSPseudoClass::Visited => unsafe { Gecko_IsVisitedLink(self.0) },
|
||||
NonTSPseudoClass::Active |
|
||||
NonTSPseudoClass::Focus |
|
||||
NonTSPseudoClass::Hover |
|
||||
|
@ -601,7 +568,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
|
||||
fn get_id(&self) -> Option<Atom> {
|
||||
let ptr = unsafe {
|
||||
bindings::Gecko_AtomAttrValue(self.element,
|
||||
bindings::Gecko_AtomAttrValue(self.0,
|
||||
atom!("id").as_ptr())
|
||||
};
|
||||
|
||||
|
@ -613,7 +580,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
}
|
||||
|
||||
fn has_class(&self, name: &Atom) -> bool {
|
||||
snapshot_helpers::has_class(self.element,
|
||||
snapshot_helpers::has_class(self.0,
|
||||
name,
|
||||
Gecko_ClassOrClassList)
|
||||
}
|
||||
|
@ -621,14 +588,14 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
fn each_class<F>(&self, callback: F)
|
||||
where F: FnMut(&Atom)
|
||||
{
|
||||
snapshot_helpers::each_class(self.element,
|
||||
snapshot_helpers::each_class(self.0,
|
||||
callback,
|
||||
Gecko_ClassOrClassList)
|
||||
}
|
||||
|
||||
fn is_html_element_in_html_document(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_IsHTMLElementInHTMLDocument(self.element)
|
||||
Gecko_IsHTMLElementInHTMLDocument(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -660,14 +627,14 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
|
|||
|
||||
fn match_attr_has(&self, attr: &AttrSelector<Self::Impl>) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_HasAttr(self.element,
|
||||
bindings::Gecko_HasAttr(self.0,
|
||||
attr.ns_or_null(),
|
||||
attr.select_name(self.is_html_element_in_html_document()))
|
||||
}
|
||||
}
|
||||
fn match_attr_equals(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_AttrEquals(self.element,
|
||||
bindings::Gecko_AttrEquals(self.0,
|
||||
attr.ns_or_null(),
|
||||
attr.select_name(self.is_html_element_in_html_document()),
|
||||
value.as_ptr(),
|
||||
|
@ -676,7 +643,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
|
|||
}
|
||||
fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_AttrEquals(self.element,
|
||||
bindings::Gecko_AttrEquals(self.0,
|
||||
attr.ns_or_null(),
|
||||
attr.select_name(self.is_html_element_in_html_document()),
|
||||
value.as_ptr(),
|
||||
|
@ -685,7 +652,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
|
|||
}
|
||||
fn match_attr_includes(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_AttrIncludes(self.element,
|
||||
bindings::Gecko_AttrIncludes(self.0,
|
||||
attr.ns_or_null(),
|
||||
attr.select_name(self.is_html_element_in_html_document()),
|
||||
value.as_ptr())
|
||||
|
@ -693,7 +660,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
|
|||
}
|
||||
fn match_attr_dash(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_AttrDashEquals(self.element,
|
||||
bindings::Gecko_AttrDashEquals(self.0,
|
||||
attr.ns_or_null(),
|
||||
attr.select_name(self.is_html_element_in_html_document()),
|
||||
value.as_ptr())
|
||||
|
@ -701,7 +668,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
|
|||
}
|
||||
fn match_attr_prefix(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_AttrHasPrefix(self.element,
|
||||
bindings::Gecko_AttrHasPrefix(self.0,
|
||||
attr.ns_or_null(),
|
||||
attr.select_name(self.is_html_element_in_html_document()),
|
||||
value.as_ptr())
|
||||
|
@ -709,7 +676,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
|
|||
}
|
||||
fn match_attr_substring(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_AttrHasSubstring(self.element,
|
||||
bindings::Gecko_AttrHasSubstring(self.0,
|
||||
attr.ns_or_null(),
|
||||
attr.select_name(self.is_html_element_in_html_document()),
|
||||
value.as_ptr())
|
||||
|
@ -717,7 +684,7 @@ impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
|
|||
}
|
||||
fn match_attr_suffix(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
|
||||
unsafe {
|
||||
bindings::Gecko_AttrHasSuffix(self.element,
|
||||
bindings::Gecko_AttrHasSuffix(self.0,
|
||||
attr.ns_or_null(),
|
||||
attr.select_name(self.is_html_element_in_html_document()),
|
||||
value.as_ptr())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue