mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Move all methods on T to JSRef<T> or JS<T> as appropriate.
This commit is contained in:
parent
7daa97c7e5
commit
109410900c
15 changed files with 574 additions and 521 deletions
|
@ -37,10 +37,11 @@ use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementDerived};
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementDerived, TextDerived};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementDerived, TextDerived};
|
||||||
use script::dom::bindings::js::JS;
|
use script::dom::bindings::js::JS;
|
||||||
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
|
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
|
||||||
use script::dom::element::{HTMLLinkElementTypeId};
|
use script::dom::element::{HTMLLinkElementTypeId, LayoutElementHelpers, RawLayoutElementHelpers};
|
||||||
use script::dom::htmliframeelement::HTMLIFrameElement;
|
use script::dom::htmliframeelement::HTMLIFrameElement;
|
||||||
use script::dom::htmlimageelement::HTMLImageElement;
|
use script::dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers};
|
||||||
use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, Node, NodeTypeId, LayoutNodeHelpers};
|
use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, Node, NodeTypeId};
|
||||||
|
use script::dom::node::{LayoutNodeHelpers, RawLayoutNodeHelpers};
|
||||||
use script::dom::text::Text;
|
use script::dom::text::Text;
|
||||||
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
||||||
use servo_util::namespace;
|
use servo_util::namespace;
|
||||||
|
@ -95,7 +96,7 @@ pub trait TLayoutNode {
|
||||||
fail!("not an image!")
|
fail!("not an image!")
|
||||||
}
|
}
|
||||||
let image_element: JS<HTMLImageElement> = self.get_jsmanaged().transmute_copy();
|
let image_element: JS<HTMLImageElement> = self.get_jsmanaged().transmute_copy();
|
||||||
(*image_element.unsafe_get()).image().as_ref().map(|url| (*url).clone())
|
image_element.image().as_ref().map(|url| (*url).clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +164,9 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_id(&self) -> Option<NodeTypeId> {
|
fn type_id(&self) -> Option<NodeTypeId> {
|
||||||
Some(self.node.type_id_for_layout())
|
unsafe {
|
||||||
|
Some(self.node.type_id_for_layout())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> {
|
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> {
|
||||||
|
@ -172,7 +175,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
|
||||||
|
|
||||||
fn first_child(&self) -> Option<LayoutNode<'ln>> {
|
fn first_child(&self) -> Option<LayoutNode<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,19 +224,19 @@ impl<'ln> LayoutNode<'ln> {
|
||||||
impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
|
impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
|
||||||
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
|
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.get().parent_node_ref().map(|node| self.new_with_this_lifetime(node))
|
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prev_sibling(&self) -> Option<LayoutNode<'ln>> {
|
fn prev_sibling(&self) -> Option<LayoutNode<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.get().prev_sibling_ref().map(|node| self.new_with_this_lifetime(node))
|
self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_sibling(&self) -> Option<LayoutNode<'ln>> {
|
fn next_sibling(&self) -> Option<LayoutNode<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.get().next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
|
self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +244,7 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_element(&self) -> LayoutElement<'ln> {
|
fn as_element(&self) -> LayoutElement<'ln> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
assert!(self.node.is_element_for_layout());
|
||||||
let elem: JS<Element> = self.node.transmute_copy();
|
let elem: JS<Element> = self.node.transmute_copy();
|
||||||
let element = &*elem.unsafe_get();
|
let element = &*elem.unsafe_get();
|
||||||
LayoutElement {
|
LayoutElement {
|
||||||
|
@ -258,9 +262,9 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool {
|
fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool {
|
||||||
let element = self.as_element();
|
|
||||||
let name = unsafe {
|
let name = unsafe {
|
||||||
if element.element.html_element_in_html_document_for_layout() {
|
let element: JS<Element> = self.node.transmute_copy();
|
||||||
|
if element.html_element_in_html_document_for_layout() {
|
||||||
attr.lower_name.as_slice()
|
attr.lower_name.as_slice()
|
||||||
} else {
|
} else {
|
||||||
attr.name.as_slice()
|
attr.name.as_slice()
|
||||||
|
@ -268,6 +272,7 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
|
||||||
};
|
};
|
||||||
match attr.namespace {
|
match attr.namespace {
|
||||||
SpecificNamespace(ref ns) => {
|
SpecificNamespace(ref ns) => {
|
||||||
|
let element = self.as_element();
|
||||||
element.get_attr(ns, name)
|
element.get_attr(ns, name)
|
||||||
.map_or(false, |attr| test(attr))
|
.map_or(false, |attr| test(attr))
|
||||||
},
|
},
|
||||||
|
@ -459,7 +464,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,10 +514,10 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
/// 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 == Before || self.pseudo == BeforeBlock {
|
if self.pseudo == Before || self.pseudo == BeforeBlock {
|
||||||
return (*self.get_jsmanaged().unsafe_get()).first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
return self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
(*self.get_jsmanaged().unsafe_get()).next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
|
self.get_jsmanaged().next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over this node's children.
|
/// Returns an iterator over this node's children.
|
||||||
|
@ -527,7 +532,8 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_element(&self) -> ThreadSafeLayoutElement {
|
pub fn as_element(&self) -> ThreadSafeLayoutElement {
|
||||||
unsafe {
|
unsafe {
|
||||||
let elem: JS<Element> = self.node.get_jsmanaged().transmute_copy();
|
assert!(self.get_jsmanaged().is_element_for_layout());
|
||||||
|
let elem: JS<Element> = self.get_jsmanaged().transmute_copy();
|
||||||
let element = elem.unsafe_get();
|
let element = elem.unsafe_get();
|
||||||
// FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on
|
// FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on
|
||||||
// implementations.
|
// implementations.
|
||||||
|
|
|
@ -76,8 +76,115 @@ impl DocumentDerived for EventTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait DocumentHelpers {
|
||||||
|
fn url<'a>(&'a self) -> &'a Url;
|
||||||
|
fn quirks_mode(&self) -> QuirksMode;
|
||||||
|
fn set_quirks_mode(&mut self, mode: QuirksMode);
|
||||||
|
fn set_encoding_name(&mut self, name: DOMString);
|
||||||
|
fn content_changed(&self);
|
||||||
|
fn damage_and_reflow(&self, damage: DocumentDamageLevel);
|
||||||
|
fn wait_until_safe_to_modify_dom(&self);
|
||||||
|
fn unregister_named_element(&mut self, to_unregister: &JSRef<Element>, id: DOMString);
|
||||||
|
fn register_named_element(&mut self, element: &JSRef<Element>, id: DOMString);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DocumentHelpers for JSRef<'a, Document> {
|
||||||
|
fn url<'a>(&'a self) -> &'a Url {
|
||||||
|
&*self.url
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quirks_mode(&self) -> QuirksMode {
|
||||||
|
*self.quirks_mode
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_quirks_mode(&mut self, mode: QuirksMode) {
|
||||||
|
*self.quirks_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_encoding_name(&mut self, name: DOMString) {
|
||||||
|
self.encoding_name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn content_changed(&self) {
|
||||||
|
self.damage_and_reflow(ContentChangedDocumentDamage);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn damage_and_reflow(&self, damage: DocumentDamageLevel) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
self.window.root(&roots).damage_and_reflow(damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait_until_safe_to_modify_dom(&self) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
self.window.root(&roots).wait_until_safe_to_modify_dom();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Remove any existing association between the provided id and any elements in this document.
|
||||||
|
fn unregister_named_element(&mut self,
|
||||||
|
to_unregister: &JSRef<Element>,
|
||||||
|
id: DOMString) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
let mut is_empty = false;
|
||||||
|
match self.idmap.find_mut(&id) {
|
||||||
|
None => {},
|
||||||
|
Some(elements) => {
|
||||||
|
let position = elements.iter()
|
||||||
|
.map(|elem| elem.root(&roots))
|
||||||
|
.position(|element| &*element == to_unregister)
|
||||||
|
.expect("This element should be in registered.");
|
||||||
|
elements.remove(position);
|
||||||
|
is_empty = elements.is_empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_empty {
|
||||||
|
self.idmap.remove(&id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Associate an element present in this document with the provided id.
|
||||||
|
fn register_named_element(&mut self,
|
||||||
|
element: &JSRef<Element>,
|
||||||
|
id: DOMString) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
assert!({
|
||||||
|
let node: &JSRef<Node> = NodeCast::from_ref(element);
|
||||||
|
node.is_in_doc()
|
||||||
|
});
|
||||||
|
|
||||||
|
// FIXME https://github.com/mozilla/rust/issues/13195
|
||||||
|
// Use mangle() when it exists again.
|
||||||
|
let root = self.GetDocumentElement().expect("The element is in the document, so there must be a document element.").root(&roots);
|
||||||
|
match self.idmap.find_mut(&id) {
|
||||||
|
Some(elements) => {
|
||||||
|
let new_node: &JSRef<Node> = NodeCast::from_ref(element);
|
||||||
|
let mut head : uint = 0u;
|
||||||
|
let root: &JSRef<Node> = NodeCast::from_ref(&*root);
|
||||||
|
for node in root.traverse_preorder(&roots) {
|
||||||
|
let elem: Option<&JSRef<Element>> = ElementCast::to_ref(&node);
|
||||||
|
match elem {
|
||||||
|
Some(elem) => {
|
||||||
|
if elements.get(head) == &elem.unrooted() {
|
||||||
|
head = head + 1;
|
||||||
|
}
|
||||||
|
if new_node == &node || head == elements.len() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elements.insert(head, element.unrooted());
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
self.idmap.insert(id, vec!(element.unrooted()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Document {
|
impl Document {
|
||||||
pub fn reflect_document(document: ~Document,
|
pub fn reflect_document(document: ~Document,
|
||||||
window: &JSRef<Window>,
|
window: &JSRef<Window>,
|
||||||
wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~Document) -> JS<Document>)
|
wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~Document) -> JS<Document>)
|
||||||
-> Unrooted<Document> {
|
-> Unrooted<Document> {
|
||||||
|
@ -88,7 +195,7 @@ impl Document {
|
||||||
|
|
||||||
let mut doc_alias = raw_doc.clone();
|
let mut doc_alias = raw_doc.clone();
|
||||||
let node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut doc_alias);
|
let node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut doc_alias);
|
||||||
node.get_mut().set_owner_doc(&*raw_doc);
|
node.set_owner_doc(&*raw_doc);
|
||||||
Unrooted::new_rooted(&*raw_doc)
|
Unrooted::new_rooted(&*raw_doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,100 +238,6 @@ impl Document {
|
||||||
let document = Document::new_inherited(window.unrooted(), url, doctype, content_type);
|
let document = Document::new_inherited(window.unrooted(), url, doctype, content_type);
|
||||||
Document::reflect_document(~document, window, DocumentBinding::Wrap)
|
Document::reflect_document(~document, window, DocumentBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn url<'a>(&'a self) -> &'a Url {
|
|
||||||
&*self.url
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn quirks_mode(&self) -> QuirksMode {
|
|
||||||
*self.quirks_mode
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_quirks_mode(&mut self, mode: QuirksMode) {
|
|
||||||
*self.quirks_mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_encoding_name(&mut self, name: DOMString) {
|
|
||||||
self.encoding_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn content_changed(&self) {
|
|
||||||
self.damage_and_reflow(ContentChangedDocumentDamage);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn damage_and_reflow(&self, damage: DocumentDamageLevel) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
self.window.root(&roots).damage_and_reflow(damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wait_until_safe_to_modify_dom(&self) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
self.window.root(&roots).wait_until_safe_to_modify_dom();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Remove any existing association between the provided id and any elements in this document.
|
|
||||||
pub fn unregister_named_element(&mut self,
|
|
||||||
to_unregister: &JSRef<Element>,
|
|
||||||
id: DOMString) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
let mut is_empty = false;
|
|
||||||
match self.idmap.find_mut(&id) {
|
|
||||||
None => {},
|
|
||||||
Some(elements) => {
|
|
||||||
let position = elements.iter()
|
|
||||||
.map(|elem| elem.root(&roots))
|
|
||||||
.position(|element| &*element == to_unregister)
|
|
||||||
.expect("This element should be in registered.");
|
|
||||||
elements.remove(position);
|
|
||||||
is_empty = elements.is_empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if is_empty {
|
|
||||||
self.idmap.remove(&id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Associate an element present in this document with the provided id.
|
|
||||||
pub fn register_named_element(&mut self,
|
|
||||||
abstract_self: &JSRef<Document>,
|
|
||||||
element: &JSRef<Element>,
|
|
||||||
id: DOMString) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
assert!({
|
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(element);
|
|
||||||
node.is_in_doc()
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME https://github.com/mozilla/rust/issues/13195
|
|
||||||
// Use mangle() when it exists again.
|
|
||||||
let root = abstract_self.GetDocumentElement().expect("The element is in the document, so there must be a document element.").root(&roots);
|
|
||||||
match self.idmap.find_mut(&id) {
|
|
||||||
Some(elements) => {
|
|
||||||
let new_node: &JSRef<Node> = NodeCast::from_ref(element);
|
|
||||||
let mut head : uint = 0u;
|
|
||||||
let root: &JSRef<Node> = NodeCast::from_ref(&*root);
|
|
||||||
for node in root.traverse_preorder(&roots) {
|
|
||||||
let elem: Option<&JSRef<Element>> = ElementCast::to_ref(&node);
|
|
||||||
match elem {
|
|
||||||
Some(elem) => {
|
|
||||||
if elements.get(head) == &elem.unrooted() {
|
|
||||||
head = head + 1;
|
|
||||||
}
|
|
||||||
if new_node == &node || head == elements.len() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elements.insert(head, element.unrooted());
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
self.idmap.insert(id, vec!(element.unrooted()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Reflectable for Document {
|
impl Reflectable for Document {
|
||||||
|
@ -237,12 +250,12 @@ impl Reflectable for Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DocumentHelpers {
|
trait PrivateDocumentHelpers {
|
||||||
fn createNodeList(&self, callback: |node: &JSRef<Node>| -> bool) -> Unrooted<NodeList>;
|
fn createNodeList(&self, callback: |node: &JSRef<Node>| -> bool) -> Unrooted<NodeList>;
|
||||||
fn get_html_element(&self) -> Option<Unrooted<HTMLHtmlElement>>;
|
fn get_html_element(&self) -> Option<Unrooted<HTMLHtmlElement>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DocumentHelpers for JSRef<'a, Document> {
|
impl<'a> PrivateDocumentHelpers for JSRef<'a, Document> {
|
||||||
fn createNodeList(&self, callback: |node: &JSRef<Node>| -> bool) -> Unrooted<NodeList> {
|
fn createNodeList(&self, callback: |node: &JSRef<Node>| -> bool) -> Unrooted<NodeList> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let window = self.window.root(&roots);
|
let window = self.window.root(&roots);
|
||||||
|
@ -354,7 +367,8 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-document-doctype
|
// http://dom.spec.whatwg.org/#dom-document-doctype
|
||||||
fn GetDoctype(&self) -> Option<Unrooted<DocumentType>> {
|
fn GetDoctype(&self) -> Option<Unrooted<DocumentType>> {
|
||||||
self.node.children().find(|child| {
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
node.children().find(|child| {
|
||||||
child.is_doctype()
|
child.is_doctype()
|
||||||
}).map(|node| {
|
}).map(|node| {
|
||||||
let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(&node).unwrap();
|
let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(&node).unwrap();
|
||||||
|
@ -364,7 +378,8 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-document-documentelement
|
// http://dom.spec.whatwg.org/#dom-document-documentelement
|
||||||
fn GetDocumentElement(&self) -> Option<Unrooted<Element>> {
|
fn GetDocumentElement(&self) -> Option<Unrooted<Element>> {
|
||||||
self.node.child_elements().next().map(|elem| Unrooted::new_rooted(&elem))
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
node.child_elements().next().map(|elem| Unrooted::new_rooted(&elem))
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-document-getelementsbytagname
|
// http://dom.spec.whatwg.org/#dom-document-getelementsbytagname
|
||||||
|
@ -544,7 +559,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
root.traverse_preorder(&roots)
|
root.traverse_preorder(&roots)
|
||||||
.find(|node| node.type_id() == ElementNodeTypeId(HTMLTitleElementTypeId))
|
.find(|node| node.type_id() == ElementNodeTypeId(HTMLTitleElementTypeId))
|
||||||
.map(|title_elem| {
|
.map(|title_elem| {
|
||||||
for child in title_elem.deref().children() {
|
for child in title_elem.children() {
|
||||||
if child.is_text() {
|
if child.is_text() {
|
||||||
let text: &JSRef<Text> = TextCast::to_ref(&child).unwrap();
|
let text: &JSRef<Text> = TextCast::to_ref(&child).unwrap();
|
||||||
title.push_str(text.get().characterdata.data.as_slice());
|
title.push_str(text.get().characterdata.data.as_slice());
|
||||||
|
@ -633,8 +648,9 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
match new_body {
|
match new_body {
|
||||||
Some(ref node) => {
|
Some(ref htmlelem) => {
|
||||||
match node.get().element.node.type_id {
|
let node: &JSRef<Node> = NodeCast::from_ref(htmlelem);
|
||||||
|
match node.type_id() {
|
||||||
ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => {}
|
ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => {}
|
||||||
_ => return Err(HierarchyRequest)
|
_ => return Err(HierarchyRequest)
|
||||||
}
|
}
|
||||||
|
@ -676,7 +692,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
|
|
||||||
self.createNodeList(|node| {
|
self.createNodeList(|node| {
|
||||||
if !node.get().is_element() {
|
if !node.is_element() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ use dom::bindings::error::{ErrorResult, Fallible, NamespaceError, InvalidCharact
|
||||||
use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type};
|
use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type};
|
||||||
use dom::clientrect::ClientRect;
|
use dom::clientrect::ClientRect;
|
||||||
use dom::clientrectlist::ClientRectList;
|
use dom::clientrectlist::ClientRectList;
|
||||||
use dom::document::Document;
|
use dom::document::{Document, DocumentHelpers};
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlcollection::HTMLCollection;
|
use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::htmlserializer::serialize;
|
use dom::htmlserializer::serialize;
|
||||||
use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node};
|
use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node};
|
||||||
use dom::node::window_from_node;
|
use dom::node::{window_from_node, LayoutNodeHelpers};
|
||||||
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
||||||
use layout_interface::ContentChangedDocumentDamage;
|
use layout_interface::ContentChangedDocumentDamage;
|
||||||
use layout_interface::MatchSelectorsDocumentDamage;
|
use layout_interface::MatchSelectorsDocumentDamage;
|
||||||
|
@ -157,36 +157,51 @@ impl Element {
|
||||||
let element = Element::new_inherited(ElementTypeId, local_name, namespace, prefix, document.unrooted());
|
let element = Element::new_inherited(ElementTypeId, local_name, namespace, prefix, document.unrooted());
|
||||||
Node::reflect_node(~element, document, ElementBinding::Wrap)
|
Node::reflect_node(~element, document, ElementBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn html_element_in_html_document(&self) -> bool {
|
pub trait RawLayoutElementHelpers {
|
||||||
let roots = RootCollection::new();
|
unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str) -> Option<&'static str>;
|
||||||
self.namespace == namespace::HTML &&
|
}
|
||||||
self.node.owner_doc().root(&roots).is_html_document
|
|
||||||
|
impl RawLayoutElementHelpers for Element {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str)
|
||||||
|
-> Option<&'static str> {
|
||||||
|
self.attrs.iter().find(|attr: & &JS<Attr>| {
|
||||||
|
let attr = attr.unsafe_get();
|
||||||
|
name == (*attr).local_name && (*attr).namespace == *namespace
|
||||||
|
}).map(|attr| {
|
||||||
|
let attr = attr.unsafe_get();
|
||||||
|
cast::transmute((*attr).value.as_slice())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element {
|
pub trait LayoutElementHelpers {
|
||||||
pub unsafe fn html_element_in_html_document_for_layout(&self) -> bool {
|
unsafe fn html_element_in_html_document_for_layout(&self) -> bool;
|
||||||
if self.namespace != namespace::HTML {
|
}
|
||||||
|
|
||||||
|
impl LayoutElementHelpers for JS<Element> {
|
||||||
|
unsafe fn html_element_in_html_document_for_layout(&self) -> bool {
|
||||||
|
if (*self.unsafe_get()).namespace != namespace::HTML {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
let owner_doc: *JS<Document> = self.node.owner_doc_for_layout();
|
let node: JS<Node> = self.transmute_copy();
|
||||||
let owner_doc: **Document = owner_doc as **Document;
|
let owner_doc = node.owner_doc_for_layout().unsafe_get();
|
||||||
(**owner_doc).is_html_document
|
(*owner_doc).is_html_document
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
pub trait ElementHelpers {
|
||||||
pub unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str)
|
fn html_element_in_html_document(&self) -> bool;
|
||||||
-> Option<&'static str> {
|
}
|
||||||
self.attrs.iter().find(|attr: & &JS<Attr>| {
|
|
||||||
// unsafely avoid a borrow because this is accessed by many tasks
|
impl<'a> ElementHelpers for JSRef<'a, Element> {
|
||||||
// during parallel layout
|
fn html_element_in_html_document(&self) -> bool {
|
||||||
let attr: ***Attr = cast::transmute(attr);
|
let roots = RootCollection::new();
|
||||||
name == (***attr).local_name && (***attr).namespace == *namespace
|
let is_html = self.namespace == namespace::HTML;
|
||||||
}).map(|attr| {
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
let attr: **Attr = cast::transmute(attr);
|
is_html && node.owner_doc().root(&roots).is_html_document
|
||||||
cast::transmute((**attr).value.as_slice())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +229,7 @@ pub trait AttributeHandlers {
|
||||||
impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<Unrooted<Attr>> {
|
fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<Unrooted<Attr>> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
if self.get().html_element_in_html_document() {
|
if self.html_element_in_html_document() {
|
||||||
self.get().attrs.iter().map(|attr| attr.root(&roots)).find(|attr| {
|
self.get().attrs.iter().map(|attr| attr.root(&roots)).find(|attr| {
|
||||||
name.to_ascii_lower() == attr.local_name && attr.namespace == namespace
|
name.to_ascii_lower() == attr.local_name && attr.namespace == namespace
|
||||||
}).map(|x| Unrooted::new_rooted(&*x))
|
}).map(|x| Unrooted::new_rooted(&*x))
|
||||||
|
@ -248,7 +263,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
node.wait_until_safe_to_modify_dom();
|
node.wait_until_safe_to_modify_dom();
|
||||||
|
|
||||||
let position: |&JSRef<Attr>| -> bool =
|
let position: |&JSRef<Attr>| -> bool =
|
||||||
if self.get().html_element_in_html_document() {
|
if self.html_element_in_html_document() {
|
||||||
|attr| attr.get().local_name.eq_ignore_ascii_case(local_name)
|
|attr| attr.get().local_name.eq_ignore_ascii_case(local_name)
|
||||||
} else {
|
} else {
|
||||||
|attr| attr.get().local_name == local_name
|
|attr| attr.get().local_name == local_name
|
||||||
|
@ -453,7 +468,10 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
Some(ref list) => return Unrooted::new(list.clone()),
|
Some(ref list) => return Unrooted::new(list.clone()),
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = self.node.owner_doc().root(&roots);
|
let doc = {
|
||||||
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
node.owner_doc()
|
||||||
|
}.root(&roots);
|
||||||
let window = doc.deref().window.root(&roots);
|
let window = doc.deref().window.root(&roots);
|
||||||
let list = AttrList::new(&*window, self);
|
let list = AttrList::new(&*window, self);
|
||||||
self.attr_list.assign(Some(list));
|
self.attr_list.assign(Some(list));
|
||||||
|
@ -463,7 +481,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
// http://dom.spec.whatwg.org/#dom-element-getattribute
|
// http://dom.spec.whatwg.org/#dom-element-getattribute
|
||||||
fn GetAttribute(&self, name: DOMString) -> Option<DOMString> {
|
fn GetAttribute(&self, name: DOMString) -> Option<DOMString> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let name = if self.get().html_element_in_html_document() {
|
let name = if self.html_element_in_html_document() {
|
||||||
name.to_ascii_lower()
|
name.to_ascii_lower()
|
||||||
} else {
|
} else {
|
||||||
name
|
name
|
||||||
|
@ -488,7 +506,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
value: DOMString) -> ErrorResult {
|
value: DOMString) -> ErrorResult {
|
||||||
{
|
{
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
node.get().wait_until_safe_to_modify_dom();
|
node.wait_until_safe_to_modify_dom();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
|
@ -498,7 +516,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let name = if self.get().html_element_in_html_document() {
|
let name = if self.html_element_in_html_document() {
|
||||||
name.to_ascii_lower()
|
name.to_ascii_lower()
|
||||||
} else {
|
} else {
|
||||||
name
|
name
|
||||||
|
@ -518,7 +536,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
value: DOMString) -> ErrorResult {
|
value: DOMString) -> ErrorResult {
|
||||||
{
|
{
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
node.get().wait_until_safe_to_modify_dom();
|
node.wait_until_safe_to_modify_dom();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
|
@ -707,15 +725,14 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
||||||
match name.as_slice() {
|
match name.as_slice() {
|
||||||
"style" => {
|
"style" => {
|
||||||
let doc = document_from_node(self).root(&roots);
|
let doc = document_from_node(self).root(&roots);
|
||||||
let base_url = doc.get().url().clone();
|
let base_url = doc.deref().url().clone();
|
||||||
self.get_mut().style_attribute = Some(style::parse_style_attribute(value, &base_url))
|
self.get_mut().style_attribute = Some(style::parse_style_attribute(value, &base_url))
|
||||||
}
|
}
|
||||||
"id" => {
|
"id" => {
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
if node.is_in_doc() {
|
if node.is_in_doc() {
|
||||||
let mut doc = document_from_node(self).root(&roots);
|
let mut doc = document_from_node(self).root(&roots);
|
||||||
let doc_alias = (*doc).clone();
|
doc.register_named_element(self, value.clone());
|
||||||
doc.register_named_element(&doc_alias, self, value.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
|
@ -758,8 +775,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
||||||
match self.get_attribute(Null, "id").root(&roots) {
|
match self.get_attribute(Null, "id").root(&roots) {
|
||||||
Some(attr) => {
|
Some(attr) => {
|
||||||
let mut doc = document_from_node(self).root(&roots);
|
let mut doc = document_from_node(self).root(&roots);
|
||||||
let doc_alias = (*doc).clone();
|
doc.register_named_element(self, attr.deref().Value());
|
||||||
doc.register_named_element(&doc_alias, self, attr.deref().Value());
|
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use dom::element::HTMLButtonElementTypeId;
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlformelement::HTMLFormElement;
|
use dom::htmlformelement::HTMLFormElement;
|
||||||
use dom::node::{Node, ElementNodeTypeId};
|
use dom::node::{Node, ElementNodeTypeId, window_from_node};
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::ValidityState;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
|
@ -168,8 +168,8 @@ impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
|
||||||
|
|
||||||
fn Validity(&self) -> Unrooted<ValidityState> {
|
fn Validity(&self) -> Unrooted<ValidityState> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let doc = self.htmlelement.element.node.owner_doc().root(&roots);
|
let window = window_from_node(self).root(&roots);
|
||||||
ValidityState::new(&*doc.deref().window.root(&roots))
|
ValidityState::new(&*window)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetValidity(&mut self, _validity: JS<ValidityState>) {
|
fn SetValidity(&mut self, _validity: JS<ValidityState>) {
|
||||||
|
|
|
@ -107,8 +107,7 @@ impl<'a> HTMLFieldSetElementMethods for JSRef<'a, HTMLFieldSetElement> {
|
||||||
|
|
||||||
fn Validity(&self) -> Unrooted<ValidityState> {
|
fn Validity(&self) -> Unrooted<ValidityState> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let doc = self.htmlelement.element.node.owner_doc().root(&roots);
|
let window = window_from_node(self).root(&roots);
|
||||||
let window = doc.deref().window.root(&roots);
|
|
||||||
ValidityState::new(&*window)
|
ValidityState::new(&*window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use dom::element::{Element, HTMLFormElementTypeId};
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlcollection::{HTMLCollection, Static};
|
use dom::htmlcollection::{HTMLCollection, Static};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::{Node, ElementNodeTypeId};
|
use dom::node::{Node, ElementNodeTypeId, window_from_node};
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
#[deriving(Encodable)]
|
#[deriving(Encodable)]
|
||||||
|
@ -144,8 +144,7 @@ impl<'a> HTMLFormElementMethods for JSRef<'a, HTMLFormElement> {
|
||||||
fn Elements(&self) -> Unrooted<HTMLCollection> {
|
fn Elements(&self) -> Unrooted<HTMLCollection> {
|
||||||
// FIXME: https://github.com/mozilla/servo/issues/1844
|
// FIXME: https://github.com/mozilla/servo/issues/1844
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let doc = self.htmlelement.element.node.owner_doc().root(&roots);
|
let window = window_from_node(self).root(&roots);
|
||||||
let window = doc.deref().window.root(&roots);
|
|
||||||
HTMLCollection::new(&*window, Static(vec!()))
|
HTMLCollection::new(&*window, Static(vec!()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,12 +54,17 @@ pub struct IFrameSize {
|
||||||
pub subpage_id: SubpageId,
|
pub subpage_id: SubpageId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLIFrameElement {
|
pub trait HTMLIFrameElementHelpers {
|
||||||
pub fn is_sandboxed(&self) -> bool {
|
fn is_sandboxed(&self) -> bool;
|
||||||
|
fn set_frame(&mut self, frame: Url);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
||||||
|
fn is_sandboxed(&self) -> bool {
|
||||||
self.sandbox.is_some()
|
self.sandbox.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_frame(&mut self, frame: Url) {
|
fn set_frame(&mut self, frame: Url) {
|
||||||
*self.frame = Some(frame);
|
*self.frame = Some(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,29 +35,18 @@ impl HTMLImageElementDerived for EventTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLImageElement {
|
trait PrivateHTMLImageElementHelpers {
|
||||||
pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLImageElement {
|
fn update_image(&mut self, value: Option<DOMString>, url: Option<Url>);
|
||||||
HTMLImageElement {
|
}
|
||||||
htmlelement: HTMLElement::new_inherited(HTMLImageElementTypeId, localName, document),
|
|
||||||
image: Untraceable::new(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLImageElement> {
|
|
||||||
let element = HTMLImageElement::new_inherited(localName, document.unrooted());
|
|
||||||
Node::reflect_node(~element, document, HTMLImageElementBinding::Wrap)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn image<'a>(&'a self) -> &'a Option<Url> {
|
|
||||||
&*self.image
|
|
||||||
}
|
|
||||||
|
|
||||||
|
impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
|
||||||
/// Makes the local `image` member match the status of the `src` attribute and starts
|
/// Makes the local `image` member match the status of the `src` attribute and starts
|
||||||
/// prefetching the image. This method must be called after `src` is changed.
|
/// prefetching the image. This method must be called after `src` is changed.
|
||||||
fn update_image(&mut self, value: Option<DOMString>, url: Option<Url>) {
|
fn update_image(&mut self, value: Option<DOMString>, url: Option<Url>) {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let elem = &mut self.htmlelement.element;
|
let self_alias = self.clone();
|
||||||
let document = elem.node.owner_doc().root(&roots);
|
let node_alias: &JSRef<Node> = NodeCast::from_ref(&self_alias);
|
||||||
|
let document = node_alias.owner_doc().root(&roots);
|
||||||
let window = document.deref().window.root(&roots);
|
let window = document.deref().window.root(&roots);
|
||||||
let image_cache = &window.image_cache_task;
|
let image_cache = &window.image_cache_task;
|
||||||
match value {
|
match value {
|
||||||
|
@ -79,6 +68,30 @@ impl HTMLImageElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HTMLImageElement {
|
||||||
|
pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLImageElement {
|
||||||
|
HTMLImageElement {
|
||||||
|
htmlelement: HTMLElement::new_inherited(HTMLImageElementTypeId, localName, document),
|
||||||
|
image: Untraceable::new(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(localName: DOMString, document: &JSRef<Document>) -> Unrooted<HTMLImageElement> {
|
||||||
|
let element = HTMLImageElement::new_inherited(localName, document.unrooted());
|
||||||
|
Node::reflect_node(~element, document, HTMLImageElementBinding::Wrap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LayoutHTMLImageElementHelpers {
|
||||||
|
unsafe fn image<'a>(&'a self) -> &'a Option<Url>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutHTMLImageElementHelpers for JS<HTMLImageElement> {
|
||||||
|
unsafe fn image<'a>(&'a self) -> &'a Option<Url> {
|
||||||
|
&*(*self.unsafe_get()).image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait HTMLImageElementMethods {
|
pub trait HTMLImageElementMethods {
|
||||||
fn Alt(&self) -> DOMString;
|
fn Alt(&self) -> DOMString;
|
||||||
fn SetAlt(&mut self, alt: DOMString);
|
fn SetAlt(&mut self, alt: DOMString);
|
||||||
|
@ -271,7 +284,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
|
||||||
if "src" == name {
|
if "src" == name {
|
||||||
let window = window_from_node(self).root(&roots);
|
let window = window_from_node(self).root(&roots);
|
||||||
let url = Some(window.get().get_url());
|
let url = Some(window.get().get_url());
|
||||||
self.get_mut().update_image(Some(value), url);
|
self.update_image(Some(value), url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +295,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if "src" == name {
|
if "src" == name {
|
||||||
self.get_mut().update_image(None, None);
|
self.update_image(None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use dom::element::HTMLMapElementTypeId;
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlcollection::{HTMLCollection, Static};
|
use dom::htmlcollection::{HTMLCollection, Static};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::{Node, ElementNodeTypeId};
|
use dom::node::{Node, ElementNodeTypeId, window_from_node};
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
#[deriving(Encodable)]
|
#[deriving(Encodable)]
|
||||||
|
@ -59,8 +59,7 @@ impl<'a> HTMLMapElementMethods for JSRef<'a, HTMLMapElement> {
|
||||||
fn Areas(&self) -> Unrooted<HTMLCollection> {
|
fn Areas(&self) -> Unrooted<HTMLCollection> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
// FIXME: https://github.com/mozilla/servo/issues/1845
|
// FIXME: https://github.com/mozilla/servo/issues/1845
|
||||||
let doc = self.htmlelement.element.node.owner_doc().root(&roots);
|
let window = window_from_node(self).root(&roots);
|
||||||
let window = doc.deref().window.root(&roots);
|
|
||||||
HTMLCollection::new(&*window, Static(vec!()))
|
HTMLCollection::new(&*window, Static(vec!()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,9 +191,8 @@ impl<'a> HTMLObjectElementMethods for JSRef<'a, HTMLObjectElement> {
|
||||||
|
|
||||||
fn Validity(&self) -> Unrooted<ValidityState> {
|
fn Validity(&self) -> Unrooted<ValidityState> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let doc = self.htmlelement.element.node.owner_doc().root(&roots);
|
let window = window_from_node(self).root(&roots);
|
||||||
let window = doc.deref().window.root(&roots);
|
ValidityState::new(&*window)
|
||||||
ValidityState::new(&window.root_ref())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ValidationMessage(&self) -> DOMString {
|
fn ValidationMessage(&self) -> DOMString {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use dom::element::HTMLOutputElementTypeId;
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlformelement::HTMLFormElement;
|
use dom::htmlformelement::HTMLFormElement;
|
||||||
use dom::node::{Node, ElementNodeTypeId};
|
use dom::node::{Node, ElementNodeTypeId, window_from_node};
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::ValidityState;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
|
@ -103,8 +103,7 @@ impl<'a> HTMLOutputElementMethods for JSRef<'a, HTMLOutputElement> {
|
||||||
|
|
||||||
fn Validity(&self) -> Unrooted<ValidityState> {
|
fn Validity(&self) -> Unrooted<ValidityState> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let doc = self.htmlelement.element.node.owner_doc().root(&roots);
|
let window = window_from_node(self).root(&roots);
|
||||||
let window = doc.deref().window.root(&roots);
|
|
||||||
ValidityState::new(&*window)
|
ValidityState::new(&*window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ use dom::element::{Element, HTMLSelectElementTypeId};
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlformelement::HTMLFormElement;
|
use dom::htmlformelement::HTMLFormElement;
|
||||||
use dom::node::{Node, ElementNodeTypeId};
|
use dom::node::{Node, ElementNodeTypeId, window_from_node};
|
||||||
use dom::htmloptionelement::HTMLOptionElement;
|
use dom::htmloptionelement::HTMLOptionElement;
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::ValidityState;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
@ -193,8 +193,7 @@ impl<'a> HTMLSelectElementMethods for JSRef<'a, HTMLSelectElement> {
|
||||||
|
|
||||||
fn Validity(&self) -> Unrooted<ValidityState> {
|
fn Validity(&self) -> Unrooted<ValidityState> {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let doc = self.htmlelement.element.node.owner_doc().root(&roots);
|
let window = window_from_node(self).root(&roots);
|
||||||
let window = doc.deref().window.root(&roots);
|
|
||||||
ValidityState::new(&*window)
|
ValidityState::new(&*window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTypeCast};
|
use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTypeCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast, ElementDerived};
|
||||||
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived};
|
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived};
|
||||||
use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast};
|
use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast};
|
||||||
use dom::bindings::codegen::BindingDeclarations::NodeBinding::NodeConstants;
|
use dom::bindings::codegen::BindingDeclarations::NodeBinding::NodeConstants;
|
||||||
|
@ -18,7 +18,7 @@ use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest};
|
||||||
use dom::bindings::utils;
|
use dom::bindings::utils;
|
||||||
use dom::characterdata::{CharacterData, CharacterDataMethods};
|
use dom::characterdata::{CharacterData, CharacterDataMethods};
|
||||||
use dom::comment::Comment;
|
use dom::comment::Comment;
|
||||||
use dom::document::{Document, DocumentMethods, HTMLDocument, NonHTMLDocument};
|
use dom::document::{Document, DocumentMethods, DocumentHelpers, HTMLDocument, NonHTMLDocument};
|
||||||
use dom::documentfragment::DocumentFragment;
|
use dom::documentfragment::DocumentFragment;
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
use dom::element::{Element, ElementMethods, ElementTypeId, HTMLAnchorElementTypeId};
|
use dom::element::{Element, ElementMethods, ElementTypeId, HTMLAnchorElementTypeId};
|
||||||
|
@ -224,6 +224,174 @@ pub enum NodeTypeId {
|
||||||
ProcessingInstructionNodeTypeId,
|
ProcessingInstructionNodeTypeId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait PrivateNodeHelpers {
|
||||||
|
fn set_parent_node(&mut self, new_parent_node: Option<JSRef<Node>>);
|
||||||
|
fn set_first_child(&mut self, new_first_child: Option<JSRef<Node>>);
|
||||||
|
fn set_last_child(&mut self, new_last_child: Option<JSRef<Node>>);
|
||||||
|
fn set_prev_sibling(&mut self, new_prev_sibling: Option<JSRef<Node>>);
|
||||||
|
fn set_next_sibling(&mut self, new_next_sibling: Option<JSRef<Node>>);
|
||||||
|
|
||||||
|
fn node_inserted(&self);
|
||||||
|
fn node_removed(&self);
|
||||||
|
fn add_child(&mut self, new_child: &mut JSRef<Node>, before: Option<JSRef<Node>>);
|
||||||
|
fn remove_child(&mut self, child: &mut JSRef<Node>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
|
||||||
|
// http://dom.spec.whatwg.org/#node-is-inserted
|
||||||
|
fn node_inserted(&self) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
assert!(self.parent_node().is_some());
|
||||||
|
let document = document_from_node(self).root(&roots);
|
||||||
|
|
||||||
|
if self.is_in_doc() {
|
||||||
|
for node in self.traverse_preorder(&roots) {
|
||||||
|
vtable_for(&node).bind_to_tree();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.parent_node().root(&roots)
|
||||||
|
.map(|parent| vtable_for(&*parent).child_inserted(self));
|
||||||
|
|
||||||
|
document.deref().content_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://dom.spec.whatwg.org/#node-is-removed
|
||||||
|
fn node_removed(&self) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
assert!(self.parent_node().is_none());
|
||||||
|
let document = document_from_node(self).root(&roots);
|
||||||
|
|
||||||
|
for node in self.traverse_preorder(&roots) {
|
||||||
|
// XXX how about if the node wasn't in the tree in the first place?
|
||||||
|
vtable_for(&node).unbind_from_tree();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.deref().content_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pointer stitching
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Adds a new child to the end of this node's list of children.
|
||||||
|
///
|
||||||
|
/// Fails unless `new_child` is disconnected from the tree.
|
||||||
|
fn add_child(&mut self, new_child: &mut JSRef<Node>, mut before: Option<JSRef<Node>>) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
assert!(new_child.parent_node().is_none());
|
||||||
|
assert!(new_child.prev_sibling().is_none());
|
||||||
|
assert!(new_child.next_sibling().is_none());
|
||||||
|
match before {
|
||||||
|
Some(ref mut before) => {
|
||||||
|
// XXX Should assert that parent is self.
|
||||||
|
assert!(before.parent_node().is_some());
|
||||||
|
match before.prev_sibling() {
|
||||||
|
None => {
|
||||||
|
// XXX Should assert that before is the first child of
|
||||||
|
// self.
|
||||||
|
self.set_first_child(Some(new_child.clone()));
|
||||||
|
},
|
||||||
|
Some(prev_sibling) => {
|
||||||
|
let mut prev_sibling = prev_sibling.root(&roots);
|
||||||
|
prev_sibling.set_next_sibling(Some(new_child.clone()));
|
||||||
|
new_child.set_prev_sibling(Some((*prev_sibling).clone()));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
before.set_prev_sibling(Some(new_child.clone()));
|
||||||
|
new_child.set_next_sibling(Some(before.clone()));
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
match self.last_child().map(|child| child.root(&roots)) {
|
||||||
|
None => self.set_first_child(Some(new_child.clone())),
|
||||||
|
Some(mut last_child) => {
|
||||||
|
assert!(last_child.next_sibling().is_none());
|
||||||
|
last_child.set_next_sibling(Some(new_child.clone()));
|
||||||
|
new_child.set_prev_sibling(Some((*last_child).clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.set_last_child(Some(new_child.clone()));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
new_child.set_parent_node(Some(self.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the given child from this node's list of children.
|
||||||
|
///
|
||||||
|
/// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
|
||||||
|
fn remove_child(&mut self, child: &mut JSRef<Node>) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
assert!(child.parent_node.is_some());
|
||||||
|
|
||||||
|
match child.prev_sibling.root(&roots) {
|
||||||
|
None => {
|
||||||
|
let next_sibling = child.next_sibling.as_ref().map(|next| next.root(&roots));
|
||||||
|
self.set_first_child(next_sibling.root_ref());
|
||||||
|
}
|
||||||
|
Some(ref mut prev_sibling) => {
|
||||||
|
let next_sibling = child.next_sibling.as_ref().map(|next| next.root(&roots));
|
||||||
|
prev_sibling.set_next_sibling(next_sibling.root_ref());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match child.next_sibling.root(&roots) {
|
||||||
|
None => {
|
||||||
|
let prev_sibling = child.prev_sibling.as_ref().map(|prev| prev.root(&roots));
|
||||||
|
self.set_last_child(prev_sibling.root_ref());
|
||||||
|
}
|
||||||
|
Some(ref mut next_sibling) => {
|
||||||
|
let prev_sibling = child.prev_sibling.as_ref().map(|prev| prev.root(&roots));
|
||||||
|
next_sibling.set_prev_sibling(prev_sibling.root_ref());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
child.set_prev_sibling(None);
|
||||||
|
child.set_next_sibling(None);
|
||||||
|
child.set_parent_node(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Low-level pointer stitching
|
||||||
|
//
|
||||||
|
|
||||||
|
fn set_parent_node(&mut self, new_parent_node: Option<JSRef<Node>>) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
let doc = self.owner_doc().root(&roots);
|
||||||
|
doc.deref().wait_until_safe_to_modify_dom();
|
||||||
|
self.parent_node.assign(new_parent_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_first_child(&mut self, new_first_child: Option<JSRef<Node>>) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
let doc = self.owner_doc().root(&roots);
|
||||||
|
doc.deref().wait_until_safe_to_modify_dom();
|
||||||
|
self.first_child.assign(new_first_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_last_child(&mut self, new_last_child: Option<JSRef<Node>>) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
let doc = self.owner_doc().root(&roots);
|
||||||
|
doc.deref().wait_until_safe_to_modify_dom();
|
||||||
|
self.last_child.assign(new_last_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_prev_sibling(&mut self, new_prev_sibling: Option<JSRef<Node>>) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
let doc = self.owner_doc().root(&roots);
|
||||||
|
doc.deref().wait_until_safe_to_modify_dom();
|
||||||
|
self.prev_sibling.assign(new_prev_sibling);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_next_sibling(&mut self, new_next_sibling: Option<JSRef<Node>>) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
let doc = self.owner_doc().root(&roots);
|
||||||
|
doc.deref().wait_until_safe_to_modify_dom();
|
||||||
|
self.next_sibling.assign(new_next_sibling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait NodeHelpers {
|
pub trait NodeHelpers {
|
||||||
fn ancestors(&self) -> AncestorIterator;
|
fn ancestors(&self) -> AncestorIterator;
|
||||||
fn children(&self) -> AbstractNodeChildrenIterator;
|
fn children(&self) -> AbstractNodeChildrenIterator;
|
||||||
|
@ -241,17 +409,17 @@ pub trait NodeHelpers {
|
||||||
fn prev_sibling(&self) -> Option<Unrooted<Node>>;
|
fn prev_sibling(&self) -> Option<Unrooted<Node>>;
|
||||||
fn next_sibling(&self) -> Option<Unrooted<Node>>;
|
fn next_sibling(&self) -> Option<Unrooted<Node>>;
|
||||||
|
|
||||||
|
fn owner_doc(&self) -> Unrooted<Document>;
|
||||||
|
fn set_owner_doc(&mut self, document: &JSRef<Document>);
|
||||||
|
|
||||||
|
fn wait_until_safe_to_modify_dom(&self);
|
||||||
|
|
||||||
fn is_element(&self) -> bool;
|
fn is_element(&self) -> bool;
|
||||||
fn is_document(&self) -> bool;
|
fn is_document(&self) -> bool;
|
||||||
fn is_doctype(&self) -> bool;
|
fn is_doctype(&self) -> bool;
|
||||||
fn is_text(&self) -> bool;
|
fn is_text(&self) -> bool;
|
||||||
fn is_anchor_element(&self) -> bool;
|
fn is_anchor_element(&self) -> bool;
|
||||||
|
|
||||||
fn node_inserted(&self);
|
|
||||||
fn node_removed(&self);
|
|
||||||
fn add_child(&mut self, new_child: &mut JSRef<Node>, before: Option<JSRef<Node>>);
|
|
||||||
fn remove_child(&mut self, child: &mut JSRef<Node>);
|
|
||||||
|
|
||||||
fn get_hover_state(&self) -> bool;
|
fn get_hover_state(&self) -> bool;
|
||||||
fn set_hover_state(&mut self, state: bool);
|
fn set_hover_state(&mut self, state: bool);
|
||||||
|
|
||||||
|
@ -296,19 +464,6 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
||||||
format!("{:?}", self.type_id())
|
format!("{:?}", self.type_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over all ancestors of this node.
|
|
||||||
fn ancestors(&self) -> AncestorIterator {
|
|
||||||
self.get().ancestors()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn children(&self) -> AbstractNodeChildrenIterator {
|
|
||||||
self.get().children()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn child_elements(&self) -> ChildElementIterator {
|
|
||||||
self.get().child_elements()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_in_doc(&self) -> bool {
|
fn is_in_doc(&self) -> bool {
|
||||||
self.get().flags.is_in_doc()
|
self.get().flags.is_in_doc()
|
||||||
}
|
}
|
||||||
|
@ -342,7 +497,10 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_element(&self) -> bool {
|
fn is_element(&self) -> bool {
|
||||||
self.get().is_element()
|
match self.type_id {
|
||||||
|
ElementNodeTypeId(..) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -363,7 +521,10 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_doctype(&self) -> bool {
|
fn is_doctype(&self) -> bool {
|
||||||
self.get().is_doctype()
|
match self.type_id {
|
||||||
|
DoctypeNodeTypeId => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -376,127 +537,12 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#node-is-inserted
|
|
||||||
fn node_inserted(&self) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
assert!(self.parent_node().is_some());
|
|
||||||
let document = document_from_node(self).root(&roots);
|
|
||||||
|
|
||||||
if self.is_in_doc() {
|
|
||||||
for node in self.traverse_preorder(&roots) {
|
|
||||||
vtable_for(&node).bind_to_tree();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.parent_node().root(&roots)
|
|
||||||
.map(|parent| vtable_for(&*parent).child_inserted(self));
|
|
||||||
document.get().content_changed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#node-is-removed
|
|
||||||
fn node_removed(&self) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
assert!(self.parent_node().is_none());
|
|
||||||
let document = document_from_node(self).root(&roots);
|
|
||||||
|
|
||||||
for node in self.traverse_preorder(&roots) {
|
|
||||||
// XXX how about if the node wasn't in the tree in the first place?
|
|
||||||
vtable_for(&node).unbind_from_tree();
|
|
||||||
}
|
|
||||||
|
|
||||||
document.get().content_changed();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Pointer stitching
|
|
||||||
//
|
|
||||||
|
|
||||||
/// Adds a new child to the end of this node's list of children.
|
|
||||||
///
|
|
||||||
/// Fails unless `new_child` is disconnected from the tree.
|
|
||||||
fn add_child(&mut self, new_child: &mut JSRef<Node>, mut before: Option<JSRef<Node>>) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
assert!(new_child.parent_node().is_none());
|
|
||||||
assert!(new_child.prev_sibling().is_none());
|
|
||||||
assert!(new_child.next_sibling().is_none());
|
|
||||||
match before {
|
|
||||||
Some(ref mut before) => {
|
|
||||||
// XXX Should assert that parent is self.
|
|
||||||
assert!(before.parent_node().is_some());
|
|
||||||
match before.prev_sibling() {
|
|
||||||
None => {
|
|
||||||
// XXX Should assert that before is the first child of
|
|
||||||
// self.
|
|
||||||
self.get_mut().set_first_child(Some(new_child.clone()));
|
|
||||||
},
|
|
||||||
Some(prev_sibling) => {
|
|
||||||
let mut prev_sibling = prev_sibling.root(&roots);
|
|
||||||
prev_sibling.get_mut().set_next_sibling(Some(new_child.clone()));
|
|
||||||
new_child.get_mut().set_prev_sibling(Some((*prev_sibling).clone()));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
before.get_mut().set_prev_sibling(Some(new_child.clone()));
|
|
||||||
new_child.get_mut().set_next_sibling(Some(before.clone()));
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
match self.last_child().map(|child| child.root(&roots)) {
|
|
||||||
None => self.get_mut().set_first_child(Some(new_child.clone())),
|
|
||||||
Some(mut last_child) => {
|
|
||||||
assert!(last_child.next_sibling().is_none());
|
|
||||||
last_child.get_mut().set_next_sibling(Some(new_child.clone()));
|
|
||||||
new_child.get_mut().set_prev_sibling(Some((*last_child).clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.get_mut().set_last_child(Some(new_child.clone()));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
new_child.get_mut().set_parent_node(Some(self.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Removes the given child from this node's list of children.
|
|
||||||
///
|
|
||||||
/// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
|
|
||||||
fn remove_child(&mut self, child: &mut JSRef<Node>) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
let this_node = self.get_mut();
|
|
||||||
let child_node = child.get_mut();
|
|
||||||
assert!(child_node.parent_node.is_some());
|
|
||||||
|
|
||||||
match child_node.prev_sibling.root(&roots) {
|
|
||||||
None => {
|
|
||||||
let next_sibling = child_node.next_sibling.as_ref().map(|next| next.root(&roots));
|
|
||||||
this_node.set_first_child(next_sibling.root_ref());
|
|
||||||
}
|
|
||||||
Some(ref mut prev_sibling) => {
|
|
||||||
let next_sibling = child_node.next_sibling.as_ref().map(|next| next.root(&roots));
|
|
||||||
prev_sibling.set_next_sibling(next_sibling.root_ref());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match child_node.next_sibling.root(&roots) {
|
|
||||||
None => {
|
|
||||||
let prev_sibling = child_node.prev_sibling.as_ref().map(|prev| prev.root(&roots));
|
|
||||||
this_node.set_last_child(prev_sibling.root_ref());
|
|
||||||
}
|
|
||||||
Some(ref mut next_sibling) => {
|
|
||||||
let prev_sibling = child_node.prev_sibling.as_ref().map(|prev| prev.root(&roots));
|
|
||||||
next_sibling.set_prev_sibling(prev_sibling.root_ref());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
child_node.set_prev_sibling(None);
|
|
||||||
child_node.set_next_sibling(None);
|
|
||||||
child_node.set_parent_node(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_hover_state(&self) -> bool {
|
fn get_hover_state(&self) -> bool {
|
||||||
self.get().flags.get_in_hover_state()
|
self.flags.get_in_hover_state()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_hover_state(&mut self, state: bool) {
|
fn set_hover_state(&mut self, state: bool) {
|
||||||
self.get_mut().flags.set_is_in_hover_state(state);
|
self.flags.set_is_in_hover_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over this node and all its descendants, in preorder.
|
/// Iterates over this node and all its descendants, in preorder.
|
||||||
|
@ -563,6 +609,48 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
||||||
let ContentBoxesResponse(rects) = page.query_layout(ContentBoxesQuery(addr, chan), port);
|
let ContentBoxesResponse(rects) = page.query_layout(ContentBoxesQuery(addr, chan), port);
|
||||||
rects
|
rects
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ancestors(&self) -> AncestorIterator {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
AncestorIterator {
|
||||||
|
current: self.parent_node.clone().map(|node| (*node.root(&roots)).clone()),
|
||||||
|
roots: roots,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn owner_doc(&self) -> Unrooted<Document> {
|
||||||
|
Unrooted::new(self.owner_doc.get_ref().clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_owner_doc(&mut self, document: &JSRef<Document>) {
|
||||||
|
self.owner_doc = Some(document.unrooted());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn children(&self) -> AbstractNodeChildrenIterator {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
AbstractNodeChildrenIterator {
|
||||||
|
current_node: self.first_child.clone().map(|node| (*node.root(&roots)).clone()),
|
||||||
|
roots: roots,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn child_elements(&self) -> ChildElementIterator {
|
||||||
|
self.children()
|
||||||
|
.filter(|node| {
|
||||||
|
node.is_element()
|
||||||
|
})
|
||||||
|
.map(|node| {
|
||||||
|
let elem: &JSRef<Element> = ElementCast::to_ref(&node).unwrap();
|
||||||
|
elem.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait_until_safe_to_modify_dom(&self) {
|
||||||
|
let roots = RootCollection::new();
|
||||||
|
let document = self.owner_doc().root(&roots);
|
||||||
|
document.deref().wait_until_safe_to_modify_dom();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the given untrusted node address represents a valid DOM node in the given runtime,
|
/// If the given untrusted node address represents a valid DOM node in the given runtime,
|
||||||
|
@ -582,19 +670,69 @@ pub fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNode
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait LayoutNodeHelpers {
|
pub trait LayoutNodeHelpers {
|
||||||
fn type_id_for_layout(&self) -> NodeTypeId;
|
unsafe fn type_id_for_layout(&self) -> NodeTypeId;
|
||||||
|
|
||||||
|
unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
|
||||||
|
unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
|
||||||
|
unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
|
||||||
|
unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
|
||||||
|
unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
|
||||||
|
|
||||||
|
unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document>;
|
||||||
|
|
||||||
|
unsafe fn is_element_for_layout(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutNodeHelpers for JS<Node> {
|
impl LayoutNodeHelpers for JS<Node> {
|
||||||
fn type_id_for_layout(&self) -> NodeTypeId {
|
unsafe fn type_id_for_layout(&self) -> NodeTypeId {
|
||||||
unsafe {
|
(*self.unsafe_get()).type_id
|
||||||
let node: **Node = cast::transmute::<*JS<Node>,
|
}
|
||||||
**Node>(self);
|
|
||||||
(**node).type_id
|
unsafe fn is_element_for_layout(&self) -> bool {
|
||||||
}
|
(*self.unsafe_get()).is_element()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
||||||
|
(*self.unsafe_get()).parent_node.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
||||||
|
(*self.unsafe_get()).first_child.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
||||||
|
(*self.unsafe_get()).last_child.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
||||||
|
(*self.unsafe_get()).prev_sibling.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
||||||
|
(*self.unsafe_get()).next_sibling.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document> {
|
||||||
|
(*self.unsafe_get()).owner_doc.get_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait RawLayoutNodeHelpers {
|
||||||
|
unsafe fn get_hover_state_for_layout(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawLayoutNodeHelpers for Node {
|
||||||
|
unsafe fn get_hover_state_for_layout(&self) -> bool {
|
||||||
|
self.flags.get_in_hover_state()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Iteration and traversal
|
// Iteration and traversal
|
||||||
//
|
//
|
||||||
|
@ -689,7 +827,7 @@ impl<'a> NodeIterator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_child<'b>(&self, node: &JSRef<'b, Node>) -> Option<JSRef<Node>> {
|
fn next_child<'b>(&self, node: &JSRef<'b, Node>) -> Option<JSRef<Node>> {
|
||||||
if !self.include_descendants_of_void && node.get().is_element() {
|
if !self.include_descendants_of_void && node.is_element() {
|
||||||
let elem: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
|
let elem: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
|
||||||
if elem.get().is_void() {
|
if elem.get().is_void() {
|
||||||
None
|
None
|
||||||
|
@ -771,65 +909,6 @@ pub enum CloneChildrenFlag {
|
||||||
fn as_uintptr<T>(t: &T) -> uintptr_t { t as *T as uintptr_t }
|
fn as_uintptr<T>(t: &T) -> uintptr_t { t as *T as uintptr_t }
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
pub fn ancestors(&self) -> AncestorIterator {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
AncestorIterator {
|
|
||||||
current: self.parent_node.clone().map(|node| (*node.root(&roots)).clone()),
|
|
||||||
roots: roots,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_element(&self) -> bool {
|
|
||||||
match self.type_id {
|
|
||||||
ElementNodeTypeId(..) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_doctype(&self) -> bool {
|
|
||||||
match self.type_id {
|
|
||||||
DoctypeNodeTypeId => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn owner_doc(&self) -> Unrooted<Document> {
|
|
||||||
Unrooted::new(self.owner_doc.get_ref().clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document> {
|
|
||||||
self.owner_doc.get_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_owner_doc(&mut self, document: &JSRef<Document>) {
|
|
||||||
self.owner_doc = Some(document.unrooted());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn children(&self) -> AbstractNodeChildrenIterator {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
AbstractNodeChildrenIterator {
|
|
||||||
current_node: self.first_child.clone().map(|node| (*node.root(&roots)).clone()),
|
|
||||||
roots: roots,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child_elements(&self) -> ChildElementIterator {
|
|
||||||
self.children()
|
|
||||||
.filter(|node| {
|
|
||||||
node.is_element()
|
|
||||||
})
|
|
||||||
.map(|node| {
|
|
||||||
let elem: &JSRef<Element> = ElementCast::to_ref(&node).unwrap();
|
|
||||||
elem.clone()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wait_until_safe_to_modify_dom(&self) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
let document = self.owner_doc().root(&roots);
|
|
||||||
document.get().wait_until_safe_to_modify_dom();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reflect_node<N: Reflectable+NodeBase>
|
pub fn reflect_node<N: Reflectable+NodeBase>
|
||||||
(node: ~N,
|
(node: ~N,
|
||||||
document: &JSRef<Document>,
|
document: &JSRef<Document>,
|
||||||
|
@ -873,21 +952,6 @@ impl Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends layout data, if any, back to the script task to be destroyed.
|
|
||||||
pub unsafe fn reap_layout_data(&mut self) {
|
|
||||||
if self.layout_data.is_present() {
|
|
||||||
let layout_data = mem::replace(&mut self.layout_data, LayoutDataRef::new());
|
|
||||||
let layout_chan = layout_data.take_chan();
|
|
||||||
match layout_chan {
|
|
||||||
None => {}
|
|
||||||
Some(chan) => {
|
|
||||||
let LayoutChan(chan) = chan;
|
|
||||||
chan.send(ReapLayoutDataMsg(layout_data))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#concept-node-adopt
|
// http://dom.spec.whatwg.org/#concept-node-adopt
|
||||||
pub fn adopt(node: &mut JSRef<Node>, document: &JSRef<Document>) {
|
pub fn adopt(node: &mut JSRef<Node>, document: &JSRef<Document>) {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
|
@ -903,7 +967,7 @@ impl Node {
|
||||||
let node_doc = document_from_node(node).root(&roots);
|
let node_doc = document_from_node(node).root(&roots);
|
||||||
if &*node_doc != document {
|
if &*node_doc != document {
|
||||||
for mut descendant in node.traverse_preorder(&roots) {
|
for mut descendant in node.traverse_preorder(&roots) {
|
||||||
descendant.get_mut().set_owner_doc(document);
|
descendant.set_owner_doc(document);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,7 +1040,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
match child {
|
match child {
|
||||||
Some(ref child) if child.inclusively_following_siblings()
|
Some(ref child) if child.inclusively_following_siblings()
|
||||||
.any(|child| child.deref().is_doctype()) => {
|
.any(|child| child.is_doctype()) => {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -995,7 +1059,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
match child {
|
match child {
|
||||||
Some(ref child) if child.inclusively_following_siblings()
|
Some(ref child) if child.inclusively_following_siblings()
|
||||||
.any(|child| child.deref().is_doctype()) => {
|
.any(|child| child.is_doctype()) => {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -1003,14 +1067,14 @@ impl Node {
|
||||||
},
|
},
|
||||||
// Step 6.3
|
// Step 6.3
|
||||||
DoctypeNodeTypeId => {
|
DoctypeNodeTypeId => {
|
||||||
if parent.children().any(|c| c.deref().is_doctype()) {
|
if parent.children().any(|c| c.is_doctype()) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
match child {
|
match child {
|
||||||
Some(ref child) => {
|
Some(ref child) => {
|
||||||
if parent.children()
|
if parent.children()
|
||||||
.take_while(|c| c != child)
|
.take_while(|c| c != child)
|
||||||
.any(|c| c.deref().is_element()) {
|
.any(|c| c.is_element()) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1092,7 +1156,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#concept-node-replace-all
|
// http://dom.spec.whatwg.org/#concept-node-replace-all
|
||||||
pub fn replace_all(mut node: Option<JSRef<Node>>, parent: &mut JSRef<Node>) {
|
fn replace_all(mut node: Option<JSRef<Node>>, parent: &mut JSRef<Node>) {
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
|
@ -1178,7 +1242,7 @@ impl Node {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
let mut document = match maybe_doc {
|
let mut document = match maybe_doc {
|
||||||
Some(doc) => doc.unrooted().root(&roots),
|
Some(doc) => doc.unrooted().root(&roots),
|
||||||
None => node.get().owner_doc().root(&roots)
|
None => node.owner_doc().root(&roots)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
|
@ -1204,7 +1268,6 @@ impl Node {
|
||||||
},
|
},
|
||||||
DocumentNodeTypeId => {
|
DocumentNodeTypeId => {
|
||||||
let document: &JSRef<Document> = DocumentCast::to_ref(node).unwrap();
|
let document: &JSRef<Document> = DocumentCast::to_ref(node).unwrap();
|
||||||
let document = document.get();
|
|
||||||
let is_html_doc = match document.is_html_document {
|
let is_html_doc = match document.is_html_document {
|
||||||
true => HTMLDocument,
|
true => HTMLDocument,
|
||||||
false => NonHTMLDocument
|
false => NonHTMLDocument
|
||||||
|
@ -1242,15 +1305,13 @@ impl Node {
|
||||||
} else {
|
} else {
|
||||||
document.unrooted().root(&roots)
|
document.unrooted().root(&roots)
|
||||||
};
|
};
|
||||||
assert!(&*copy.get().owner_doc().root(&roots) == &*document);
|
assert!(&*copy.owner_doc().root(&roots) == &*document);
|
||||||
|
|
||||||
// Step 4 (some data already copied in step 2).
|
// Step 4 (some data already copied in step 2).
|
||||||
match node.get().type_id {
|
match node.get().type_id {
|
||||||
DocumentNodeTypeId => {
|
DocumentNodeTypeId => {
|
||||||
let node_doc: &JSRef<Document> = DocumentCast::to_ref(node).unwrap();
|
let node_doc: &JSRef<Document> = DocumentCast::to_ref(node).unwrap();
|
||||||
let node_doc = node_doc.get();
|
|
||||||
let copy_doc: &mut JSRef<Document> = DocumentCast::to_mut_ref(&mut *copy).unwrap();
|
let copy_doc: &mut JSRef<Document> = DocumentCast::to_mut_ref(&mut *copy).unwrap();
|
||||||
let copy_doc = copy_doc.get_mut();
|
|
||||||
copy_doc.set_encoding_name(node_doc.encoding_name.clone());
|
copy_doc.set_encoding_name(node_doc.encoding_name.clone());
|
||||||
copy_doc.set_quirks_mode(node_doc.quirks_mode());
|
copy_doc.set_quirks_mode(node_doc.quirks_mode());
|
||||||
},
|
},
|
||||||
|
@ -1281,7 +1342,7 @@ impl Node {
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
if clone_children == CloneChildren {
|
if clone_children == CloneChildren {
|
||||||
for ref child in node.get().children() {
|
for ref child in node.children() {
|
||||||
let mut child_copy = Node::clone(&*child, Some(&*document), clone_children).root(&roots);
|
let mut child_copy = Node::clone(&*child, Some(&*document), clone_children).root(&roots);
|
||||||
let _inserted_node = Node::pre_insert(&mut *child_copy, &mut *copy, None);
|
let _inserted_node = Node::pre_insert(&mut *child_copy, &mut *copy, None);
|
||||||
}
|
}
|
||||||
|
@ -1291,81 +1352,19 @@ impl Node {
|
||||||
Unrooted::new_rooted(&*copy)
|
Unrooted::new_rooted(&*copy)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/// Sends layout data, if any, back to the script task to be destroyed.
|
||||||
// Low-level pointer stitching
|
unsafe fn reap_layout_data(&mut self) {
|
||||||
//
|
if self.layout_data.is_present() {
|
||||||
|
let layout_data = mem::replace(&mut self.layout_data, LayoutDataRef::new());
|
||||||
pub fn set_parent_node(&mut self, new_parent_node: Option<JSRef<Node>>) {
|
let layout_chan = layout_data.take_chan();
|
||||||
let roots = RootCollection::new();
|
match layout_chan {
|
||||||
let doc = self.owner_doc().root(&roots);
|
None => {}
|
||||||
doc.get().wait_until_safe_to_modify_dom();
|
Some(chan) => {
|
||||||
self.parent_node.assign(new_parent_node);
|
let LayoutChan(chan) = chan;
|
||||||
}
|
chan.send(ReapLayoutDataMsg(layout_data))
|
||||||
|
},
|
||||||
pub fn set_first_child(&mut self, new_first_child: Option<JSRef<Node>>) {
|
}
|
||||||
let roots = RootCollection::new();
|
}
|
||||||
let doc = self.owner_doc().root(&roots);
|
|
||||||
doc.get().wait_until_safe_to_modify_dom();
|
|
||||||
self.first_child.assign(new_first_child);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_last_child(&mut self, new_last_child: Option<JSRef<Node>>) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
let doc = self.owner_doc().root(&roots);
|
|
||||||
doc.get().wait_until_safe_to_modify_dom();
|
|
||||||
self.last_child.assign(new_last_child);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<JSRef<Node>>) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
let doc = self.owner_doc().root(&roots);
|
|
||||||
doc.get().wait_until_safe_to_modify_dom();
|
|
||||||
self.prev_sibling.assign(new_prev_sibling);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_next_sibling(&mut self, new_next_sibling: Option<JSRef<Node>>) {
|
|
||||||
let roots = RootCollection::new();
|
|
||||||
let doc = self.owner_doc().root(&roots);
|
|
||||||
doc.get().wait_until_safe_to_modify_dom();
|
|
||||||
self.next_sibling.assign(new_next_sibling);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_hover_state(&self) -> bool {
|
|
||||||
self.flags.get_in_hover_state()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_hover_state(&mut self, state: bool) {
|
|
||||||
self.flags.set_is_in_hover_state(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
|
||||||
self.parent_node.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
|
||||||
self.first_child.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
|
||||||
self.last_child.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
|
||||||
self.prev_sibling.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
|
|
||||||
self.next_sibling.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn get_hover_state_for_layout(&self) -> bool {
|
|
||||||
let unsafe_this: *Node = cast::transmute::<&Node,*Node>(self);
|
|
||||||
(*unsafe_this).flags.get_in_hover_state()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1486,7 +1485,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
Some(ref list) => return Unrooted::new(list.clone()),
|
Some(ref list) => return Unrooted::new(list.clone()),
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = self.deref().owner_doc().root(&roots);
|
let doc = self.owner_doc().root(&roots);
|
||||||
let window = doc.deref().window.root(&roots);
|
let window = doc.deref().window.root(&roots);
|
||||||
let child_list = NodeList::new_child_list(&*window, self);
|
let child_list = NodeList::new_child_list(&*window, self);
|
||||||
self.child_list.assign(Some(child_list));
|
self.child_list.assign(Some(child_list));
|
||||||
|
@ -1600,7 +1599,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
|
|
||||||
// Notify the document that the content of this node is different
|
// Notify the document that the content of this node is different
|
||||||
let document = self.owner_doc().root(&roots);
|
let document = self.owner_doc().root(&roots);
|
||||||
document.get().content_changed();
|
document.deref().content_changed();
|
||||||
}
|
}
|
||||||
DoctypeNodeTypeId |
|
DoctypeNodeTypeId |
|
||||||
DocumentNodeTypeId => {}
|
DocumentNodeTypeId => {}
|
||||||
|
@ -1671,7 +1670,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
if child.following_siblings()
|
if child.following_siblings()
|
||||||
.any(|child| child.deref().is_doctype()) {
|
.any(|child| child.is_doctype()) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1685,18 +1684,18 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
if child.following_siblings()
|
if child.following_siblings()
|
||||||
.any(|child| child.deref().is_doctype()) {
|
.any(|child| child.is_doctype()) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Step 6.3
|
// Step 6.3
|
||||||
DoctypeNodeTypeId => {
|
DoctypeNodeTypeId => {
|
||||||
if self.children().any(|c| c.deref().is_doctype() && &c != child) {
|
if self.children().any(|c| c.is_doctype() && &c != child) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
if self.children()
|
if self.children()
|
||||||
.take_while(|c| c != child)
|
.take_while(|c| c != child)
|
||||||
.any(|c| c.deref().is_element()) {
|
.any(|c| c.is_element()) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,11 +7,11 @@ use dom::bindings::codegen::InheritTypes::{NodeBase, NodeCast, TextCast, Element
|
||||||
use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast;
|
use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast;
|
||||||
use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, OptionalRootable, Root};
|
use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, OptionalRootable, Root};
|
||||||
use dom::bindings::utils::Reflectable;
|
use dom::bindings::utils::Reflectable;
|
||||||
use dom::document::Document;
|
use dom::document::{Document, DocumentHelpers};
|
||||||
use dom::element::{AttributeHandlers, HTMLLinkElementTypeId, HTMLIFrameElementTypeId};
|
use dom::element::{AttributeHandlers, HTMLLinkElementTypeId, HTMLIFrameElementTypeId};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlheadingelement::{Heading1, Heading2, Heading3, Heading4, Heading5, Heading6};
|
use dom::htmlheadingelement::{Heading1, Heading2, Heading3, Heading4, Heading5, Heading6};
|
||||||
use dom::htmliframeelement::IFrameSize;
|
use dom::htmliframeelement::{IFrameSize, HTMLIFrameElementHelpers};
|
||||||
use dom::htmlformelement::HTMLFormElement;
|
use dom::htmlformelement::HTMLFormElement;
|
||||||
use dom::node::{ElementNodeTypeId, NodeHelpers, NodeMethods};
|
use dom::node::{ElementNodeTypeId, NodeHelpers, NodeMethods};
|
||||||
use dom::types::*;
|
use dom::types::*;
|
||||||
|
@ -364,7 +364,11 @@ pub fn parse_html(page: &Page,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Spawn additional parsing, network loads, etc. from tag and attrs
|
// Spawn additional parsing, network loads, etc. from tag and attrs
|
||||||
match element.get().node.type_id {
|
let type_id = {
|
||||||
|
let node: &JSRef<Node> = NodeCast::from_ref(&*element);
|
||||||
|
node.type_id()
|
||||||
|
};
|
||||||
|
match type_id {
|
||||||
// Handle CSS style sheets from <link> elements
|
// Handle CSS style sheets from <link> elements
|
||||||
ElementNodeTypeId(HTMLLinkElementTypeId) => {
|
ElementNodeTypeId(HTMLLinkElementTypeId) => {
|
||||||
match (rel, href) {
|
match (rel, href) {
|
||||||
|
@ -384,10 +388,10 @@ pub fn parse_html(page: &Page,
|
||||||
let iframe_chan = discovery_chan.clone();
|
let iframe_chan = discovery_chan.clone();
|
||||||
let iframe_element: &mut JSRef<HTMLIFrameElement> =
|
let iframe_element: &mut JSRef<HTMLIFrameElement> =
|
||||||
HTMLIFrameElementCast::to_mut_ref(&mut *element).unwrap();
|
HTMLIFrameElementCast::to_mut_ref(&mut *element).unwrap();
|
||||||
let sandboxed = iframe_element.get().is_sandboxed();
|
let sandboxed = iframe_element.is_sandboxed();
|
||||||
for src in src_opt.iter() {
|
for src in src_opt.iter() {
|
||||||
let iframe_url = parse_url(*src, Some(url2.clone()));
|
let iframe_url = parse_url(*src, Some(url2.clone()));
|
||||||
iframe_element.get_mut().set_frame(iframe_url.clone());
|
iframe_element.set_frame(iframe_url.clone());
|
||||||
|
|
||||||
// Subpage Id
|
// Subpage Id
|
||||||
let subpage_id = *next_subpage_id.borrow();
|
let subpage_id = *next_subpage_id.borrow();
|
||||||
|
@ -463,14 +467,14 @@ pub fn parse_html(page: &Page,
|
||||||
// NOTE: tmp vars are workaround for lifetime issues. Both required.
|
// NOTE: tmp vars are workaround for lifetime issues. Both required.
|
||||||
let mut tmp_borrow = doc_cell.borrow_mut();
|
let mut tmp_borrow = doc_cell.borrow_mut();
|
||||||
let tmp = &mut *tmp_borrow;
|
let tmp = &mut *tmp_borrow;
|
||||||
tmp.get_mut().set_quirks_mode(mode);
|
tmp.set_quirks_mode(mode);
|
||||||
},
|
},
|
||||||
encoding_change: |encname| {
|
encoding_change: |encname| {
|
||||||
debug!("encoding change");
|
debug!("encoding change");
|
||||||
// NOTE: tmp vars are workaround for lifetime issues. Both required.
|
// NOTE: tmp vars are workaround for lifetime issues. Both required.
|
||||||
let mut tmp_borrow = doc_cell.borrow_mut();
|
let mut tmp_borrow = doc_cell.borrow_mut();
|
||||||
let tmp = &mut *tmp_borrow;
|
let tmp = &mut *tmp_borrow;
|
||||||
tmp.get_mut().set_encoding_name(encname);
|
tmp.set_encoding_name(encname);
|
||||||
},
|
},
|
||||||
complete_script: |script| {
|
complete_script: |script| {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, OptionalAssignable}
|
||||||
use dom::bindings::js::OptionalRootable;
|
use dom::bindings::js::OptionalRootable;
|
||||||
use dom::bindings::trace::{Traceable, Untraceable};
|
use dom::bindings::trace::{Traceable, Untraceable};
|
||||||
use dom::bindings::utils::{Reflectable, GlobalStaticData, wrap_for_same_compartment};
|
use dom::bindings::utils::{Reflectable, GlobalStaticData, wrap_for_same_compartment};
|
||||||
use dom::document::{Document, HTMLDocument, DocumentMethods};
|
use dom::document::{Document, HTMLDocument, DocumentMethods, DocumentHelpers};
|
||||||
use dom::element::{Element, AttributeHandlers};
|
use dom::element::{Element, AttributeHandlers};
|
||||||
use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
|
use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
|
||||||
use dom::event::{Event, EventMethods};
|
use dom::event::{Event, EventMethods};
|
||||||
|
@ -949,7 +949,7 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kick off the initial reflow of the page.
|
// Kick off the initial reflow of the page.
|
||||||
document.get().content_changed();
|
document.content_changed();
|
||||||
|
|
||||||
let fragment = url.fragment.as_ref().map(|ref fragment| fragment.to_owned());
|
let fragment = url.fragment.as_ref().map(|ref fragment| fragment.to_owned());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue