diff options
Diffstat (limited to 'src/components/script/dom/document.rs')
-rw-r--r-- | src/components/script/dom/document.rs | 634 |
1 files changed, 370 insertions, 264 deletions
diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index fdf47a5467d..d911611eba3 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -3,11 +3,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::InheritTypes::{DocumentDerived, EventCast, HTMLElementCast}; -use dom::bindings::codegen::InheritTypes::{DocumentBase, NodeCast, DocumentCast}; use dom::bindings::codegen::InheritTypes::{HTMLHeadElementCast, TextCast, ElementCast}; -use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast}; +use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast, NodeCast}; use dom::bindings::codegen::BindingDeclarations::DocumentBinding; -use dom::bindings::js::JS; +use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable, TemporaryPushable}; +use dom::bindings::js::OptionalRootable; use dom::bindings::trace::Untraceable; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::{ErrorResult, Fallible, NotSupported, InvalidCharacter, HierarchyRequest, NamespaceError}; @@ -22,18 +22,18 @@ use dom::element::{HTMLBodyElementTypeId, HTMLFrameSetElementTypeId}; use dom::event::Event; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlcollection::{HTMLCollection, CollectionFilter}; -use dom::nodelist::NodeList; use dom::htmlelement::HTMLElement; use dom::htmlheadelement::HTMLHeadElement; use dom::htmlhtmlelement::HTMLHtmlElement; use dom::htmltitleelement::HTMLTitleElement; use dom::mouseevent::MouseEvent; -use dom::node::{Node, ElementNodeTypeId, DocumentNodeTypeId, NodeHelpers, INode}; +use dom::node::{Node, ElementNodeTypeId, DocumentNodeTypeId, NodeHelpers, NodeMethods}; use dom::node::{CloneChildren, DoNotCloneChildren}; +use dom::nodelist::NodeList; use dom::text::Text; use dom::processinginstruction::ProcessingInstruction; use dom::uievent::UIEvent; -use dom::window::Window; +use dom::window::{Window, WindowMethods}; use dom::location::Location; use html::hubbub_html_parser::build_element_from_tag; use hubbub::hubbub::{QuirksMode, NoQuirks, LimitedQuirks, FullQuirks}; @@ -76,23 +76,127 @@ 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) { + self.window.root().damage_and_reflow(damage); + } + + fn wait_until_safe_to_modify_dom(&self) { + self.window.root().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 mut is_empty = false; + match self.idmap.find_mut(&id) { + None => {}, + Some(elements) => { + let position = elements.iter() + .map(|elem| elem.root()) + .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) { + 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(); + 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() { + let elem: Option<&JSRef<Element>> = ElementCast::to_ref(&node); + match elem { + Some(elem) => { + if &*elements.get(head).root() == elem { + head = head + 1; + } + if new_node == &node || head == elements.len() { + break; + } + } + None => {} + } + } + elements.insert_unrooted(head, element); + return; + }, + None => (), + } + let mut elements = vec!(); + elements.push_unrooted(element); + self.idmap.insert(id, elements); + } +} + impl Document { - pub fn reflect_document<D: Reflectable+DocumentBase> - (document: ~D, - window: &JS<Window>, - wrap_fn: extern "Rust" fn(*JSContext, &JS<Window>, ~D) -> JS<D>) - -> JS<D> { + pub fn reflect_document(document: ~Document, + window: &JSRef<Window>, + wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~Document) -> JS<Document>) + -> Temporary<Document> { assert!(document.reflector().get_jsobject().is_null()); - let raw_doc = reflect_dom_object(document, window, wrap_fn); + let mut raw_doc = reflect_dom_object(document, window, wrap_fn).root(); assert!(raw_doc.reflector().get_jsobject().is_not_null()); - let document = DocumentCast::from(&raw_doc); - let mut node: JS<Node> = NodeCast::from(&document); - node.get_mut().set_owner_doc(&document); - raw_doc + let mut doc_alias = raw_doc.clone(); + let node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut doc_alias); + node.set_owner_doc(&*raw_doc); + Temporary::from_rooted(&*raw_doc) } - pub fn new_inherited(window: JS<Window>, + pub fn new_inherited(window: &JSRef<Window>, url: Option<Url>, is_html_document: IsHTMLDocument, content_type: Option<DOMString>) -> Document { @@ -101,7 +205,7 @@ impl Document { Document { node: Node::new_without_doc(DocumentNodeTypeId), reflector_: Reflector::new(), - window: window, + window: window.unrooted(), idmap: HashMap::new(), implementation: None, content_type: match content_type { @@ -122,23 +226,15 @@ impl Document { } } - pub fn new(window: &JS<Window>, url: Option<Url>, doctype: IsHTMLDocument, content_type: Option<DOMString>) -> JS<Document> { - let document = Document::new_inherited(window.clone(), url, doctype, content_type); - Document::reflect_document(~document, window, DocumentBinding::Wrap) - } -} - -impl Document { - pub fn url<'a>(&'a self) -> &'a Url { - &*self.url - } -} - -impl Document { // http://dom.spec.whatwg.org/#dom-document - pub fn Constructor(owner: &JS<Window>) -> Fallible<JS<Document>> { + pub fn Constructor(owner: &JSRef<Window>) -> Fallible<Temporary<Document>> { Ok(Document::new(owner, None, NonHTMLDocument, None)) } + + pub fn new(window: &JSRef<Window>, url: Option<Url>, doctype: IsHTMLDocument, content_type: Option<DOMString>) -> Temporary<Document> { + let document = Document::new_inherited(window, url, doctype, content_type); + Document::reflect_document(~document, window, DocumentBinding::Wrap) + } } impl Reflectable for Document { @@ -151,108 +247,183 @@ impl Reflectable for Document { } } -impl Document { +trait PrivateDocumentHelpers { + fn createNodeList(&self, callback: |node: &JSRef<Node>| -> bool) -> Temporary<NodeList>; + fn get_html_element(&self) -> Option<Temporary<HTMLHtmlElement>>; +} + +impl<'a> PrivateDocumentHelpers for JSRef<'a, Document> { + fn createNodeList(&self, callback: |node: &JSRef<Node>| -> bool) -> Temporary<NodeList> { + let window = self.window.root(); + + match self.GetDocumentElement().root() { + None => { + NodeList::new_simple_list(&*window, vec!()) + }, + Some(root) => { + let mut nodes = vec!(); + let root: &JSRef<Node> = NodeCast::from_ref(&*root); + for child in root.traverse_preorder() { + if callback(&child) { + nodes.push(child); + } + } + NodeList::new_simple_list(&*window, nodes) + } + } + + } + + fn get_html_element(&self) -> Option<Temporary<HTMLHtmlElement>> { + self.GetDocumentElement().root().filtered(|root| { + root.node.type_id == ElementNodeTypeId(HTMLHtmlElementTypeId) + }).map(|elem| { + Temporary::from_rooted(HTMLHtmlElementCast::to_ref(&*elem).unwrap()) + }) + } +} + +pub trait DocumentMethods { + fn Implementation(&mut self) -> Temporary<DOMImplementation>; + fn URL(&self) -> DOMString; + fn DocumentURI(&self) -> DOMString; + fn CompatMode(&self) -> DOMString; + fn CharacterSet(&self) -> DOMString; + fn ContentType(&self) -> DOMString; + fn GetDoctype(&self) -> Option<Temporary<DocumentType>>; + fn GetDocumentElement(&self) -> Option<Temporary<Element>>; + fn GetElementsByTagName(&self, tag_name: DOMString) -> Temporary<HTMLCollection>; + fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>, tag_name: DOMString) -> Temporary<HTMLCollection>; + fn GetElementsByClassName(&self, classes: DOMString) -> Temporary<HTMLCollection>; + fn GetElementById(&self, id: DOMString) -> Option<Temporary<Element>>; + fn CreateElement(&self, local_name: DOMString) -> Fallible<Temporary<Element>>; + fn CreateElementNS(&self, namespace: Option<DOMString>, qualified_name: DOMString) -> Fallible<Temporary<Element>>; + fn CreateDocumentFragment(&self) -> Temporary<DocumentFragment>; + fn CreateTextNode(&self, data: DOMString) -> Temporary<Text>; + fn CreateComment(&self, data: DOMString) -> Temporary<Comment>; + fn CreateProcessingInstruction(&self, target: DOMString, data: DOMString) -> Fallible<Temporary<ProcessingInstruction>>; + fn ImportNode(&self, node: &JSRef<Node>, deep: bool) -> Fallible<Temporary<Node>>; + fn AdoptNode(&self, node: &mut JSRef<Node>) -> Fallible<Temporary<Node>>; + fn CreateEvent(&self, interface: DOMString) -> Fallible<Temporary<Event>>; + fn Title(&self) -> DOMString; + fn SetTitle(&self, title: DOMString) -> ErrorResult; + fn GetHead(&self) -> Option<Temporary<HTMLHeadElement>>; + fn GetBody(&self) -> Option<Temporary<HTMLElement>>; + fn SetBody(&self, new_body: Option<JSRef<HTMLElement>>) -> ErrorResult; + fn GetElementsByName(&self, name: DOMString) -> Temporary<NodeList>; + fn Images(&self) -> Temporary<HTMLCollection>; + fn Embeds(&self) -> Temporary<HTMLCollection>; + fn Plugins(&self) -> Temporary<HTMLCollection>; + fn Links(&self) -> Temporary<HTMLCollection>; + fn Forms(&self) -> Temporary<HTMLCollection>; + fn Scripts(&self) -> Temporary<HTMLCollection>; + fn Anchors(&self) -> Temporary<HTMLCollection>; + fn Applets(&self) -> Temporary<HTMLCollection>; + fn Location(&mut self) -> Temporary<Location>; + fn Children(&self) -> Temporary<HTMLCollection>; +} + +impl<'a> DocumentMethods for JSRef<'a, Document> { // http://dom.spec.whatwg.org/#dom-document-implementation - pub fn Implementation(&mut self) -> JS<DOMImplementation> { + fn Implementation(&mut self) -> Temporary<DOMImplementation> { if self.implementation.is_none() { - self.implementation = Some(DOMImplementation::new(&self.window)); + let window = self.window.root(); + self.implementation.assign(Some(DOMImplementation::new(&*window))); } - self.implementation.get_ref().clone() + Temporary::new(self.implementation.get_ref().clone()) } // http://dom.spec.whatwg.org/#dom-document-url - pub fn URL(&self) -> DOMString { + fn URL(&self) -> DOMString { self.url().to_str() } // http://dom.spec.whatwg.org/#dom-document-documenturi - pub fn DocumentURI(&self) -> DOMString { + fn DocumentURI(&self) -> DOMString { self.URL() } // http://dom.spec.whatwg.org/#dom-document-compatmode - pub fn CompatMode(&self) -> DOMString { + fn CompatMode(&self) -> DOMString { match *self.quirks_mode { NoQuirks => ~"CSS1Compat", LimitedQuirks | FullQuirks => ~"BackCompat" } } - pub fn quirks_mode(&self) -> QuirksMode { - *self.quirks_mode - } - - pub fn set_quirks_mode(&mut self, mode: QuirksMode) { - *self.quirks_mode = mode; - } - // http://dom.spec.whatwg.org/#dom-document-characterset - pub fn CharacterSet(&self) -> DOMString { + fn CharacterSet(&self) -> DOMString { self.encoding_name.to_ascii_lower() } - pub fn set_encoding_name(&mut self, name: DOMString) { - self.encoding_name = name; - } - // http://dom.spec.whatwg.org/#dom-document-content_type - pub fn ContentType(&self) -> DOMString { + fn ContentType(&self) -> DOMString { self.content_type.clone() } // http://dom.spec.whatwg.org/#dom-document-doctype - pub fn GetDoctype(&self) -> Option<JS<DocumentType>> { - self.node.children().find(|child| child.is_doctype()) - .map(|node| DocumentTypeCast::to(&node).unwrap()) + fn GetDoctype(&self) -> Option<Temporary<DocumentType>> { + let node: &JSRef<Node> = NodeCast::from_ref(self); + node.children().find(|child| { + child.is_doctype() + }).map(|node| { + let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(&node).unwrap(); + Temporary::from_rooted(doctype) + }) } // http://dom.spec.whatwg.org/#dom-document-documentelement - pub fn GetDocumentElement(&self) -> Option<JS<Element>> { - self.node.child_elements().next() + fn GetDocumentElement(&self) -> Option<Temporary<Element>> { + let node: &JSRef<Node> = NodeCast::from_ref(self); + node.child_elements().next().map(|elem| Temporary::from_rooted(&elem)) } // http://dom.spec.whatwg.org/#dom-document-getelementsbytagname - pub fn GetElementsByTagName(&self, abstract_self: &JS<Document>, tag_name: DOMString) -> JS<HTMLCollection> { - HTMLCollection::by_tag_name(&self.window, &NodeCast::from(abstract_self), tag_name) + fn GetElementsByTagName(&self, tag_name: DOMString) -> Temporary<HTMLCollection> { + let window = self.window.root(); + HTMLCollection::by_tag_name(&*window, NodeCast::from_ref(self), tag_name) } // http://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens - pub fn GetElementsByTagNameNS(&self, abstract_self: &JS<Document>, maybe_ns: Option<DOMString>, tag_name: DOMString) -> JS<HTMLCollection> { + fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>, tag_name: DOMString) -> Temporary<HTMLCollection> { + let window = self.window.root(); + let namespace = match maybe_ns { Some(namespace) => Namespace::from_str(namespace), None => Null }; - HTMLCollection::by_tag_name_ns(&self.window, &NodeCast::from(abstract_self), tag_name, namespace) + HTMLCollection::by_tag_name_ns(&*window, NodeCast::from_ref(self), tag_name, namespace) } // http://dom.spec.whatwg.org/#dom-document-getelementsbyclassname - pub fn GetElementsByClassName(&self, abstract_self: &JS<Document>, classes: DOMString) -> JS<HTMLCollection> { - HTMLCollection::by_class_name(&self.window, &NodeCast::from(abstract_self), classes) + fn GetElementsByClassName(&self, classes: DOMString) -> Temporary<HTMLCollection> { + let window = self.window.root(); + + HTMLCollection::by_class_name(&*window, NodeCast::from_ref(self), classes) } // http://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid - pub fn GetElementById(&self, id: DOMString) -> Option<JS<Element>> { + fn GetElementById(&self, id: DOMString) -> Option<Temporary<Element>> { match self.idmap.find_equiv(&id) { None => None, - Some(ref elements) => Some(elements.get(0).clone()), + Some(ref elements) => Some(Temporary::new(elements.get(0).clone())), } } // http://dom.spec.whatwg.org/#dom-document-createelement - pub fn CreateElement(&self, abstract_self: &JS<Document>, local_name: DOMString) - -> Fallible<JS<Element>> { + fn CreateElement(&self, local_name: DOMString) -> Fallible<Temporary<Element>> { if xml_name_type(local_name) == InvalidXMLName { debug!("Not a valid element name"); return Err(InvalidCharacter); } let local_name = local_name.to_ascii_lower(); - Ok(build_element_from_tag(local_name, abstract_self)) + Ok(build_element_from_tag(local_name, self)) } // http://dom.spec.whatwg.org/#dom-document-createelementns - pub fn CreateElementNS(&self, abstract_self: &JS<Document>, - namespace: Option<DOMString>, - qualified_name: DOMString) -> Fallible<JS<Element>> { + fn CreateElementNS(&self, + namespace: Option<DOMString>, + qualified_name: DOMString) -> Fallible<Temporary<Element>> { let ns = Namespace::from_str(null_str_as_empty_ref(&namespace)); match xml_name_type(qualified_name) { InvalidXMLName => { @@ -289,31 +460,31 @@ impl Document { } if ns == namespace::HTML { - Ok(build_element_from_tag(local_name_from_qname, abstract_self)) + Ok(build_element_from_tag(local_name_from_qname, self)) } else { - Ok(Element::new(local_name_from_qname, ns, prefix_from_qname, abstract_self)) + Ok(Element::new(local_name_from_qname, ns, prefix_from_qname, self)) } } // http://dom.spec.whatwg.org/#dom-document-createdocumentfragment - pub fn CreateDocumentFragment(&self, abstract_self: &JS<Document>) -> JS<DocumentFragment> { - DocumentFragment::new(abstract_self) + fn CreateDocumentFragment(&self) -> Temporary<DocumentFragment> { + DocumentFragment::new(self) } // http://dom.spec.whatwg.org/#dom-document-createtextnode - pub fn CreateTextNode(&self, abstract_self: &JS<Document>, data: DOMString) - -> JS<Text> { - Text::new(data, abstract_self) + fn CreateTextNode(&self, data: DOMString) + -> Temporary<Text> { + Text::new(data, self) } // http://dom.spec.whatwg.org/#dom-document-createcomment - pub fn CreateComment(&self, abstract_self: &JS<Document>, data: DOMString) -> JS<Comment> { - Comment::new(data, abstract_self) + fn CreateComment(&self, data: DOMString) -> Temporary<Comment> { + Comment::new(data, self) } // http://dom.spec.whatwg.org/#dom-document-createprocessinginstruction - pub fn CreateProcessingInstruction(&self, abstract_self: &JS<Document>, target: DOMString, - data: DOMString) -> Fallible<JS<ProcessingInstruction>> { + fn CreateProcessingInstruction(&self, target: DOMString, + data: DOMString) -> Fallible<Temporary<ProcessingInstruction>> { // Step 1. if xml_name_type(target) == InvalidXMLName { return Err(InvalidCharacter); @@ -325,11 +496,11 @@ impl Document { } // Step 3. - Ok(ProcessingInstruction::new(target, data, abstract_self)) + Ok(ProcessingInstruction::new(target, data, self)) } // http://dom.spec.whatwg.org/#dom-document-importnode - pub fn ImportNode(&self, abstract_self: &JS<Document>, node: &JS<Node>, deep: bool) -> Fallible<JS<Node>> { + fn ImportNode(&self, node: &JSRef<Node>, deep: bool) -> Fallible<Temporary<Node>> { // Step 1. if node.is_document() { return Err(NotSupported); @@ -341,47 +512,48 @@ impl Document { false => DoNotCloneChildren }; - Ok(Node::clone(node, Some(abstract_self), clone_children)) + Ok(Node::clone(node, Some(self), clone_children)) } // http://dom.spec.whatwg.org/#dom-document-adoptnode - pub fn AdoptNode(&self, abstract_self: &JS<Document>, node: &JS<Node>) -> Fallible<JS<Node>> { + fn AdoptNode(&self, node: &mut JSRef<Node>) -> Fallible<Temporary<Node>> { // Step 1. if node.is_document() { return Err(NotSupported); } // Step 2. - let mut adoptee = node.clone(); - Node::adopt(&mut adoptee, abstract_self); + Node::adopt(node, self); // Step 3. - Ok(adoptee) + Ok(Temporary::from_rooted(node)) } // http://dom.spec.whatwg.org/#dom-document-createevent - pub fn CreateEvent(&self, interface: DOMString) -> Fallible<JS<Event>> { + fn CreateEvent(&self, interface: DOMString) -> Fallible<Temporary<Event>> { + let window = self.window.root(); + match interface.to_ascii_lower().as_slice() { // FIXME: Implement CustomEvent (http://dom.spec.whatwg.org/#customevent) - "uievents" | "uievent" => Ok(EventCast::from(&UIEvent::new(&self.window))), - "mouseevents" | "mouseevent" => Ok(EventCast::from(&MouseEvent::new(&self.window))), - "htmlevents" | "events" | "event" => Ok(Event::new(&self.window)), + "uievents" | "uievent" => Ok(EventCast::from_unrooted(UIEvent::new(&*window))), + "mouseevents" | "mouseevent" => Ok(EventCast::from_unrooted(MouseEvent::new(&*window))), + "htmlevents" | "events" | "event" => Ok(Event::new(&*window)), _ => Err(NotSupported) } } // http://www.whatwg.org/specs/web-apps/current-work/#document.title - pub fn Title(&self, _: &JS<Document>) -> DOMString { + fn Title(&self) -> DOMString { let mut title = ~""; - self.GetDocumentElement().map(|root| { - let root: JS<Node> = NodeCast::from(&root); + self.GetDocumentElement().root().map(|root| { + let root: &JSRef<Node> = NodeCast::from_ref(&*root); root.traverse_preorder() .find(|node| node.type_id() == ElementNodeTypeId(HTMLTitleElementTypeId)) .map(|title_elem| { for child in title_elem.children() { if child.is_text() { - let text: JS<Text> = TextCast::to(&child).unwrap(); - title.push_str(text.get().characterdata.data.as_slice()); + let text: &JSRef<Text> = TextCast::to_ref(&child).unwrap(); + title.push_str(text.deref().characterdata.data.as_slice()); } } }); @@ -392,15 +564,15 @@ impl Document { } // http://www.whatwg.org/specs/web-apps/current-work/#document.title - pub fn SetTitle(&self, abstract_self: &JS<Document>, title: DOMString) -> ErrorResult { - self.GetDocumentElement().map(|root| { - let root: JS<Node> = NodeCast::from(&root); + fn SetTitle(&self, title: DOMString) -> ErrorResult { + self.GetDocumentElement().root().map(|root| { + let root: &JSRef<Node> = NodeCast::from_ref(&*root); let mut head_node = root.traverse_preorder().find(|child| { - child.get().type_id == ElementNodeTypeId(HTMLHeadElementTypeId) + child.type_id() == ElementNodeTypeId(HTMLHeadElementTypeId) }); head_node.as_mut().map(|head| { let mut title_node = head.children().find(|child| { - child.get().type_id == ElementNodeTypeId(HTMLTitleElementTypeId) + child.type_id() == ElementNodeTypeId(HTMLTitleElementTypeId) }); match title_node { @@ -408,15 +580,18 @@ impl Document { for mut title_child in title_node.children() { assert!(title_node.RemoveChild(&mut title_child).is_ok()); } - let new_text = self.CreateTextNode(abstract_self, title.clone()); - assert!(title_node.AppendChild(&mut NodeCast::from(&new_text)).is_ok()); + let mut new_text = self.CreateTextNode(title.clone()).root(); + + assert!(title_node.AppendChild(NodeCast::from_mut_ref(&mut *new_text)).is_ok()); }, None => { - let mut new_title: JS<Node> = - NodeCast::from(&HTMLTitleElement::new(~"title", abstract_self)); - let new_text = self.CreateTextNode(abstract_self, title.clone()); - assert!(new_title.AppendChild(&mut NodeCast::from(&new_text)).is_ok()); - assert!(head.AppendChild(&mut new_title).is_ok()); + let mut new_title = HTMLTitleElement::new(~"title", self).root(); + let new_title: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut *new_title); + + let mut new_text = self.CreateTextNode(title.clone()).root(); + + assert!(new_title.AppendChild(NodeCast::from_mut_ref(&mut *new_text)).is_ok()); + assert!(head.AppendChild(&mut *new_title).is_ok()); }, } }); @@ -424,42 +599,43 @@ impl Document { Ok(()) } - fn get_html_element(&self) -> Option<JS<HTMLHtmlElement>> { - self.GetDocumentElement().filtered(|root| { - root.get().node.type_id == ElementNodeTypeId(HTMLHtmlElementTypeId) - }).map(|elem| HTMLHtmlElementCast::to(&elem).unwrap()) - } - // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-head - pub fn GetHead(&self) -> Option<JS<HTMLHeadElement>> { + fn GetHead(&self) -> Option<Temporary<HTMLHeadElement>> { self.get_html_element().and_then(|root| { - let node: JS<Node> = NodeCast::from(&root); + let root = root.root(); + let node: &JSRef<Node> = NodeCast::from_ref(&*root); node.children().find(|child| { child.type_id() == ElementNodeTypeId(HTMLHeadElementTypeId) - }).map(|node| HTMLHeadElementCast::to(&node).unwrap()) + }).map(|node| { + Temporary::from_rooted(HTMLHeadElementCast::to_ref(&node).unwrap()) + }) }) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-body - pub fn GetBody(&self, _: &JS<Document>) -> Option<JS<HTMLElement>> { + fn GetBody(&self) -> Option<Temporary<HTMLElement>> { self.get_html_element().and_then(|root| { - let node: JS<Node> = NodeCast::from(&root); + let root = root.root(); + let node: &JSRef<Node> = NodeCast::from_ref(&*root); node.children().find(|child| { match child.type_id() { ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => true, _ => false } - }).map(|node| HTMLElementCast::to(&node).unwrap()) + }).map(|node| { + Temporary::from_rooted(HTMLElementCast::to_ref(&node).unwrap()) + }) }) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-body - pub fn SetBody(&self, abstract_self: &JS<Document>, new_body: Option<JS<HTMLElement>>) -> ErrorResult { + fn SetBody(&self, new_body: Option<JSRef<HTMLElement>>) -> ErrorResult { // Step 1. match new_body { - Some(ref node) => { - match node.get().element.node.type_id { + Some(ref htmlelem) => { + let node: &JSRef<Node> = NodeCast::from_ref(htmlelem); + match node.type_id() { ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => {} _ => return Err(HierarchyRequest) } @@ -468,24 +644,28 @@ impl Document { } // Step 2. - let old_body: Option<JS<HTMLElement>> = self.GetBody(abstract_self); - if old_body == new_body { + let mut old_body = self.GetBody().root(); + //FIXME: covariant lifetime workaround. do not judge. + if old_body.as_ref().map(|body| body.deref()) == new_body.as_ref().map(|a| &*a) { return Ok(()); } // Step 3. - match self.get_html_element() { + match self.get_html_element().root() { // Step 4. None => return Err(HierarchyRequest), - Some(root) => { - let mut new_body: JS<Node> = NodeCast::from(&new_body.unwrap()); - let mut root: JS<Node> = NodeCast::from(&root); + Some(ref mut root) => { + let mut new_body_unwrapped = new_body.unwrap(); + let new_body: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut new_body_unwrapped); + + let root: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut **root); match old_body { - Some(child) => { - let mut child: JS<Node> = NodeCast::from(&child); - assert!(root.ReplaceChild(&mut new_body, &mut child).is_ok()) + Some(ref mut child) => { + let child: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut **child); + + assert!(root.ReplaceChild(new_body, child).is_ok()) } - None => assert!(root.AppendChild(&mut new_body).is_ok()) + None => assert!(root.AppendChild(new_body).is_ok()) }; } } @@ -493,204 +673,130 @@ impl Document { } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-getelementsbyname - pub fn GetElementsByName(&self, name: DOMString) -> JS<NodeList> { + fn GetElementsByName(&self, name: DOMString) -> Temporary<NodeList> { self.createNodeList(|node| { if !node.is_element() { return false; } - let element: JS<Element> = ElementCast::to(node).unwrap(); - element.get_attribute(Null, "name").map_or(false, |attr| { - attr.get().value_ref() == name + let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); + element.get_attribute(Null, "name").root().map_or(false, |mut attr| { + attr.value_ref() == name }) }) } - pub fn Images(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { + fn Images(&self) -> Temporary<HTMLCollection> { + let window = self.window.root(); + // FIXME: https://github.com/mozilla/servo/issues/1847 struct ImagesFilter; impl CollectionFilter for ImagesFilter { - fn filter(&self, elem: &JS<Element>, _root: &JS<Node>) -> bool { - elem.get().local_name == ~"img" + fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { + elem.deref().local_name == ~"img" } } let filter = ~ImagesFilter; - HTMLCollection::create(&self.window, &NodeCast::from(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(self), filter) } - pub fn Embeds(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { + fn Embeds(&self) -> Temporary<HTMLCollection> { + let window = self.window.root(); + // FIXME: https://github.com/mozilla/servo/issues/1847 struct EmbedsFilter; impl CollectionFilter for EmbedsFilter { - fn filter(&self, elem: &JS<Element>, _root: &JS<Node>) -> bool { - elem.get().local_name == ~"embed" + fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { + elem.deref().local_name == ~"embed" } } let filter = ~EmbedsFilter; - HTMLCollection::create(&self.window, &NodeCast::from(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(self), filter) } - pub fn Plugins(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { + fn Plugins(&self) -> Temporary<HTMLCollection> { // FIXME: https://github.com/mozilla/servo/issues/1847 - self.Embeds(abstract_self) + self.Embeds() } - pub fn Links(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { + fn Links(&self) -> Temporary<HTMLCollection> { + let window = self.window.root(); + // FIXME: https://github.com/mozilla/servo/issues/1847 struct LinksFilter; impl CollectionFilter for LinksFilter { - fn filter(&self, elem: &JS<Element>, _root: &JS<Node>) -> bool { - (elem.get().local_name == ~"a" || elem.get().local_name == ~"area") && + fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { + (elem.deref().local_name == ~"a" || elem.deref().local_name == ~"area") && elem.get_attribute(Null, "href").is_some() } } let filter = ~LinksFilter; - HTMLCollection::create(&self.window, &NodeCast::from(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(self), filter) } - pub fn Forms(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { + fn Forms(&self) -> Temporary<HTMLCollection> { + let window = self.window.root(); + // FIXME: https://github.com/mozilla/servo/issues/1847 struct FormsFilter; impl CollectionFilter for FormsFilter { - fn filter(&self, elem: &JS<Element>, _root: &JS<Node>) -> bool { - elem.get().local_name == ~"form" + fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { + elem.deref().local_name == ~"form" } } let filter = ~FormsFilter; - HTMLCollection::create(&self.window, &NodeCast::from(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(self), filter) } - pub fn Scripts(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { + fn Scripts(&self) -> Temporary<HTMLCollection> { + let window = self.window.root(); + // FIXME: https://github.com/mozilla/servo/issues/1847 struct ScriptsFilter; impl CollectionFilter for ScriptsFilter { - fn filter(&self, elem: &JS<Element>, _root: &JS<Node>) -> bool { - elem.get().local_name == ~"script" + fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { + elem.deref().local_name == ~"script" } } let filter = ~ScriptsFilter; - HTMLCollection::create(&self.window, &NodeCast::from(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(self), filter) } - pub fn Anchors(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { + fn Anchors(&self) -> Temporary<HTMLCollection> { + let window = self.window.root(); + // FIXME: https://github.com/mozilla/servo/issues/1847 struct AnchorsFilter; impl CollectionFilter for AnchorsFilter { - fn filter(&self, elem: &JS<Element>, _root: &JS<Node>) -> bool { - elem.get().local_name == ~"a" && elem.get_attribute(Null, "name").is_some() + fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { + elem.deref().local_name == ~"a" && elem.get_attribute(Null, "name").is_some() } } let filter = ~AnchorsFilter; - HTMLCollection::create(&self.window, &NodeCast::from(abstract_self), filter) + HTMLCollection::create(&*window, NodeCast::from_ref(self), filter) } - pub fn Applets(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { + fn Applets(&self) -> Temporary<HTMLCollection> { + let window = self.window.root(); + // FIXME: This should be return OBJECT elements containing applets. struct AppletsFilter; impl CollectionFilter for AppletsFilter { - fn filter(&self, elem: &JS<Element>, _root: &JS<Node>) -> bool { - elem.get().local_name == ~"applet" + fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool { + elem.deref().local_name == ~"applet" } } let filter = ~AppletsFilter; - HTMLCollection::create(&self.window, &NodeCast::from(abstract_self), filter) - } - - pub fn Location(&mut self, abstract_self: &JS<Document>) -> JS<Location> { - self.window.get_mut().Location(&abstract_self.get().window) - } - - pub fn Children(&self, abstract_self: &JS<Document>) -> JS<HTMLCollection> { - let doc = self.node.owner_doc(); - let doc = doc.get(); - HTMLCollection::children(&doc.window, &NodeCast::from(abstract_self)) - } - - pub fn createNodeList(&self, callback: |node: &JS<Node>| -> bool) -> JS<NodeList> { - let mut nodes = vec!(); - match self.GetDocumentElement() { - None => {}, - Some(root) => { - let root: JS<Node> = NodeCast::from(&root); - for child in root.traverse_preorder() { - if callback(&child) { - nodes.push(child.clone()); - } - } - } - } - - NodeList::new_simple_list(&self.window, nodes) - } - - pub fn content_changed(&self) { - self.damage_and_reflow(ContentChangedDocumentDamage); - } - - pub fn damage_and_reflow(&self, damage: DocumentDamageLevel) { - self.window.get().damage_and_reflow(damage); - } - - pub fn wait_until_safe_to_modify_dom(&self) { - self.window.get().wait_until_safe_to_modify_dom(); + HTMLCollection::create(&*window, NodeCast::from_ref(self), filter) } - - /// Remove any existing association between the provided id and any elements in this document. - pub fn unregister_named_element(&mut self, - abstract_self: &JS<Element>, - id: DOMString) { - let mut is_empty = false; - match self.idmap.find_mut(&id) { - None => {}, - Some(elements) => { - let position = elements.iter() - .position(|element| element == abstract_self) - .expect("This element should be in registered."); - elements.remove(position); - is_empty = elements.is_empty(); - } - } - if is_empty { - self.idmap.remove(&id); - } + fn Location(&mut self) -> Temporary<Location> { + let mut window = self.window.root(); + window.Location() } - /// Associate an element present in this document with the provided id. - pub fn register_named_element(&mut self, - element: &JS<Element>, - id: DOMString) { - assert!({ - let node: JS<Node> = NodeCast::from(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."); - match self.idmap.find_mut(&id) { - Some(elements) => { - let new_node = NodeCast::from(element); - let mut head : uint = 0u; - let root: JS<Node> = NodeCast::from(&root); - for node in root.traverse_preorder() { - match ElementCast::to(&node) { - Some(elem) => { - if elements.get(head) == &elem { - head = head + 1; - } - if new_node == node || head == elements.len() { - break; - } - } - None => {} - } - } - elements.insert(head, element.clone()); - return; - }, - None => (), - } - self.idmap.insert(id, vec!(element.clone())); + fn Children(&self) -> Temporary<HTMLCollection> { + let window = self.window.root(); + HTMLCollection::children(&*window, NodeCast::from_ref(self)) } } |