aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/node.rs')
-rw-r--r--components/script/dom/node.rs211
1 files changed, 177 insertions, 34 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index ee1451a0137..ddea136c9f3 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -4,6 +4,7 @@
//! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements.
+use document_loader::DocumentLoader;
use dom::attr::{Attr, AttrHelpers};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
@@ -157,6 +158,9 @@ bitflags! {
const CLICK_IN_PROGRESS = 0x100,
#[doc = "Specifies whether this node has the focus."]
const IN_FOCUS_STATE = 0x200,
+ #[doc = "Specifies whether this node is focusable and whether it is supposed \
+ to be reachable with using sequential focus navigation."]
+ const SEQUENTIALLY_FOCUSABLE = 0x400,
}
}
@@ -173,7 +177,8 @@ impl NodeFlags {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptGroupElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement)) |
//NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMenuItemElement)) |
- NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFieldSetElement)) => IN_ENABLED_STATE | dirty,
+ NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFieldSetElement)) =>
+ IN_ENABLED_STATE | dirty,
_ => dirty,
}
}
@@ -244,7 +249,7 @@ impl LayoutDataRef {
#[inline]
#[allow(unsafe_code)]
pub unsafe fn borrow_unchecked(&self) -> *const Option<LayoutData> {
- mem::transmute(&self.data_cell)
+ self.data_cell.as_unsafe_cell().get() as *const _
}
/// Borrows the layout data immutably. This function is *not* thread-safe.
@@ -422,6 +427,9 @@ pub trait NodeHelpers {
fn child_elements(self) -> ChildElementIterator;
fn following_siblings(self) -> NodeSiblingIterator;
fn preceding_siblings(self) -> ReverseSiblingIterator;
+ fn following_nodes(self, root: JSRef<Node>) -> FollowingNodeIterator;
+ fn preceding_nodes(self, root: JSRef<Node>) -> PrecedingNodeIterator;
+ fn descending_last_children(self) -> LastChildIterator;
fn is_in_doc(self) -> bool;
fn is_inclusive_ancestor_of(self, parent: JSRef<Node>) -> bool;
fn is_parent_of(self, child: JSRef<Node>) -> bool;
@@ -629,7 +637,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn set_hover_state(self, state: bool) {
self.set_flag(IN_HOVER_STATE, state);
- self.dirty(NodeDamage::OtherNodeDamage);
+ self.dirty(NodeDamage::NodeStyleDamaged);
}
fn get_focus_state(self) -> bool {
@@ -638,7 +646,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn set_focus_state(self, state: bool) {
self.set_flag(IN_FOCUS_STATE, state);
- self.dirty(NodeDamage::OtherNodeDamage);
+ self.dirty(NodeDamage::NodeStyleDamaged);
}
fn get_disabled_state(self) -> bool {
@@ -781,6 +789,26 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
}
}
+ fn following_nodes(self, root: JSRef<Node>) -> FollowingNodeIterator {
+ FollowingNodeIterator {
+ current: Some(Temporary::from_rooted(self)),
+ root: Temporary::from_rooted(root),
+ }
+ }
+
+ fn preceding_nodes(self, root: JSRef<Node>) -> PrecedingNodeIterator {
+ PrecedingNodeIterator {
+ current: Some(Temporary::from_rooted(self)),
+ root: Temporary::from_rooted(root),
+ }
+ }
+
+ fn descending_last_children(self) -> LastChildIterator {
+ LastChildIterator {
+ current: self.GetLastChild(),
+ }
+ }
+
fn is_parent_of(self, child: JSRef<Node>) -> bool {
match child.parent_node.get().root() {
Some(ref parent) => parent.r() == self,
@@ -913,15 +941,11 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
// https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
#[allow(unsafe_code)]
fn query_selector_all(self, selectors: DOMString) -> Fallible<Temporary<NodeList>> {
- let mut nodes = RootedVec::new();
- for node in try!(unsafe { self.query_selector_iter(selectors) }) {
- nodes.push(JS::from_rooted(node));
- }
let window = window_from_node(self).root();
- Ok(NodeList::new_simple_list(window.r(), &nodes))
+ let iter = try!(unsafe { self.query_selector_iter(selectors) });
+ Ok(NodeList::new_simple_list(window.r(), iter))
}
-
fn ancestors(self) -> AncestorIterator {
AncestorIterator {
current: self.GetParentNode()
@@ -976,20 +1000,17 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn get_unique_id(self) -> String {
// FIXME(https://github.com/rust-lang/rust/issues/23338)
- let id = self.unique_id.borrow();
- id.clone()
- }
-
- fn summarize(self) -> NodeInfo {
if self.unique_id.borrow().is_empty() {
let mut unique_id = self.unique_id.borrow_mut();
*unique_id = uuid::Uuid::new_v4().to_simple_string();
}
+ let id = self.unique_id.borrow();
+ id.clone()
+ }
- // FIXME(https://github.com/rust-lang/rust/issues/23338)
- let unique_id = self.unique_id.borrow();
+ fn summarize(self) -> NodeInfo {
NodeInfo {
- uniqueId: unique_id.clone(),
+ uniqueId: self.get_unique_id(),
baseURI: self.GetBaseURI().unwrap_or("".to_owned()),
parent: self.GetParentNode().root().map(|node| node.r().get_unique_id()).unwrap_or("".to_owned()),
nodeType: self.NodeType(),
@@ -1238,6 +1259,114 @@ impl Iterator for ReverseSiblingIterator {
}
}
+pub struct FollowingNodeIterator {
+ current: Option<Temporary<Node>>,
+ root: Temporary<Node>,
+}
+
+impl Iterator for FollowingNodeIterator {
+ type Item = Temporary<Node>;
+
+ // https://dom.spec.whatwg.org/#concept-tree-following
+ fn next(&mut self) -> Option<Temporary<Node>> {
+ let current = match self.current.take() {
+ None => return None,
+ Some(current) => current,
+ };
+
+ let node = current.root();
+ if let Some(first_child) = node.r().GetFirstChild() {
+ self.current = Some(first_child);
+ return node.r().GetFirstChild()
+ }
+
+ if self.root == current {
+ self.current = None;
+ return None;
+ }
+
+ if let Some(next_sibling) = node.r().GetNextSibling() {
+ self.current = Some(next_sibling);
+ return node.r().GetNextSibling()
+ }
+
+ for ancestor in node.r().inclusive_ancestors() {
+ if self.root == ancestor {
+ break;
+ }
+ if let Some(next_sibling) = ancestor.root().r().GetNextSibling() {
+ self.current = Some(next_sibling);
+ return ancestor.root().r().GetNextSibling()
+ }
+ }
+ self.current = None;
+ return None
+ }
+}
+
+pub struct PrecedingNodeIterator {
+ current: Option<Temporary<Node>>,
+ root: Temporary<Node>,
+}
+
+impl Iterator for PrecedingNodeIterator {
+ type Item = Temporary<Node>;
+
+ // https://dom.spec.whatwg.org/#concept-tree-preceding
+ fn next(&mut self) -> Option<Temporary<Node>> {
+ let current = match self.current.take() {
+ None => return None,
+ Some(current) => current,
+ };
+
+ if self.root == current {
+ self.current = None;
+ return None
+ }
+
+ let node = current.root();
+ if let Some(previous_sibling) = node.r().GetPreviousSibling() {
+ if self.root == previous_sibling {
+ self.current = None;
+ return None
+ }
+
+ if let Some(last_child) = previous_sibling.root().r().descending_last_children().last() {
+ self.current = Some(last_child);
+ return previous_sibling.root().r().descending_last_children().last()
+ }
+
+ self.current = Some(previous_sibling);
+ return node.r().GetPreviousSibling()
+ };
+
+ if let Some(parent_node) = node.r().GetParentNode() {
+ self.current = Some(parent_node);
+ return node.r().GetParentNode()
+ }
+
+ self.current = None;
+ return None
+ }
+}
+
+pub struct LastChildIterator {
+ current: Option<Temporary<Node>>,
+}
+
+impl Iterator for LastChildIterator {
+ type Item = Temporary<Node>;
+
+ fn next(&mut self) -> Option<Temporary<Node>> {
+ let current = match self.current.take() {
+ None => return None,
+ Some(current) => current,
+ }.root();
+ self.current = current.r().GetLastChild();
+ Some(Temporary::from_rooted(current.r()))
+ }
+}
+
pub struct AncestorIterator {
current: Option<Temporary<Node>>,
}
@@ -1300,7 +1429,6 @@ impl Iterator for TreeIterator {
}
}
-
/// Specifies whether children must be recursively cloned or not.
#[derive(Copy, Clone, PartialEq)]
pub enum CloneChildrenFlag {
@@ -1707,9 +1835,10 @@ impl Node {
false => IsHTMLDocument::NonHTMLDocument,
};
let window = document.window().root();
+ let loader = DocumentLoader::new(&*document.loader());
let document = Document::new(window.r(), Some(document.url()),
is_html_doc, None,
- None, DocumentSource::NotFromParser);
+ None, DocumentSource::NotFromParser, loader);
NodeCast::from_temporary(document)
},
NodeTypeId::Element(..) => {
@@ -1803,13 +1932,20 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
// https://dom.spec.whatwg.org/#dom-node-nodetype
fn NodeType(self) -> u16 {
match self.type_id {
- NodeTypeId::CharacterData(CharacterDataTypeId::Text) => NodeConstants::TEXT_NODE,
- NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => NodeConstants::PROCESSING_INSTRUCTION_NODE,
- NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => NodeConstants::COMMENT_NODE,
- NodeTypeId::Document => NodeConstants::DOCUMENT_NODE,
- NodeTypeId::DocumentType => NodeConstants::DOCUMENT_TYPE_NODE,
- NodeTypeId::DocumentFragment => NodeConstants::DOCUMENT_FRAGMENT_NODE,
- NodeTypeId::Element(_) => NodeConstants::ELEMENT_NODE,
+ NodeTypeId::CharacterData(CharacterDataTypeId::Text) =>
+ NodeConstants::TEXT_NODE,
+ NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) =>
+ NodeConstants::PROCESSING_INSTRUCTION_NODE,
+ NodeTypeId::CharacterData(CharacterDataTypeId::Comment) =>
+ NodeConstants::COMMENT_NODE,
+ NodeTypeId::Document =>
+ NodeConstants::DOCUMENT_NODE,
+ NodeTypeId::DocumentType =>
+ NodeConstants::DOCUMENT_TYPE_NODE,
+ NodeTypeId::DocumentFragment =>
+ NodeConstants::DOCUMENT_FRAGMENT_NODE,
+ NodeTypeId::Element(_) =>
+ NodeConstants::ELEMENT_NODE,
}
}
@@ -2002,7 +2138,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
// Step 4-5.
match node.type_id() {
- NodeTypeId::CharacterData(CharacterDataTypeId::Text) if self.is_document() => return Err(HierarchyRequest),
+ NodeTypeId::CharacterData(CharacterDataTypeId::Text) if self.is_document() =>
+ return Err(HierarchyRequest),
NodeTypeId::DocumentType if !self.is_document() => return Err(HierarchyRequest),
NodeTypeId::DocumentFragment |
NodeTypeId::DocumentType |
@@ -2153,7 +2290,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
match prev_text {
Some(ref text_node) => {
let text_node = text_node.clone().root();
- let prev_characterdata: JSRef<CharacterData> = CharacterDataCast::from_ref(text_node.r());
+ let prev_characterdata: JSRef<CharacterData> =
+ CharacterDataCast::from_ref(text_node.r());
let _ = prev_characterdata.AppendData(characterdata.Data());
self.remove_child(child.r());
},
@@ -2231,13 +2369,18 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
match node.type_id() {
// Step 3.
- NodeTypeId::DocumentType if !is_equal_doctype(this, node) => return false,
- NodeTypeId::Element(..) if !is_equal_element(this, node) => return false,
- NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) if !is_equal_processinginstruction(this, node) => return false,
+ NodeTypeId::DocumentType
+ if !is_equal_doctype(this, node) => return false,
+ NodeTypeId::Element(..)
+ if !is_equal_element(this, node) => return false,
+ NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction)
+ if !is_equal_processinginstruction(this, node) => return false,
NodeTypeId::CharacterData(CharacterDataTypeId::Text) |
- NodeTypeId::CharacterData(CharacterDataTypeId::Comment) if !is_equal_characterdata(this, node) => return false,
+ NodeTypeId::CharacterData(CharacterDataTypeId::Comment)
+ if !is_equal_characterdata(this, node) => return false,
// Step 4.
- NodeTypeId::Element(..) if !is_equal_element_attrs(this, node) => return false,
+ NodeTypeId::Element(..)
+ if !is_equal_element_attrs(this, node) => return false,
_ => ()
}