mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #6443 - Ms2ger:cleanup-layout, r=pcwalton
Various layout cleanup. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6443) <!-- Reviewable:end -->
This commit is contained in:
commit
469b9550f6
9 changed files with 207 additions and 287 deletions
|
@ -16,7 +16,7 @@
|
||||||
use block::BlockFlow;
|
use block::BlockFlow;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use data::{HAS_NEWLY_CONSTRUCTED_FLOW, LayoutDataAccess, LayoutDataWrapper};
|
use data::{HAS_NEWLY_CONSTRUCTED_FLOW, LayoutDataWrapper};
|
||||||
use floats::FloatKind;
|
use floats::FloatKind;
|
||||||
use flow::{Descendants, AbsDescendants};
|
use flow::{Descendants, AbsDescendants};
|
||||||
use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
||||||
|
@ -41,7 +41,7 @@ use table_row::TableRowFlow;
|
||||||
use table_rowgroup::TableRowGroupFlow;
|
use table_rowgroup::TableRowGroupFlow;
|
||||||
use table_wrapper::TableWrapperFlow;
|
use table_wrapper::TableWrapperFlow;
|
||||||
use text::TextRunScanner;
|
use text::TextRunScanner;
|
||||||
use wrapper::{PostorderNodeMutTraversal, PseudoElementType, TLayoutNode, ThreadSafeLayoutNode};
|
use wrapper::{PostorderNodeMutTraversal, PseudoElementType, ThreadSafeLayoutNode};
|
||||||
|
|
||||||
use gfx::display_list::OpaqueNode;
|
use gfx::display_list::OpaqueNode;
|
||||||
use script::dom::characterdata::CharacterDataTypeId;
|
use script::dom::characterdata::CharacterDataTypeId;
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
use animation;
|
use animation;
|
||||||
use context::SharedLayoutContext;
|
use context::SharedLayoutContext;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use data::{LayoutDataAccess, LayoutDataWrapper};
|
use data::LayoutDataWrapper;
|
||||||
use incremental::{self, RestyleDamage};
|
use incremental::{self, RestyleDamage};
|
||||||
use opaque_node::OpaqueNodeMethods;
|
use opaque_node::OpaqueNodeMethods;
|
||||||
use smallvec::SmallVec16;
|
use smallvec::SmallVec16;
|
||||||
use wrapper::{LayoutElement, LayoutNode, TLayoutNode};
|
use wrapper::{LayoutElement, LayoutNode};
|
||||||
|
|
||||||
use script::dom::characterdata::CharacterDataTypeId;
|
use script::dom::characterdata::CharacterDataTypeId;
|
||||||
use script::dom::node::NodeTypeId;
|
use script::dom::node::NodeTypeId;
|
||||||
|
@ -677,7 +677,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
&mut None => panic!("no layout data"),
|
&mut None => panic!("no layout data"),
|
||||||
&mut Some(ref mut layout_data) => {
|
&mut Some(ref mut layout_data) => {
|
||||||
match self.type_id() {
|
match self.type_id() {
|
||||||
Some(NodeTypeId::CharacterData(CharacterDataTypeId::Text)) => {
|
NodeTypeId::CharacterData(CharacterDataTypeId::Text) => {
|
||||||
// Text nodes get a copy of the parent style. This ensures
|
// Text nodes get a copy of the parent style. This ensures
|
||||||
// that during fragment construction any non-inherited
|
// that during fragment construction any non-inherited
|
||||||
// CSS properties (such as vertical-align) are correctly
|
// CSS properties (such as vertical-align) are correctly
|
||||||
|
|
|
@ -2,19 +2,14 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
|
||||||
|
|
||||||
use construct::{ConstructionItem, ConstructionResult};
|
use construct::{ConstructionItem, ConstructionResult};
|
||||||
use incremental::RestyleDamage;
|
use incremental::RestyleDamage;
|
||||||
use msg::constellation_msg::ConstellationChan;
|
use msg::constellation_msg::ConstellationChan;
|
||||||
use parallel::DomParallelInfo;
|
use parallel::DomParallelInfo;
|
||||||
use script::dom::node::SharedLayoutData;
|
use script::dom::node::SharedLayoutData;
|
||||||
use script::layout_interface::LayoutChan;
|
use script::layout_interface::LayoutChan;
|
||||||
use std::cell::{Ref, RefMut};
|
|
||||||
use std::mem;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use wrapper::{LayoutNode, TLayoutNode};
|
|
||||||
|
|
||||||
/// Data that layout associates with a node.
|
/// Data that layout associates with a node.
|
||||||
pub struct PrivateLayoutData {
|
pub struct PrivateLayoutData {
|
||||||
|
@ -95,41 +90,10 @@ impl LayoutDataWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code, unsafe_code)]
|
||||||
fn static_assertion(x: Option<LayoutDataWrapper>) {
|
fn static_assertion(x: Option<LayoutDataWrapper>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: Option<::script::dom::node::LayoutData> =
|
let _: Option<::script::dom::node::LayoutData> =
|
||||||
::std::intrinsics::transmute(x);
|
::std::intrinsics::transmute(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait that allows access to the layout data of a DOM node.
|
|
||||||
pub trait LayoutDataAccess {
|
|
||||||
/// Borrows the layout data without checks.
|
|
||||||
unsafe fn borrow_layout_data_unchecked(&self) -> *const Option<LayoutDataWrapper>;
|
|
||||||
/// Borrows the layout data immutably. Fails on a conflicting borrow.
|
|
||||||
fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>>;
|
|
||||||
/// Borrows the layout data mutably. Fails on a conflicting borrow.
|
|
||||||
fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ln> LayoutDataAccess for LayoutNode<'ln> {
|
|
||||||
#[inline(always)]
|
|
||||||
unsafe fn borrow_layout_data_unchecked(&self) -> *const Option<LayoutDataWrapper> {
|
|
||||||
mem::transmute(self.get().layout_data_unchecked())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> {
|
|
||||||
unsafe {
|
|
||||||
mem::transmute(self.get().layout_data())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> {
|
|
||||||
unsafe {
|
|
||||||
mem::transmute(self.get().layout_data_mut())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ use layout_debug;
|
||||||
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified};
|
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified};
|
||||||
use text;
|
use text;
|
||||||
use opaque_node::OpaqueNodeMethods;
|
use opaque_node::OpaqueNodeMethods;
|
||||||
use wrapper::{TLayoutNode, ThreadSafeLayoutNode};
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use euclid::{Point2D, Rect, Size2D};
|
use euclid::{Point2D, Rect, Size2D};
|
||||||
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
|
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
|
||||||
|
|
|
@ -11,7 +11,7 @@ use animation;
|
||||||
use construct::ConstructionResult;
|
use construct::ConstructionResult;
|
||||||
use context::{SharedLayoutContext, SharedLayoutContextWrapper, heap_size_of_local_context};
|
use context::{SharedLayoutContext, SharedLayoutContextWrapper, heap_size_of_local_context};
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use data::{LayoutDataAccess, LayoutDataWrapper};
|
use data::LayoutDataWrapper;
|
||||||
use display_list_builder::ToGfxColor;
|
use display_list_builder::ToGfxColor;
|
||||||
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
|
@ -21,7 +21,7 @@ use layout_debug;
|
||||||
use opaque_node::OpaqueNodeMethods;
|
use opaque_node::OpaqueNodeMethods;
|
||||||
use parallel::{self, UnsafeFlow};
|
use parallel::{self, UnsafeFlow};
|
||||||
use sequential;
|
use sequential;
|
||||||
use wrapper::{LayoutNode, TLayoutNode};
|
use wrapper::LayoutNode;
|
||||||
|
|
||||||
use azure::azure::AzColor;
|
use azure::azure::AzColor;
|
||||||
use canvas_traits::CanvasMsg;
|
use canvas_traits::CanvasMsg;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use script::dom::bindings::js::LayoutJS;
|
||||||
use script::dom::node::Node;
|
use script::dom::node::Node;
|
||||||
use script::layout_interface::{TrustedNodeAddress};
|
use script::layout_interface::{TrustedNodeAddress};
|
||||||
use script_traits::UntrustedNodeAddress;
|
use script_traits::UntrustedNodeAddress;
|
||||||
use wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
|
use wrapper::{LayoutNode, ThreadSafeLayoutNode};
|
||||||
|
|
||||||
pub trait OpaqueNodeMethods {
|
pub trait OpaqueNodeMethods {
|
||||||
/// Converts a DOM node (layout view) to an `OpaqueNode`.
|
/// Converts a DOM node (layout view) to an `OpaqueNode`.
|
||||||
|
|
|
@ -12,7 +12,7 @@ use context::{LayoutContext, SharedLayoutContextWrapper, SharedLayoutContext};
|
||||||
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
|
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
|
||||||
use flow;
|
use flow;
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
use data::{LayoutDataAccess, LayoutDataWrapper};
|
use data::LayoutDataWrapper;
|
||||||
use traversal::{BubbleISizes, AssignISizes, AssignBSizesAndStoreOverflow};
|
use traversal::{BubbleISizes, AssignISizes, AssignBSizesAndStoreOverflow};
|
||||||
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
|
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
|
||||||
use traversal::{RecalcStyleForNode, ConstructFlows};
|
use traversal::{RecalcStyleForNode, ConstructFlows};
|
||||||
|
|
|
@ -21,8 +21,6 @@
|
||||||
//!
|
//!
|
||||||
//! Rules of the road for this file:
|
//! Rules of the road for this file:
|
||||||
//!
|
//!
|
||||||
//! * You must not use `.get()`; instead, use `.unsafe_get()`.
|
|
||||||
//!
|
|
||||||
//! * Do not call any methods on DOM nodes without checking to see whether they use borrow flags.
|
//! * Do not call any methods on DOM nodes without checking to see whether they use borrow flags.
|
||||||
//!
|
//!
|
||||||
//! o Instead of `get_attr()`, use `.get_attr_val_for_layout()`.
|
//! o Instead of `get_attr()`, use `.get_attr_val_for_layout()`.
|
||||||
|
@ -36,7 +34,7 @@ use canvas_traits::CanvasMsg;
|
||||||
use context::SharedLayoutContext;
|
use context::SharedLayoutContext;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use incremental::RestyleDamage;
|
use incremental::RestyleDamage;
|
||||||
use data::{LayoutDataAccess, LayoutDataFlags, LayoutDataWrapper, PrivateLayoutData};
|
use data::{LayoutDataFlags, LayoutDataWrapper, PrivateLayoutData};
|
||||||
use opaque_node::OpaqueNodeMethods;
|
use opaque_node::OpaqueNodeMethods;
|
||||||
|
|
||||||
use gfx::display_list::OpaqueNode;
|
use gfx::display_list::OpaqueNode;
|
||||||
|
@ -50,11 +48,10 @@ use script::dom::characterdata::{CharacterDataTypeId, LayoutCharacterDataHelpers
|
||||||
use script::dom::element::{Element, ElementTypeId};
|
use script::dom::element::{Element, ElementTypeId};
|
||||||
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
|
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
|
||||||
use script::dom::htmlelement::HTMLElementTypeId;
|
use script::dom::htmlelement::HTMLElementTypeId;
|
||||||
use script::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers};
|
use script::dom::htmlcanvaselement::LayoutHTMLCanvasElementHelpers;
|
||||||
use script::dom::htmliframeelement::HTMLIFrameElement;
|
|
||||||
use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
|
use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
|
||||||
use script::dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers};
|
use script::dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers};
|
||||||
use script::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers};
|
use script::dom::htmltextareaelement::LayoutHTMLTextAreaElementHelpers;
|
||||||
use script::dom::node::{Node, NodeTypeId};
|
use script::dom::node::{Node, NodeTypeId};
|
||||||
use script::dom::node::{LayoutNodeHelpers, RawLayoutNodeHelpers, SharedLayoutData};
|
use script::dom::node::{LayoutNodeHelpers, RawLayoutNodeHelpers, SharedLayoutData};
|
||||||
use script::dom::node::{HAS_CHANGED, IS_DIRTY, HAS_DIRTY_SIBLINGS, HAS_DIRTY_DESCENDANTS};
|
use script::dom::node::{HAS_CHANGED, IS_DIRTY, HAS_DIRTY_SIBLINGS, HAS_DIRTY_DESCENDANTS};
|
||||||
|
@ -78,99 +75,6 @@ use style::node::{TElement, TElementAttributes, TNode};
|
||||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// Allows some convenience methods on generic layout nodes.
|
|
||||||
pub trait TLayoutNode {
|
|
||||||
/// Creates a new layout node with the same lifetime as this layout node.
|
|
||||||
unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> Self;
|
|
||||||
|
|
||||||
/// Returns the type ID of this node. Fails if this node is borrowed mutably. Returns `None`
|
|
||||||
/// if this is a pseudo-element; otherwise, returns `Some`.
|
|
||||||
fn type_id(&self) -> Option<NodeTypeId>;
|
|
||||||
|
|
||||||
/// Returns the interior of this node as a `LayoutJS`. This is highly unsafe for layout to
|
|
||||||
/// call and as such is marked `unsafe`.
|
|
||||||
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node>;
|
|
||||||
|
|
||||||
/// Returns the interior of this node as a `Node`. This is highly unsafe for layout to call
|
|
||||||
/// and as such is marked `unsafe`.
|
|
||||||
unsafe fn get<'a>(&'a self) -> &'a Node {
|
|
||||||
&*self.get_jsmanaged().unsafe_get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_is_element(&self) -> bool {
|
|
||||||
match self.type_id() {
|
|
||||||
Some(NodeTypeId::Element(..)) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_is_document(&self) -> bool {
|
|
||||||
match self.type_id() {
|
|
||||||
Some(NodeTypeId::Document(..)) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If this is an image element, returns its URL. If this is not an image element, fails.
|
|
||||||
///
|
|
||||||
/// FIXME(pcwalton): Don't copy URLs.
|
|
||||||
fn image_url(&self) -> Option<Url> {
|
|
||||||
unsafe {
|
|
||||||
match HTMLImageElementCast::to_layout_js(self.get_jsmanaged()) {
|
|
||||||
Some(elem) => elem.image_url().as_ref().map(|url| (*url).clone()),
|
|
||||||
None => panic!("not an image!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn renderer(&self) -> Option<Sender<CanvasMsg>> {
|
|
||||||
unsafe {
|
|
||||||
let canvas_element: Option<LayoutJS<HTMLCanvasElement>> =
|
|
||||||
HTMLCanvasElementCast::to_layout_js(self.get_jsmanaged());
|
|
||||||
canvas_element.and_then(|elem| elem.get_renderer())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn canvas_width(&self) -> u32 {
|
|
||||||
unsafe {
|
|
||||||
let canvas_element: Option<LayoutJS<HTMLCanvasElement>> =
|
|
||||||
HTMLCanvasElementCast::to_layout_js(self.get_jsmanaged());
|
|
||||||
canvas_element.unwrap().get_canvas_width()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn canvas_height(&self) -> u32 {
|
|
||||||
unsafe {
|
|
||||||
let canvas_element: Option<LayoutJS<HTMLCanvasElement>> =
|
|
||||||
HTMLCanvasElementCast::to_layout_js(self.get_jsmanaged());
|
|
||||||
canvas_element.unwrap().get_canvas_height()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If this node is an iframe element, returns its pipeline and subpage IDs. If this node is
|
|
||||||
/// not an iframe element, fails.
|
|
||||||
fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) {
|
|
||||||
unsafe {
|
|
||||||
let iframe_element: LayoutJS<HTMLIFrameElement> =
|
|
||||||
match HTMLIFrameElementCast::to_layout_js(self.get_jsmanaged()) {
|
|
||||||
Some(elem) => elem,
|
|
||||||
None => panic!("not an iframe element!")
|
|
||||||
};
|
|
||||||
((*iframe_element.unsafe_get()).containing_page_pipeline_id().unwrap(),
|
|
||||||
(*iframe_element.unsafe_get()).subpage_id().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If this is a text node or generated content, copies out its content. If this is not a text
|
|
||||||
/// node, fails.
|
|
||||||
///
|
|
||||||
/// FIXME(pcwalton): This might have too much copying and/or allocation. Profile this.
|
|
||||||
fn text_content(&self) -> Vec<ContentItem>;
|
|
||||||
|
|
||||||
/// Returns the first child of this node.
|
|
||||||
fn first_child(&self) -> Option<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
|
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
|
||||||
/// only ever see these and must never see instances of `LayoutJS`.
|
/// only ever see these and must never see instances of `LayoutJS`.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -189,56 +93,22 @@ impl<'a> PartialEq for LayoutNode<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> TLayoutNode for LayoutNode<'ln> {
|
impl<'ln> LayoutNode<'ln> {
|
||||||
unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> LayoutNode<'ln> {
|
/// Creates a new layout node with the same lifetime as this layout node.
|
||||||
|
pub unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> LayoutNode<'ln> {
|
||||||
LayoutNode {
|
LayoutNode {
|
||||||
node: *node,
|
node: *node,
|
||||||
chain: self.chain,
|
chain: self.chain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_id(&self) -> Option<NodeTypeId> {
|
/// Returns the type ID of this node.
|
||||||
|
pub fn type_id(&self) -> NodeTypeId {
|
||||||
unsafe {
|
unsafe {
|
||||||
Some(self.node.type_id_for_layout())
|
self.node.type_id_for_layout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node> {
|
|
||||||
&self.node
|
|
||||||
}
|
|
||||||
|
|
||||||
fn first_child(&self) -> Option<LayoutNode<'ln>> {
|
|
||||||
unsafe {
|
|
||||||
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn text_content(&self) -> Vec<ContentItem> {
|
|
||||||
unsafe {
|
|
||||||
let text: Option<LayoutJS<Text>> = TextCast::to_layout_js(self.get_jsmanaged());
|
|
||||||
if let Some(text) = text {
|
|
||||||
return vec![
|
|
||||||
ContentItem::String(
|
|
||||||
CharacterDataCast::from_layout_js(&text).data_for_layout().to_owned())
|
|
||||||
];
|
|
||||||
}
|
|
||||||
let input: Option<LayoutJS<HTMLInputElement>> =
|
|
||||||
HTMLInputElementCast::to_layout_js(self.get_jsmanaged());
|
|
||||||
if let Some(input) = input {
|
|
||||||
return vec![ContentItem::String(input.get_value_for_layout())];
|
|
||||||
}
|
|
||||||
let area: Option<LayoutJS<HTMLTextAreaElement>> =
|
|
||||||
HTMLTextAreaElementCast::to_layout_js(self.get_jsmanaged());
|
|
||||||
if let Some(area) = area {
|
|
||||||
return vec![ContentItem::String(area.get_value_for_layout())];
|
|
||||||
}
|
|
||||||
|
|
||||||
panic!("not text!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ln> LayoutNode<'ln> {
|
|
||||||
pub fn dump(self) {
|
pub fn dump(self) {
|
||||||
self.dump_indent(0);
|
self.dump_indent(0);
|
||||||
}
|
}
|
||||||
|
@ -282,14 +152,8 @@ impl<'ln> LayoutNode<'ln> {
|
||||||
|
|
||||||
/// Returns an iterator over this node's children.
|
/// Returns an iterator over this node's children.
|
||||||
pub fn children(self) -> LayoutNodeChildrenIterator<'ln> {
|
pub fn children(self) -> LayoutNodeChildrenIterator<'ln> {
|
||||||
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
|
|
||||||
// of disambiguating methods.
|
|
||||||
fn first_child<T: TLayoutNode>(this: T) -> Option<T> {
|
|
||||||
this.first_child()
|
|
||||||
}
|
|
||||||
|
|
||||||
LayoutNodeChildrenIterator {
|
LayoutNodeChildrenIterator {
|
||||||
current: first_child(self),
|
current: self.first_child(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,6 +164,8 @@ impl<'ln> LayoutNode<'ln> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the interior of this node as a `LayoutJS`. This is highly unsafe for layout to
|
||||||
|
/// call and as such is marked `unsafe`.
|
||||||
pub unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node> {
|
pub unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node> {
|
||||||
&self.node
|
&self.node
|
||||||
}
|
}
|
||||||
|
@ -322,7 +188,7 @@ impl<'ln> LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_children(self) -> bool {
|
pub fn has_children(self) -> bool {
|
||||||
TLayoutNode::first_child(&self).is_some()
|
self.first_child().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// While doing a reflow, the node at the root has no parent, as far as we're
|
/// While doing a reflow, the node at the root has no parent, as far as we're
|
||||||
|
@ -396,11 +262,17 @@ impl<'ln> TNode for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_element(&self) -> bool {
|
fn is_element(&self) -> bool {
|
||||||
self.node_is_element()
|
match self.type_id() {
|
||||||
|
NodeTypeId::Element(..) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_document(&self) -> bool {
|
fn is_document(&self) -> bool {
|
||||||
self.node_is_document()
|
match self.type_id() {
|
||||||
|
NodeTypeId::Document(..) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
|
fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
|
||||||
|
@ -460,6 +332,28 @@ impl<'ln> LayoutNode<'ln> {
|
||||||
pub unsafe fn set_dirty_descendants(&self, value: bool) {
|
pub unsafe fn set_dirty_descendants(&self, value: bool) {
|
||||||
self.node.set_flag(HAS_DIRTY_DESCENDANTS, value)
|
self.node.set_flag(HAS_DIRTY_DESCENDANTS, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Borrows the layout data without checks.
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn borrow_layout_data_unchecked(&self) -> *const Option<LayoutDataWrapper> {
|
||||||
|
mem::transmute(self.get_jsmanaged().layout_data_unchecked())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Borrows the layout data immutably. Fails on a conflicting borrow.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> {
|
||||||
|
unsafe {
|
||||||
|
mem::transmute(self.get_jsmanaged().layout_data())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Borrows the layout data mutably. Fails on a conflicting borrow.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> {
|
||||||
|
unsafe {
|
||||||
|
mem::transmute(self.get_jsmanaged().layout_data_mut())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LayoutNodeChildrenIterator<'a> {
|
pub struct LayoutNodeChildrenIterator<'a> {
|
||||||
|
@ -718,76 +612,15 @@ pub struct ThreadSafeLayoutNode<'ln> {
|
||||||
pseudo: PseudoElementType,
|
pseudo: PseudoElementType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
|
impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
/// Creates a new layout node with the same lifetime as this layout node.
|
/// Creates a new layout node with the same lifetime as this layout node.
|
||||||
unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> ThreadSafeLayoutNode<'ln> {
|
pub unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> ThreadSafeLayoutNode<'ln> {
|
||||||
ThreadSafeLayoutNode {
|
ThreadSafeLayoutNode {
|
||||||
node: self.node.new_with_this_lifetime(node),
|
node: self.node.new_with_this_lifetime(node),
|
||||||
pseudo: PseudoElementType::Normal,
|
pseudo: PseudoElementType::Normal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `None` if this is a pseudo-element.
|
|
||||||
fn type_id(&self) -> Option<NodeTypeId> {
|
|
||||||
if self.pseudo != PseudoElementType::Normal {
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
|
|
||||||
self.node.type_id()
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node> {
|
|
||||||
self.node.get_jsmanaged()
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn get<'a>(&'a self) -> &'a Node { // this change.
|
|
||||||
&*self.get_jsmanaged().unsafe_get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn first_child(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
|
|
||||||
if self.pseudo != PseudoElementType::Normal {
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.has_before_pseudo() {
|
|
||||||
// FIXME(pcwalton): This logic looks weird. Is it right?
|
|
||||||
match self.pseudo {
|
|
||||||
PseudoElementType::Normal => {
|
|
||||||
let pseudo_before_node = self.with_pseudo(PseudoElementType::Before(self.get_before_display()));
|
|
||||||
return Some(pseudo_before_node)
|
|
||||||
}
|
|
||||||
PseudoElementType::Before(display::T::inline) => {}
|
|
||||||
PseudoElementType::Before(_) => {
|
|
||||||
let pseudo_before_node = self.with_pseudo(PseudoElementType::Before(display::T::inline));
|
|
||||||
return Some(pseudo_before_node)
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn text_content(&self) -> Vec<ContentItem> {
|
|
||||||
if self.pseudo != PseudoElementType::Normal {
|
|
||||||
let layout_data_ref = self.borrow_layout_data();
|
|
||||||
let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap();
|
|
||||||
|
|
||||||
if self.pseudo.is_before() {
|
|
||||||
let before_style = node_layout_data_wrapper.data.before_style.as_ref().unwrap();
|
|
||||||
return get_content(&before_style.get_box().content)
|
|
||||||
} else {
|
|
||||||
let after_style = node_layout_data_wrapper.data.after_style.as_ref().unwrap();
|
|
||||||
return get_content(&after_style.get_box().content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.node.text_content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ln> ThreadSafeLayoutNode<'ln> {
|
|
||||||
/// Creates a new `ThreadSafeLayoutNode` from the given `LayoutNode`.
|
/// Creates a new `ThreadSafeLayoutNode` from the given `LayoutNode`.
|
||||||
pub fn new<'a>(node: &LayoutNode<'a>) -> ThreadSafeLayoutNode<'a> {
|
pub fn new<'a>(node: &LayoutNode<'a>) -> ThreadSafeLayoutNode<'a> {
|
||||||
ThreadSafeLayoutNode {
|
ThreadSafeLayoutNode {
|
||||||
|
@ -805,6 +638,22 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the interior of this node as a `LayoutJS`. This is highly unsafe for layout to
|
||||||
|
/// call and as such is marked `unsafe`.
|
||||||
|
pub unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node> {
|
||||||
|
self.node.get_jsmanaged()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the type ID of this node.
|
||||||
|
/// Returns `None` if this is a pseudo-element; otherwise, returns `Some`.
|
||||||
|
pub fn type_id(&self) -> Option<NodeTypeId> {
|
||||||
|
if self.pseudo != PseudoElementType::Normal {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(self.node.type_id())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn debug_id(self) -> usize {
|
pub fn debug_id(self) -> usize {
|
||||||
self.node.debug_id()
|
self.node.debug_id()
|
||||||
}
|
}
|
||||||
|
@ -813,6 +662,20 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
self.node.flow_debug_id()
|
self.node.flow_debug_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn first_child(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
|
||||||
|
if self.pseudo != PseudoElementType::Normal {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.has_before_pseudo() {
|
||||||
|
return Some(self.with_pseudo(PseudoElementType::Before(self.get_before_display())));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the next sibling of this node. Unsafe and private because this can lead to races.
|
/// Returns the next sibling of this node. Unsafe and private because this can lead to races.
|
||||||
unsafe fn next_sibling(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
|
unsafe fn next_sibling(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
|
||||||
if self.pseudo.is_before() {
|
if self.pseudo.is_before() {
|
||||||
|
@ -889,11 +752,11 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
layout_data_wrapper_ref.data.after_style.is_some()
|
layout_data_wrapper_ref.data.after_style.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the layout data without checking. Fails on a conflicting borrow.
|
/// Borrows the layout data without checking.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn borrow_layout_data_unchecked<'a>(&'a self) -> *const Option<LayoutDataWrapper> {
|
fn borrow_layout_data_unchecked<'a>(&'a self) -> *const Option<LayoutDataWrapper> {
|
||||||
unsafe {
|
unsafe {
|
||||||
mem::transmute(self.get().layout_data_unchecked())
|
self.node.borrow_layout_data_unchecked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -902,9 +765,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
|
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> {
|
pub fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> {
|
||||||
unsafe {
|
self.node.borrow_layout_data()
|
||||||
mem::transmute(self.get().layout_data())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the layout data mutably. Fails on a conflicting borrow.
|
/// Borrows the layout data mutably. Fails on a conflicting borrow.
|
||||||
|
@ -912,9 +773,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
|
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> {
|
pub fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> {
|
||||||
unsafe {
|
self.node.mutate_layout_data()
|
||||||
mem::transmute(self.get().layout_data_mut())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the tree in postorder.
|
/// Traverses the tree in postorder.
|
||||||
|
@ -1052,6 +911,89 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If this is a text node, generated content, or a form element, copies out
|
||||||
|
/// its content. Otherwise, panics.
|
||||||
|
///
|
||||||
|
/// FIXME(pcwalton): This might have too much copying and/or allocation. Profile this.
|
||||||
|
pub fn text_content(&self) -> Vec<ContentItem> {
|
||||||
|
if self.pseudo != PseudoElementType::Normal {
|
||||||
|
let layout_data_ref = self.borrow_layout_data();
|
||||||
|
let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap();
|
||||||
|
|
||||||
|
if self.pseudo.is_before() {
|
||||||
|
let before_style = node_layout_data_wrapper.data.before_style.as_ref().unwrap();
|
||||||
|
return get_content(&before_style.get_box().content)
|
||||||
|
} else {
|
||||||
|
let after_style = node_layout_data_wrapper.data.after_style.as_ref().unwrap();
|
||||||
|
return get_content(&after_style.get_box().content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let this = unsafe { self.get_jsmanaged() };
|
||||||
|
let text = TextCast::to_layout_js(this);
|
||||||
|
if let Some(text) = text {
|
||||||
|
let data = unsafe {
|
||||||
|
CharacterDataCast::from_layout_js(&text).data_for_layout().to_owned()
|
||||||
|
};
|
||||||
|
return vec![ContentItem::String(data)];
|
||||||
|
}
|
||||||
|
let input = HTMLInputElementCast::to_layout_js(this);
|
||||||
|
if let Some(input) = input {
|
||||||
|
let data = unsafe { input.get_value_for_layout() };
|
||||||
|
return vec![ContentItem::String(data)];
|
||||||
|
}
|
||||||
|
let area = HTMLTextAreaElementCast::to_layout_js(this);
|
||||||
|
if let Some(area) = area {
|
||||||
|
let data = unsafe { area.get_value_for_layout() };
|
||||||
|
return vec![ContentItem::String(data)];
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("not text!")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If this is an image element, returns its URL. If this is not an image element, fails.
|
||||||
|
///
|
||||||
|
/// FIXME(pcwalton): Don't copy URLs.
|
||||||
|
pub fn image_url(&self) -> Option<Url> {
|
||||||
|
unsafe {
|
||||||
|
HTMLImageElementCast::to_layout_js(self.get_jsmanaged())
|
||||||
|
.expect("not an image!")
|
||||||
|
.image_url()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn renderer(&self) -> Option<Sender<CanvasMsg>> {
|
||||||
|
unsafe {
|
||||||
|
let canvas_element = HTMLCanvasElementCast::to_layout_js(self.get_jsmanaged());
|
||||||
|
canvas_element.and_then(|elem| elem.get_renderer())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn canvas_width(&self) -> u32 {
|
||||||
|
unsafe {
|
||||||
|
let canvas_element = HTMLCanvasElementCast::to_layout_js(self.get_jsmanaged());
|
||||||
|
canvas_element.unwrap().get_canvas_width()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn canvas_height(&self) -> u32 {
|
||||||
|
unsafe {
|
||||||
|
let canvas_element = HTMLCanvasElementCast::to_layout_js(self.get_jsmanaged());
|
||||||
|
canvas_element.unwrap().get_canvas_height()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If this node is an iframe element, returns its pipeline and subpage IDs. If this node is
|
||||||
|
/// not an iframe element, fails.
|
||||||
|
pub fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) {
|
||||||
|
unsafe {
|
||||||
|
let iframe_element = HTMLIFrameElementCast::to_layout_js(self.get_jsmanaged())
|
||||||
|
.expect("not an iframe element!");
|
||||||
|
((*iframe_element.unsafe_get()).containing_page_pipeline_id().unwrap(),
|
||||||
|
(*iframe_element.unsafe_get()).subpage_id().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ThreadSafeLayoutNodeChildrenIterator<'a> {
|
pub struct ThreadSafeLayoutNodeChildrenIterator<'a> {
|
||||||
|
@ -1137,7 +1079,7 @@ pub trait PostorderNodeMutTraversal {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opaque type stored in type-unsafe work queues for parallel layout.
|
/// Opaque type stored in type-unsafe work queues for parallel layout.
|
||||||
/// Must be transmutable to and from LayoutNode/ThreadSafeLayoutNode.
|
/// Must be transmutable to and from LayoutNode.
|
||||||
pub type UnsafeLayoutNode = (usize, usize);
|
pub type UnsafeLayoutNode = (usize, usize);
|
||||||
|
|
||||||
pub fn layout_node_to_unsafe_layout_node(node: &LayoutNode) -> UnsafeLayoutNode {
|
pub fn layout_node_to_unsafe_layout_node(node: &LayoutNode) -> UnsafeLayoutNode {
|
||||||
|
|
|
@ -53,6 +53,7 @@ use script_traits::UntrustedNodeAddress;
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
use util::namespace;
|
use util::namespace;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
use util::task_state;
|
||||||
use selectors::parser::{Selector, AttrSelector, NamespaceConstraint};
|
use selectors::parser::{Selector, AttrSelector, NamespaceConstraint};
|
||||||
use selectors::parser::parse_author_origin_selector_list_from_str;
|
use selectors::parser::parse_author_origin_selector_list_from_str;
|
||||||
use selectors::matching::matches;
|
use selectors::matching::matches;
|
||||||
|
@ -222,7 +223,7 @@ pub struct LayoutData {
|
||||||
unsafe impl Send for LayoutData {}
|
unsafe impl Send for LayoutData {}
|
||||||
|
|
||||||
pub struct LayoutDataRef {
|
pub struct LayoutDataRef {
|
||||||
pub data_cell: RefCell<Option<LayoutData>>,
|
data_cell: RefCell<Option<LayoutData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
no_jsmanaged_fields!(LayoutDataRef);
|
no_jsmanaged_fields!(LayoutDataRef);
|
||||||
|
@ -236,7 +237,8 @@ impl LayoutDataRef {
|
||||||
|
|
||||||
/// Sends layout data, if any, back to the layout task to be destroyed.
|
/// Sends layout data, if any, back to the layout task to be destroyed.
|
||||||
pub fn dispose(&self) {
|
pub fn dispose(&self) {
|
||||||
if let Some(mut layout_data) = mem::replace(&mut *self.borrow_mut(), None) {
|
debug_assert!(task_state::get().is_script());
|
||||||
|
if let Some(mut layout_data) = mem::replace(&mut *self.data_cell.borrow_mut(), None) {
|
||||||
let layout_chan = layout_data.chan.take();
|
let layout_chan = layout_data.chan.take();
|
||||||
match layout_chan {
|
match layout_chan {
|
||||||
None => {}
|
None => {}
|
||||||
|
@ -248,18 +250,20 @@ impl LayoutDataRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the layout data immutably, *asserting that there are no mutators*. Bad things will
|
/// Borrows the layout data immutably, *assuming that there are no mutators*. Bad things will
|
||||||
/// happen if you try to mutate the layout data while this is held. This is the only thread-
|
/// happen if you try to mutate the layout data while this is held. This is the only thread-
|
||||||
/// safe layout data accessor.
|
/// safe layout data accessor.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub unsafe fn borrow_unchecked(&self) -> *const Option<LayoutData> {
|
pub unsafe fn borrow_unchecked(&self) -> *const Option<LayoutData> {
|
||||||
|
debug_assert!(task_state::get().is_layout());
|
||||||
self.data_cell.as_unsafe_cell().get() as *const _
|
self.data_cell.as_unsafe_cell().get() as *const _
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrows the layout data immutably. This function is *not* thread-safe.
|
/// Borrows the layout data immutably. This function is *not* thread-safe.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn borrow<'a>(&'a self) -> Ref<'a,Option<LayoutData>> {
|
pub fn borrow<'a>(&'a self) -> Ref<'a,Option<LayoutData>> {
|
||||||
|
debug_assert!(task_state::get().is_layout());
|
||||||
self.data_cell.borrow()
|
self.data_cell.borrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +274,7 @@ impl LayoutDataRef {
|
||||||
/// on it. This has already resulted in one bug!
|
/// on it. This has already resulted in one bug!
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a,Option<LayoutData>> {
|
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a,Option<LayoutData>> {
|
||||||
|
debug_assert!(task_state::get().is_layout());
|
||||||
self.data_cell.borrow_mut()
|
self.data_cell.borrow_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1086,6 +1091,13 @@ pub trait LayoutNodeHelpers {
|
||||||
unsafe fn get_flag(&self, flag: NodeFlags) -> bool;
|
unsafe fn get_flag(&self, flag: NodeFlags) -> bool;
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn set_flag(&self, flag: NodeFlags, value: bool);
|
unsafe fn set_flag(&self, flag: NodeFlags, value: bool);
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn layout_data(&self) -> Ref<Option<LayoutData>>;
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn layout_data_mut(&self) -> RefMut<Option<LayoutData>>;
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutNodeHelpers for LayoutJS<Node> {
|
impl LayoutNodeHelpers for LayoutJS<Node> {
|
||||||
|
@ -1157,6 +1169,24 @@ impl LayoutNodeHelpers for LayoutJS<Node> {
|
||||||
|
|
||||||
(*this).flags.set(flags);
|
(*this).flags.set(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn layout_data(&self) -> Ref<Option<LayoutData>> {
|
||||||
|
(*self.unsafe_get()).layout_data.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn layout_data_mut(&self) -> RefMut<Option<LayoutData>> {
|
||||||
|
(*self.unsafe_get()).layout_data.borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData> {
|
||||||
|
(*self.unsafe_get()).layout_data.borrow_unchecked()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RawLayoutNodeHelpers {
|
pub trait RawLayoutNodeHelpers {
|
||||||
|
@ -1456,22 +1486,6 @@ impl Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn layout_data(&self) -> Ref<Option<LayoutData>> {
|
|
||||||
self.layout_data.borrow()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn layout_data_mut(&self) -> RefMut<Option<LayoutData>> {
|
|
||||||
self.layout_data.borrow_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
pub unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData> {
|
|
||||||
self.layout_data.borrow_unchecked()
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-node-adopt
|
// https://dom.spec.whatwg.org/#concept-node-adopt
|
||||||
pub fn adopt(node: &Node, document: &Document) {
|
pub fn adopt(node: &Node, document: &Document) {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue