aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom/document.rs
diff options
context:
space:
mode:
authorbors-servo <release+servo@mozilla.com>2014-05-03 14:25:22 -0400
committerbors-servo <release+servo@mozilla.com>2014-05-03 14:25:22 -0400
commit731e66ff132e41cdc49bc5324c0e15be19c46ec2 (patch)
treeccce9b42e8a6c54245e53620082efe0b9840eae1 /src/components/script/dom/document.rs
parent4051a8096d7ba7e7f9c86e76d0b4bffd83e85805 (diff)
parent91278da9dd55582401154e07f9eea34425a332c2 (diff)
downloadservo-731e66ff132e41cdc49bc5324c0e15be19c46ec2.tar.gz
servo-731e66ff132e41cdc49bc5324c0e15be19c46ec2.zip
auto merge of #2101 : jdm/servo/newroot_rebase, r=Ms2ger
As described in #1764, this strategy uses the following properties: * DOM members are `JS<T>` types. These cannot be used with being explicitly rooted, but they are required for compiler-derived trace hooks. * Methods that take DOM type arguments receive `&[mut] JSRef<T>`. These are rooted value references that are cloneable but cannot escape. * Methods that return DOM values use `Unrooted<T>`. These are values that may or may not be rooted elsewhere, but callers must root them in order to interact with them in any way. One unsoundness hole exists - `Unrooted` values must be rooted ASAP, or there exists the danger that JSAPI calls could be made that could cause the underlying JS value to be GCed. * All methods are implemented on `JSRef<T>`, enforcing the requirement that all DOM values are rooted for the duration of a method call (with a few exceptions for layout-related code, which cannot root values and therefore interacts with `JS<T>` and `&T` values - this is safe under the assumption that layout code interacts with DOM nodes that are in the tree, therefore rooted, and does not run concurrently with content code)
Diffstat (limited to 'src/components/script/dom/document.rs')
-rw-r--r--src/components/script/dom/document.rs634
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))
}
}